Skip to content

Polish the living document flow - #457

Open
MaggieAppleton wants to merge 7 commits into
living-spikesfrom
living-design-review
Open

MaggieAppleton wants to merge 7 commits into
living-spikesfrom
living-design-review

Conversation

@MaggieAppleton

@MaggieAppleton MaggieAppleton commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A design pass over the living document flow (spikes → Build plan → first build → In sync / Out of sync), done on the real "Margin — living document", with route interception for the other states.

Top findings → what changed

  1. Expanded rows read as machine output. A sync-added task expanded to "Committed on https://github.com/…/pull/6." and "Reflects the document change since revision 452.", while the agent's own report of what it did was never shown. Now a finished task shows its summary instead of its acceptance criteria, and sync tasks get readable criteria ("Updates pull request Test the frontend with a browser, and run it on every push #6.").
  2. A Planner draft duplicated a living document's tasks (bug). Any "update the tasks" turn, including Build's automatic draft, added the unbuilt draft to live.tasks, so the real document went from 8 to 14 rows with duplicate keys. Now liveSnapshot lists only versions that ran (regression test added).
  3. Two vocabularies for one loop. In sync / Out of sync, then "Building…". A failed sync was only distinguishable on hover, and In sync had no explanation. Now the loop reads In sync → Out of sync → Syncing…, plus Sync failed, with a tooltip for every state.
  4. The Build headline repeated the header and led with a label. "Living document · In sync · 2 commits since first build" was all one weight. Now it uses the header's icon and label, with a tertiary detail (✓ In sync · 2 commits since first build, ○ Out of sync · Waiting for @x's agent).
  5. Sync-added tasks blended into the original plan. Now they sit in a quiet Since first build section.
  6. Mobile: the header slot straddled the page's corner, and PR capsules overflowed the list (bugs). Now the slot sits in the top inset at the trailing edge, and the task grid uses minmax(0, 1fr).
  7. A failed first build vanished silently (reason only in a tooltip and an sr-only alert). Now the slot reads Retry build with a warning dot.
  8. Spike callouts were wordy and buried the decision. Now they read "Prototype queued" / "Prototyping…" with shorter @handle copy, and a report leads with the recommendation, then findings, then screenshots.

Recommended but not in this PR: hide the header slot while Build is open; list a sync's commits under the task it added; a collapsible result callout; a cancel control on the callout instead of "Delete this callout to cancel"; a label other than "Building…" for a first build that is still queued.

Screenshots

Build view, live and in sync (1440): before / after
Before: live Build view with raw acceptance criteria
After: live Build view with summaries and a Since first build section

Build plan in the narrow layout (390): before / after
Before: Build plan on the page corner at 390px
After: Build plan in the top-right inset at 390px

Out of sync in the narrow layout (390): before / after
Before: Out of sync at 390px
After: Out of sync at 390px

Header slot: sync failed and syncing: before / after
Before: failed sync reads Out of sync
After: failed sync reads Sync failed
Before: a sync in progress reads Building
After: a sync in progress reads Syncing
After: In sync explains itself on hover

Testing

  • bun run types, bun test (4551 pass with the untracked design jigs moved aside), bun run ci, bun run build. The initial chunk is unchanged at 80,590 B gzip; all new code is in the room chunk.
  • New and updated unit tests: syncLabel, syncTooltip, liveTaskGroups and the hint copy in build-model.test.ts; spike callout copy and report order in spikes.test.ts; draft exclusion and sync-task acceptance in routes.test.ts. The draft test fails without the fix.
  • Checked by hand against the real living document (LIVE_BUILD=on LIVE_SPIKES=on), using route-intercepted snapshots for the out-of-sync, failed and syncing states at 1440 and 390px. Chopin has no dark theme, so there was nothing to check there.
  • Not checked visually: "Retry build" (reaching it needs a real failed draft), and the new spike copy on a live callout (existing callouts keep their text until their state changes).
  • Verified end to end (second run, 10 Oct) with copilot --acp --allow-all on github.com/MaggieAppleton/margin: the first build of 8 tasks opened margin PRs Let the planner reach for a diagram or a formula #7 to #14, and the live edit "Snooze 15 -> 5" went Out of sync, then Syncing... (+44s), then In sync (+92s) as commit a1f2f553 on the existing PR Add type scale tokens, replace arbitrary font sizes #12. It is listed under "Since first build".

Stack

Stacked on #454 (living-spikes), the top of #450 → #451 → #452 → #453 → #454. This repository merges rebase-only: after a lower PR lands, rebase and push with --force-with-lease.

🤖 Generated with Claude Code

Second pass

This pass reviewed the new states end to end: waiting on a decision, queued, needs attention, out of sync with blocked tasks, cancel build, and no-change syncs. The full critique is in /tmp/living-design-review/critique-2.md. The after-screens were rendered on a local fake-GitHub server with intercepted snapshots.

Finding Change
At 390px, a blocker that contains a URL pushed the Build view past the card edge Status line, task detail and no-change rows wrap long words (overflow-wrap: anywhere)
"Needs attention" printed the full blocker in the status line and again in the row The status line says what to do (“X” is blocked. Edit the document to retry.); the row shows the reason; the tooltip caps it at about 120 characters
The unfinished task kept a hollow queued ring and stayed collapsed An outstanding task shows the warning dot and starts open until a sync picks it up
The slot repeated the view you were in (Queued above Queued, Waiting on a decision above Decisions) The slot hides while the view it opens is showing; "Build plan" stays because it's an action
A hollow ring meant a queued task, Queued, Out of sync and Waiting on a decision Rings are for task states only; the slot and status line use a clock for waiting, the decision glyph for a decision, and the warning dot for attention
"Queued · … 0m" A queued build shows no timer
"Your edits will sync shortly · will also retry 1 blocked task" One clause: "Your edits and 1 blocked task will sync shortly" (and matching waiting or failed copy)
No-change rows had no glyph and a time centred against long text A tertiary check in the dot column; the time sits on the first line

Not changed (recommended): agent prose is long (it needs a server-side summary and details split); a stale task survives a no-change sync; spike callouts still say "Delete this callout to cancel".

Blocker at 390px

Before: long blocker overflows the Build view at 390px
After: blocker wraps, short status line, slot hidden in Build

Needs attention at 1440px

Before: blocker printed twice
After: brief status line, reason once in the row

Unfinished task

Before: unfinished task looks queued
After: unfinished task shows the warning dot and opens

Queued

Before: Queued with 0m timer and duplicate slot
After: clock glyph, no timer, no duplicate slot

Waiting on a decision

Before: slot above the Decisions view at 390px
After: slot hidden in Decisions at 390px
After: decision glyph in the slot at 1440px

Out of sync

Before: hollow ring for out of sync at 390px
After: clock glyph for out of sync at 390px

No code change rows

Before: no-change rows without a glyph
After: no-change rows with a check and first-line time

Final pass

  • Unfinished rows say why: the agent's last report, else where it stopped. The headline names the task an edit retries.
  • Blockers drop stacked "Blocked:" labels. GitHub links show as owner/repo#N, and the row links them.
  • The warning dot shares the reason's --color-warning family. Wrapped tooltips are left-aligned.
  • Decisions shows "Answering these starts the build." while a one-click build waits on them.
  • The Build headline lines up with the task titles at both widths.

Before: unfinished task with no reason
After: unfinished task says where the agent stopped
Before: centred tooltip with stacked labels and a raw URL
After: left-aligned tooltip with a shortened link
After: Decisions explains that answering starts the build

Last pass

A real run on margin confirmed the spike lands before a queued build starts. Its result reached the first build, and no rebuild followed the callout. Two rough edges remained:

  • The first build no longer flashes "Syncing…" in its last seconds. It keeps "Building…" until it ends. "Syncing…" now only means a rebuild after an edit.
  • A one-click build started during a spike no longer adds a task that prototypes the same passage again. The implementing task follows the spike's result.

Before: first build ends showing Syncing…
After: first build keeps Building… until it ends
Before: tasks include a second prototype of the spiked passage
After: tasks follow the spike's result

@MaggieAppleton
MaggieAppleton added this pull request to stack #455 October 10, 2026 12:49
@MaggieAppleton
MaggieAppleton marked this pull request as ready for review October 10, 2026 12:50
@coolify-githubnext-app

coolify-githubnext-app Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

The preview deployment for chopin failed. 🔴

Open Build Logs | Open Application Logs

Last updated at: 2026-10-10 20:16:32 CET

@MaggieAppleton
MaggieAppleton force-pushed the living-design-review branch 3 times, most recently from e954b31 to f544612 Compare October 10, 2026 21:38
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
MaggieAppleton and others added 5 commits October 10, 2026 23:22
Give the living document one sync vocabulary (In sync, Out of sync,
Syncing…, Sync failed) with a tooltip for every state, and make the Build
headline match it. Finished tasks show what they did instead of
boilerplate acceptance criteria. Tasks added by later syncs get their own
"Since first build" section, and an unbuilt Planner draft no longer adds
duplicate rows. The header slot sits correctly on narrow layouts, a
failed first build stays visible, and spike callouts lead with the
recommendation in shorter copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ving document flow

The header reads "Waiting on a decision" while a one-click build waits and
opens Decisions, and "Needs attention" when an in-sync document still has
blocked tasks. Syncs that needed no code change appear quietly under
"Since first build". On narrow layouts the header slot keeps the page
behind it so it no longer floats over scrolled text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At narrow widths the build slot floated over the top of the document and
covered scrolled prose. It now takes its own row above the document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hide the build slot while the view it opens is showing; the view's status
  line already says the same thing.
- Use one glyph vocabulary: clock for waiting (queued, out of sync), the
  decision glyph for a pending decision, warning dot for attention; hollow
  rings stay task states only.
- Keep the blocker out of the Needs attention status line (the blocked row
  shows it) and cap it in the tooltip; mark a task the first build left
  unfinished with the warning dot and open it.
- Drop the elapsed timer from a queued build, write the blocked-task retry
  as one clause, give no-change rows a check and a first-line timestamp,
  and wrap long agent text instead of widening the page at 390px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An unfinished task's row now gives the agent's last report, or where it
stopped, and the headline names the task an edit retries. Blockers drop
stacked "Blocked:" labels and show GitHub links as owner/repo#N, linked in
the row. The warning dot shares the reason's warning family, wrapped
tooltips read left-aligned, Decisions says when answering starts a waiting
build, and the Build headline lines up with the task titles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…running spike

The header slot flashed "Syncing…" for the last seconds of a first build, after
it delivered but before its agent exited; it now keeps "Building…" until the
build ends. A one-click build drafted while a spike runs added a task that
prototyped the same passage again; the Planner now leaves that to the spike and
has the implementing task follow its result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant