Skip to content

The Board becomes a document workspace - #6

Merged
cailmdaley merged 112 commits into
mainfrom
design/document-workspace
Oct 5, 2026
Merged

cailmdaley merged 112 commits into
mainfrom
design/document-workspace

Conversation

@cailmdaley

Copy link
Copy Markdown
Owner

The Board becomes a document workspace, and every way of opening a fiber leads into it.

  • The Board is now an overview of the fleet's work: a row of the latest receipts, then each fiber that has documents as a folio with a live thumbnail of its lead document. Folios group by recent work, project or host, and you can search them.
  • The reader opens when you click a Desk card, a folio, a receipt or a wikilink. It lays one fiber's documents out as a filmstrip modelled on Television: the fiber's own page first, then its other documents. One page is selected, its neighbours are receded and inert, a crossing takes 280 ms, and selecting a page never reloads a document. The reader floats on a vellum veil over the live Desk.
  • The card's controls live at the top of the fiber's own page: the worker pill, the composer, Meeting, settings, history, and Temper/Discard. The navbar's worker pill opens the real conversation, as the Desk card's pill does.
  • Desk ordering is explicit. Every column ends in an identity tie-break, and In flight splits into Needs you and Working.

Design authority, decisions and the review are in the felt constitution ai-futures/felt/constitutions/document-workspace (design.md, review-findings.md).

What changes for a person using the board

  • Documents:
    • Each document appears once per fiber, keyed by owner plus normalized absolute path, with every send kept as a receipt.
    • Tab labels disambiguate colliding names.
    • Audio, video, PDF, image, HTML, markdown and text each have one renderer, shared by reader pages and overview thumbnails; other kinds offer a download.
    • Media keeps its playback state across selection and parking, pauses when its page recedes, and only one thing plays at a time.
  • Keyboard: one keymap module drives the Desk, the overview and the reader, and the ? overlay lists it.
    • The Desk and overview move spatially with hjkl or the arrows. The first keypress on the Desk selects the top of Awaiting review.
    • In the reader, h/l step tabs, j/k step constitutions, ↑/↓ scroll, c toggles the Constitutions sidebar and / searches.
    • HTML reports forward keys through a small bridge only when they didn't handle the key themselves.
  • Phone: the overview is a single column, the reader shows one document full-width with a bottom bar of ‹ n/N ›, and browser Back works throughout.
  • Theme: the workspace takes the Desk's pigments and materials as shared --kbn-* tokens, and every --ws-* colour derives from them.
  • Removed: FiberDetailModal and its floating window chrome, LinkedFiberPanel, the Shelf canvas (ShelfView, ShelfReader and their layout code), ReaderZoom, and sheet history.

Daemon

  • GET /file serves byte ranges (Range, If-Range, 206/416).
  • Files over 1 MiB get a cheap metadata ETag, are streamed rather than read whole, and have open-ended ranges capped at 4 MiB.
  • HEAD sends no body, and a remote HEAD is a true upstream HEAD.
  • Relays to owner hosts bound open, closed and suffix ranges to 4 MiB and relay at most 64 KiB of an error body.

Remote full-GET fallbacks still buffer within the existing 30 s timeout.

Verification

Gates on the final head (observed):

  • make test: Go suite, ExUnit, the UI suite under both pinned time zones, plugin hooks and bootstrap all pass.
  • make build SKIP_CLI=1 passes.
  • cd ui && npm run e2e: 24/24 browser checks pass. The suite drives the board harness with playwright-core and system Chrome. It covers Desk keys, card → reader, stepping, expand and resize, the inline controls, the worker pill, wikilinks to non-card fibers, the overview, real audio and video playback, PDF, and the phone layout. It asserts document identity (no reloads) and that no page errors occur.

Live real-data checks ran through vite against the dapmcw68 daemon, using documents owned by candide, cineca and amundsen, at 1440×900 and 390×844. An independent Opus review covered the daemon, data safety, entry points, security and dead code. All of its must-fix and fix-soon items have regression tests that fail before the fix.

Known follow-ups

  • HTML reports render as same-origin srcdoc, as they did on main. Sandboxing them means porting scrolling, scroll restore and media binding to the bridge.
  • Reloading a channel opened from the Desk lands on the Board view.
  • A visual design pass is next: depth and parallax, the Desk column sliding out as the sidebar, thumbnail tabs with recency order, per-constitution themes, and the audio page.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LQP1nDgXogDRnyMZNK3hoY

cailmdaley and others added 30 commits October 5, 2026 00:29
Order by durable creation or completion keys with uid, origin and id ties. Keep Resting warmth and return groups, and choose mirrored survivors deterministically without collapsing unrelated host-local paths.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Expose the In flight ordering seam without adding independent scrollers. Stage both bands in the offline harness and verify grouping, stable positions, queue peeks and row-to-card drops through both wrapped bands.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Inactive previews share one initial read but never poll on the periodic clock. Parked previews cancel that read; returning unfinished previews can retry once without activating a subscription. Workspace chords exclude Shift-Alt arrows.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Watchers signal per-subscriber recovery independently of changed bytes. HTML and text readers report readiness without repainting a retained document after a 304 or identical 200.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Install the window-bubble bridge after report load handlers.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Route owner-addressed channels through a retained filmstrip stage, keep Desk layout and focus available on return, and isolate Conversation in the existing control surface. Cover loading, navigation, body links, stable controls and CSS token contracts in integration tests.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
…me size

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Keep live document frames attached while the stage narrows, route refused launches into the channel recovery form, and give phone sheets one Back entry.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Overview implementation and label workers have final tests and commits pending; phone and scroll restoration verification remain open.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
The dock lives as long as the board, as the inspector did, so meeting,
transition and worker-phase collaborators stay where they are and the
board's polls repaint its worker pill directly. Phone sheets trap Tab and
make the stage inert; body reads keep the live worker fields of the
composite feed. Behaviour tests for the composer, images, start prompt,
requeue, worker pill, meeting and settings writes now exercise the dock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A candidate displaces only a live body of strictly lower priority (on
screen > in the ring > elsewhere), so a dense sheet no longer trades
iframes back and forth on every load; the churn crashed the browser on
the live fleet sheet. The lens becomes a radio group in the Desk's tab
register, the heading carries the illuminated initial, and host marks
extend to eight shapes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared material tokens (parchment, sheet, plate, card paper, ochre rule,
iron gall at four strengths) join the pigments on :root and the Desk
reads them; every --ws-* colour derives from them. Chrome and metadata
take the Desk's mono register, names and prose the serif, cobalt marks
only the machine, gold only fresh or waiting, and keyboard focus wears
the Desk's dashed rule. The drafting grid stays as the workspace's own
note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sidebar lists the overview's rows on a column sheet with its own
find, opens by default at 1280px and wider, and remembers an explicit
choice from the navbar control or Cmd-backslash. The tab strip centres
over the stage beside it. A channel entered directly reads the overview
so the rows exist, and folios placed before the board's metadata arrived
take their names and groups from it once it does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Back and Forward through #/desk, #/chronicle and #/board switch the
board's view. The view keys work from the reader, so 1 parks a channel
opened from the Board and 3 returns to it; only channels entered from the
Board are remembered as the Board's place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cailmdaley and others added 28 commits October 5, 2026 04:34
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Preserve the document workspace control band and carry startup-rejection handling into Dock.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 2: reconcile by owner and uid through Workspace.update, preserving the composer and retargeting worker actions.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 3: re-seed agent, kind, cron, date and parent baselines without replacing drafts or focused controls.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 6: sessionless 409 holds only until the next changed worker observation.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 7: preserve message-less Desk drag intent unless the parked composer changes; consume only a composed successful message.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Use metadata validators above one MiB, file-backed large responses, bodyless HEAD handling, and four-MiB open-ended ranges.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Distinguish malformed ranges from valid ranges outside the representation; preserve 416 for unsatisfiable open-ended and suffix requests.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 8: keep the fold state and toggle focus while refreshing the ledger and current owner attach targets.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 9: one queue per band, changed-axis writes, last-intent reversal and selective failure rollback; successful parent writes retarget queued edits before polling.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Shorten valid single remote ranges to four MiB before GET, relay at most 64 KiB of an error body after receipt, and route HEAD through the existing secure httpc setup. Full GET and If-Range 200 fallbacks retain buffering and the 30-second timeout.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 1 is fixed in the baseline; new regressions cover fresh, resume, Start retry and Desk drag. Observed all four fail with the status arguments temporarily removed, then pass after restoring them.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Review item 14 Dock subset: field swallow callbacks are reachable, so preserve isolation with one band-root listener instead of passing a helper through every builder. Workspace owns runtime updates for identity-keyed bands.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
Co-Authored-By: GPT-6 Luna <noreply@openai.com>
@cailmdaley
cailmdaley merged commit 18c8f6d into main Oct 5, 2026
4 checks passed
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