diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 23eeab2a7..9e86dea83 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -5177,3 +5177,7 @@ Before: managed project/thread verbs had no Console conversation area. After: fi 2026-10-21T01:28:05Z | Darkwing | row 232 #1734 installer I1 build, round 1 in review | Before: stack-release.sh managed only user units (systemctl --user), and stack-copy.sh had no bundle copy. After: --units external (adopt, activate, rollback --to, status, confirm, revert, gate --since, AWAITING-UNITS, stale-start, external-pm, --plan --expect-from) and stack-copy check --units external, copy --bundle FILE SHA, wrapper ID --create; user mode byte-identical to the base by test. First build 0af0c73c6 on 00d4cc1f6; rebased onto row 200 (cb5fdb064) as a0ffabc3f on darkwing/row232-r1; --sso refused under external (D9), row 200 config_checks run under external (D10). Gate on Sage's slot (sage-1618): cli 561/0, every scripts/test-*.sh green; 17/17 mutants killed. Results commit 84f1a91e6 (pushed, seat branch only). Manifest 7a3b4ea1 (9 paths), queue revs 2595-2596, request comment 29825, reviewer Filbert. Packet agents/darkwing/work/queue-232/BUILD.md. 2026-10-21T04:50:44Z | Darkwing | row 233 #1735 installer I3 build, round 1 in review | Before: root had no upgrade driver for root-owned units and no host run sheet; stack-release.sh had no rehearse --backup last and no external plan refusals. After: scripts/stack-upgrade.sh upgrade and rollback (r6 A1-A5, A2f, R1-R4) with 20 tests, docs/guides/host-run-sheet.md, TOOLS.md lines, and on Sage's rulings stack-release.sh --backup last, BACKUP_STORE and the --plan refusals open-activation and migrate-required (3 tests). Base e65a3ab4d (row 232's landing). Gate on Sage's slot (sage-1704) on d99166ade: cli 616/0, every scripts/test-*.sh green, 1201/0 summed by awk; m1-m8 8/8 killed. Correction: the process sweep after the gate found an orphaned sleep 60 from the lock test's flock holder (N1); 08db6ac3f fixes it test only, Sage ruled the gate stands (sage-1707), rerun c0 20/0 and m1 killed with 0 left (sage-1708). Tip 1a1dc80ca (pushed, seat branch only). Manifest 464ce9eb (7 paths), queue revs 2644 and 2647, request comment 29901, reviewer Filbert. Packet agents/darkwing/work/queue-233/BUILD.md. 2026-10-21T06:37:41Z | Darkwing | row 240 #1746 installer I4 build, round 1 in review | Before: root had no host check for the bwrap AppArmor profile, its pins or a boot unit, and stack-upgrade.sh exited 1 args-failed when the args move after A5 failed, while exit 1 means the old copy runs. After: scripts/case1-hostcheck.sh (seven items, --check, --enforce, --upstream), scripts/case1-pins.sh, mosaic-hostcheck.service and 16 tests; the args move failure exits 5 args-failed, documented in TOOLS.md and run sheet section 6 and tested; run sheet section 3 puts the pinned npm on PATH and names the bin/claude.exe --claude path; sections 8 and 10 have precheck lines. Verification: slot run r1 on 47ec9fe2f failed at the singles (the new N1 test's after hook threw ENOENT after the fixture cleanup removed the root); b45852daa drops the hook; r2 on b45852daa green: singles 16/0 and 21/0, c0 plus M1-M8 8/8 killed, cli 639/0, scripts 585/0. Candidate darkwing/row240-r3 ad1b23ab2 on c771a36f4, manifest 573ece95 (9 paths), revs 2694 and 2695, comment 29943. + +2026-10-21T16:04:23Z | Q195/Q196 writing editor design, #1752 / Vikunja #448 | Before: row 154 edits Markdown in a separate Docs view, with no selected-word thesaurus or document pins. After: design draft on gyro/editor-design compares three editor approaches, records WordNet source/license/size, folds the pane/pin model and specifies guarded context/proposal APIs, DesignCraft handoff and seven proposed briefs. Q196 changes the basis to a Word-like interface. Verification so far: editor/provenance checks 10 pass, 1 explicit rebuild skip (pinned esbuild absent); brief fields, unique headings and 11-line checklist checked. Product, queue and live state unchanged. WordCraft scratch evaluation is being incorporated before publication. Review and Jason choices remain open. + +2026-10-21T16:22:36Z | Q195/Q196 design verification, #1752 / Vikunja #448 | Folded Fenton 7caf8008b and Louie 880ef19e0. Recommend bounded O3: Word-like DOM editor plus isolated headless DOCX export, with explicit feature cut and semantic loss checks. WordCraft web 44,179,239 bytes, identical twice; measured comment/footnote conversion limits recorded. Seven briefs and 12-line checklist validated. Fresh editor/provenance: 10 pass, 0 fail, 1 explicit rebuild skip (esbuild 0.28.2 absent). CI queue guard identity gyro/purpose push returned documented degraded-pass (exit 0), CANNOT_ASSERT credential-unresolvable, scratch audit gyro-q195-ci-queue-audit.jsonl; no fallback or CI-green claim. Documentation-only candidate for Mos/Fenton review, no source, queue or live changes. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 222cc14c1..27f4c430f 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -1419,3 +1419,5 @@ are never rewritten or removed; corrections are new entries. 2026-10-21T06:47:54Z | researcher | row 228 (#1729) round 3 in review (rev 2702; start rev 2700) | rebase of r2 onto the 234 landing c771a36f4 as researcher/row228-r3 cf18c42b9 (one commit, pushed) with Webby's round 2 N1 (:711 and :718); manifest 82cf98c6 (3 files); slot sage-1796: session.test 13 + host.test 42 = 55/0, manifest OK before and after, busy228.sh copy named in the clear; r2 94/0 and M1 killed stand (seat blobs unchanged); request attempt left in requesting state (lock held by sage-238-review-2b when the outcome rev was written, exit 3; transport said failed pre-send, no token), Sage resolves and posts as jarvis; packet agents/researcher/work/queue-228/r3 2026-10-21T07:29:23Z | researcher | row 228 (#1729) landed as 86249ac55 (pushed 07:25Z by Sage) | patch-id b6ffe31feb0d matches my r3 candidate cf18c42b9 (checked here against origin/refactor); Sage combined gate with 238: seat 165/0, cli 640/0, scripts 585/0; queue note rev 2725, done rev 2727, #1729 closed comment 29966 (sage-1824); q228r2 worktree removed, branches researcher/row228, -r2 and -r3 stay on origin and locally; packets agents/researcher/work/queue-228 r1 r2 r3 uncommitted 2026-10-21T15:19:14Z | Sage (Opus 5.5, 1ef1e4f8) | MVP push 10-21 afternoon: rows 249, 197 proof 3/4, 222 singles, 66 r4d, queue-commit | 249 landed 9de5a57ab (+7b9737953 DEFERRED N1, #1751 closed, Vikunja 445 c442); 197 proof 3 rc=1 on a driver defect, Herb's fix a5b636750 to Webby, proof 4 set up in sage-r197p4; 222 singles 34/34 and 5 mutants killed (sage-2028); 66 round 4 in review (82c830779, c30083/30084); queue revs 2642-2904 committed 0636721e6 + +2026-10-21T16:04:23Z | Gyro (T3 Codex gpt-6.1-sol) | Q195/Q196 design only, #1752 / Vikunja #448, gyro/editor-design | Code-measured writing-editor draft with three options, local thesaurus, pane/pins, guarded API/MCP, DesignCraft handoff and proposed briefs; queue next refused linked worktree, canonical next gyro returned nothing; no implementation or live actions. diff --git a/docs/plans/2026-10-21_q195-writing-editor.md b/docs/plans/2026-10-21_q195-writing-editor.md new file mode 100644 index 000000000..73af163e4 --- /dev/null +++ b/docs/plans/2026-10-21_q195-writing-editor.md @@ -0,0 +1,803 @@ +# Q195 writing editor design + +Gitea #1752, Vikunja #448, DECISIONS Q168, Q177, Q194, Q195 and Q196. Design for review, not build +authority. Measured against `origin/refactor` at `6c75887b0`. All repository line references below +use that commit unless a different revision is named. Work is confined to `gyro/editor-design`. + +## Outcome and boundaries + +D1. Give Melanie a familiar Word-like writing interface inside the Console. She writes, saves, +selects a word for synonyms, and moves between documents without losing her draft or chat. Her +corpus includes hundreds of .doc files, several .qxd books and recent Markdown. Obsidian is not the +interface model. Ship a useful writing slice before legacy import. This add-on does not gate the +October 27 Markdown-library MVP, which Q196 leaves unchanged. + +D2. Q196 withdraws the earlier assumption that the current Markdown editor must be the solution. +Compare all three options below. WordCraft's canvas/WebGPU browser UI +(`apps/wordcraft-web/Cargo.toml:3,26`, `index.html:17`) has a different rendering and build system. +Read-only reference checkout: `/mnt/storage/src/artcraft/wordcraft`, commit +`e05b7fe86f3b85454000dffc321de638d7009817`. No code is copied by this design. Any later copy must +preserve its applicable MIT or Apache-2.0 license and notices. + +D3. No direct agent writes. Proposals appear outside the document until Melanie accepts one, then +become an undoable draft edit. Saving remains a separate human action. Q176 and Case 2 C2-06 already +prohibit agent prose and constrain corrections. Q195 does not explicitly remove that rule. The +design below specifies the interface, but agent access to unsaved text and new replacement-prose +permissions remain gated on Jason's choices, not silently enabled. + +All examples and tests use invented fixtures. No books content, host access, live stack changes, +role changes, queue changes or access to `~/.mosaic-dev` is part of this assignment. + +## What exists + +| Code | Measured finding and implication | +|---|---| +| F1 | Row 154 landed as `9353675d1` (#1648). `packages/webui/editor/model.mjs:16-18` imports ProseMirror and markdown-it. `view.mjs:162` mounts the DOM editor with history, formatting, lists and a link bar. `model.mjs:1-14` and the serializer retain original blocks unless edited. Front matter and unsupported structures remain source blocks. This is the implementation to extend. | +| F2 | The actual vendor path is `packages/webui/third_party/editor/`, relative to the WebUI package, not repository-root `third_party/editor/`. `PROVENANCE.json:1-13` records 170 files, 19 packages and no local changes. `NOTICE:1-10` names tagged source, hashes and license paths. `editor/build.mjs:16-24,34-56` aliases source and produces an unminified bundle with inline legal notices and hashes. `editor/BUILD.json:7-14` records 758,420 JS bytes and 4,462 CSS bytes. These are checked against bytes, not inferred from the README. | +| F3 | `packages/webui/src/public/bus.js:868-887,925-927` keeps a shared Markdown draft and falls back to Source when exact round-trip fails. Redrawing destroys the editor. `editor/view.mjs:183-205` creates a new history on `setText`. The README's “Visual editor” section (`packages/webui/README.md:563`) records this limit. A writer needs a stable editor mount while chat polls. | +| F4 | Row 148's save is `POST /api/project-file`, with exactly `{project,path,base,content}` (`bus.js:975-986`, `serve.mjs:414-447`). Authentication, exact Origin, Fetch Metadata, strict keys and a 1 MiB request bound apply. `packages/project/src/index.mjs:244-260` restricts it to a human and refuses a changed file base. `paths.mjs:12-15` allows only `spec/north-star.md` and direct `docs/*.md`. This route cannot save book paths today. Do not widen its regexp to admit the vault. | +| F5 | The Console already has chat projects, named threads, message paging, send and explicit resume (`packages/webui/src/chat.mjs:19-27`, `public/chat.js:9-14,66-70`). Chat has its own route and render lifecycle (`public/bus.js:1100-1104`), so Docs and Chat currently replace each other. `chat.js:68` renders bodies as escaped text. There is no document pin in these structures. | +| F6 | Sessions are durable thread identity plus replaceable runs. Row 121 landed as `2c16d6b93` (#1615). `packages/bus/src/broker.mjs:479-525` tracks pending work, holder and idle release. `:3429-3451` creates an owned thread, and `:3468-3474` requests launch only on explicit open. Reuse thread IDs, never run IDs, for pins. Existing tester isolation is in rows 177/182 and `chat.mjs:1-4`. | +| F7 | C2-11a, row 214, owns `editor/model.mjs`, bundle output and editor tests (`docs/plans/2026-10-20_case2-rows.md:235`). It measures and preserves wikilink forms. All proposed changes under `editor/` wait behind it. C2-10b owns `public/bus.js`, its stylesheet, `serve.mjs` and WebUI tests (`:780`). It supplies cited items, scope badges and sync status. Our shared-file rows wait behind it and reuse its renderer. Neither brief proves that its feature has landed. | +| F8 | Sage's input via mos-1179: row 220, C2-10a (#1721), makes the conversation reader hide creative sessions and refuse direct opens with `conversation-not-listed` (`case2-rows.md:517`). Row 198 (#1696) retires the 7331 board writer, currently referenced at `serve.mjs:12`. This design uses neither raw session files nor the board route. It does not depend on row 5 (waiting on Jason) or parked row 29. | + +Verification: `node --test packages/webui/tests/editor-provenance.test.mjs +packages/webui/tests/editor.test.mjs` passed 10 tests with 1 explicit skip. The skip is the rebuild +because pinned esbuild 0.28.2 is absent. The source tree, output hashes, licenses, route serving and +exact round-trip tests passed. This is fixture evidence, not a live check. + +## Options and recommendation under Q196 + +O1. Extend row 154 into a Word-like DOM interface. Reuse its safe source-built editor, add a +File/Home/Review ribbon, named heading/paragraph styles, a document navigation pane, familiar +shortcuts, status bar and synonyms. It preserves browser text behavior and the current CSP. The +measured JS/CSS sizes are F2, not an estimate. Its current schema has no footnote, comment or +tracked-change nodes (`editor/model.mjs:27-114`), no page layout engine and no DOCX writer. +Word-like controls do not create those features. This option needs a production export path before +it meets Q196's DesignCraft requirement. + +O2. Put WordCraft's engine and canvas interface in the document pane. It offers Word-like commands +and rich file support rather than recreating all of them in ProseMirror. Louie's scratch evaluation +is the source for build/runtime and round-trip measurements below. Its own browser file +pickers/downloads and preferences are not a Mosaic save or permission boundary. An adapter must +disable direct uncontrolled I/O, connect owned git documents, expose selection/version/undo +operations, and put all agent access through Mosaic's broker. Its native MCP server is not +automatically a browser bridge. Q167 D3 bars the required CSP loosening today. An iframe or separate +origin is not a way around that ruling. O2 requires Jason's explicit scoped exception and an +independent security review before build rows. + +O3. Keep a Word-like DOM writing interface, use WordCraft's headless formats/engine behind a narrow +server operation for production export. Recommend this bounded mix for the first release: O1 +supplies editing and local synonyms, a pinned headless exporter supplies DOCX for DesignCraft. Do +not run two live document models or send every keystroke to a server. This avoids introducing a +canvas editor and a CSP exception while adding a concrete book handoff. The cost is a reviewed +format adapter and an explicit feature boundary. It does not promise full Word parity. If footnotes, +comments, tracked changes or precise pagination must be editable in the first release, choose O2 +after its bridge and CSP gates instead of silently extending Markdown beyond what it can represent. + +The first release includes prose, headings, emphasis, lists, links, native spelling, find, word +counts, undo, explicit save and synonyms in familiar controls. True page layout, headers/footers, +rich tables, footnotes, comments and tracked changes are later rich-document work, not buttons that +discard unsupported information. Existing documents with unsupported structures remain +source-preserved or read-only with a clear reason. Jason confirms that feature cut, not an +assumption that the existing vault defines her needs. + +## WordCraft measurements used for O2 and O3 + +Louie's evaluation is pinned at `origin/louie/wordcraft-eval`, commit +`880ef19e017dad0194ecc9921ae55a0cf2e8fef2`, +`docs/plans/2026-10-21_q195-wordcraft-eval.md`. He built a scratch clone of WordCraft +`e05b7fe86f3b85454000dffc321de638d7009817` (0.9.0), with no source modifications. +These are his measured results, not estimates or a claim that this combined design ran +the application in the Console. + +| Evidence | Measured result | Design implication | +|---|---|---| +| Release build twice | 392.786 s, then 172.324 s, under `nice -n 19`, four Cargo jobs | First-build cost is material. Exact timings are that scratch host, not a product startup benchmark. | +| WASM | 43,994,316 bytes, SHA-256 `90dec375924b47b40054eb4ecafb4235b6ed0bd63880b91ec138fdbb6f939e75` | The current shipped build is much larger than the packaging README's approximate figure. Use the measured artifact. | +| JS / HTML / icon | 164,941 / 1,604 / 18,378 bytes | Total 44,179,239 bytes, identical sorted hashes for all four artifacts across both builds. No compression transfer size was measured. | +| Review scope for web target | 15 local crates, 251,457 physical Rust source lines and 199 third-party packages | O2 imports a maintained application, not a small editor widget. All dependency licenses and pinned build inputs need review. | +| Browser API | Session and selection stay in WASM. No exported page API or postMessage bridge. Browser has no TCP control channel | The native MCP server cannot control the browser document. The O2 adapter is new work. | +| `.doc` → `.docx` fixture | Heading 1, italics and footnote reference/body preserved. Comment absent, inspect reports zero comments | Useful import candidate, with a real loss boundary. Legacy import must retain the original and disclose comment loss. | +| `.doc` → `.md` fixture | Heading and italics preserved, footnote reference/body and comment absent | Markdown is not a lossless intermediate for rich legacy books. | +| `.md` → `.docx` → `.md` fixture | Heading and italics preserved. Footnote marker/definition stay ordinary text and brackets are escaped | O3's adapter must detect unsupported constructs, not rely on conversion success as proof of semantics. | +| Thesaurus | 29 headwords, 122 synonym values | WordNet is needed under every option. Hunspell spelling dictionaries are a separate mechanism. | +| MCP | 16 native tools, stdio/headless or loopback desktop connection | Reuse operation ideas through Mosaic's scoped tools. Do not expose native execute/save or a loopback control port to agents. | + +For the unmodified O2 browser app, Louie identifies `script-src 'wasm-unsafe-eval'` for +WebAssembly, `frame-src 'self' blob:` for the PDF preview, and `frame-ancestors 'self'` +on an embedded WordCraft response rather than the shell's existing `'none'`. A restricted +integration could disable PDF preview, but must demonstrate the resulting narrower policy. +The shell policy stays unchanged when only an editor response changes. Q167 D3 still +requires Jason's ruling on that editor policy. No worker/GPU-specific CSP directive is +needed for this build. + +Pane fitting is a source-based inference: eframe 0.36.2 uses ResizeObserver on the canvas. +Louie did not prove a functioning Console embedding, keyboard escape, browser startup +latency or browser selection bridge. Those remain O2 acceptance work, not measured successes. +The native fixture conversions do prove format behavior on the synthetic fixture. They do +not prove preservation of Melanie's corpus or the complete Word feature set. + +For O3, the headless format path is supported by the successful native fixture commands. +A restricted exporter service and its exact native dependency subtree, memory usage and +service latency have not been measured. W6 must measure them. O3 avoids the measured +browser WASM/app UI and a browser CSP exception, but is not claimed to be a zero-cost or +already-built backend. This is why the recommendation is limited to the tested prose, +heading/emphasis/list subset plus explicit loss checks, with richer editing as a separate +choice in Jason's checklist. + +## Stored format and DesignCraft handoff + +D20. For the recommended first slice, existing Markdown stays canonical in git, including front +matter. No forced migration. Produce DOCX as a derived, human-requested book handoff from a specific +commit. The first slice stores Markdown only in git and downloads the derived DOCX with an export +manifest. Optional storage of that output under a dedicated `exports/` directory in the writing +project requires its own accepted write-path policy brief. The manifest records source paths, source +commit/digests, converter revision, style map, output digest and conversion warnings. The Markdown +source is the sole editable copy. The DOCX is regenerated, never independently edited then merged +back. Existing Case 2 mapping does not automatically index exports or gain write permission for +them. + +Markdown-only git is easiest to inspect but cannot retain all Word features. DOCX-only git retains a +richer document model but is binary to git and outside Case 2's Markdown reader, writer and +citations. Two editable masters drift. If git later holds both, DOCX is a derived output, not +another editable format to synchronize. A later rich-document mode may make DOCX canonical per +document, with a derived Markdown reading projection and stable identity mapping, but that needs +separate writer, index, citation and loss-preservation design. It does not change this week's Case 2 +MVP. + +D21. DesignCraft checkout `3ce3a24f08d03935bc8cf7cb23755aca8065558c` lists DOCX and MD at +`docs/file-format-parity.md:69,72`. Code qualifies that claim: `crates/textimport/src/lib.rs:94-126` +recognizes `.md` but falls through to plain text. Markdown headings, emphasis and YAML are not +automatically interpreted. `crates/textimport/src/docx.rs:493-548` reads named styles and footnotes. +Its regression `tracked_changes_import_as_accepted_including_moves` at `:706` shows that +insertions/move destinations become accepted content, with deletions removed, not an editable review +history. `crates/engine/src/cmd/place_text.rs:46-93` maps style names and resolves conflicts. +`crates/engine/src/cmd/file.rs:138` documents `file.place` for DOCX/MD and +`crates/mcp/src/tools.rs:98-110` exposes typed commands through the MCP server. + +D22. `POST /api/editor/export` takes exactly `{project,path,base,format:"docx"}` under the existing +human write fences, reads the authorized saved commit and returns a bounded download containing DOCX +plus manifest. Dirty drafts must be saved first. No arbitrary server path or browser-selected +converter command is accepted. Export strips front matter into metadata, resolves source links as +text or explicit cross-reference labels and maps Normal, Title, Heading 1-3, Quote and list styles +by name. It refuses unsupported semantic content or offers an explicit loss report before export. +Jason's later layout agent fetches the reviewed Markdown commit into its own approved workspace, +produces the matching DOCX and manifest (or reads the separately authorized export commit), verifies +hashes, and uses DesignCraft MCP `execute` with `file.place`, sets an explicit style map and +`styleConflicts`, then reviews autoflow and warnings before saving a layout. That later agent +automation is not authorized by this design assignment. No editor agent gets DesignCraft credentials +or automatically sends Melanie's text to another service. + +Acceptance uses invented fixtures: body, styled headings, emphasis, list, table, link and +footnote/track-change cases appropriate to the chosen format. Compare source text and style +identities after WordCraft export and DesignCraft placement, including Unicode and paragraph +boundaries. Unsupported footnotes/revisions in Markdown must refuse or warn, not vanish. For rich +DOCX input, explicitly choose a final accepted reading before production layout, retaining the +original review-bearing file. A direct `.md` place is a plain-text fallback only, not the production +path for styled Markdown. + +D23. Legacy import is a separate assignment. It must supply stable document IDs, original hashes, a +read-only retained original, converted editable file, named styles, metadata, attachment mapping and +a loss/warning report with a human acceptance decision. It must also name the supported +format/features, source-to-output paragraph identifiers and asset paths so navigation, pins and +citations can be repaired explicitly. Never replace .doc or .qxd originals. WordCraft's `.doc` +parser is a candidate to test, not proof that every 20-year-old document survives. Neither project +reads .qxd today (DesignCraft's gap at `docs/file-format-parity.md:32`). QXD extraction needs its +own evaluated tool and license. The editor accepts only reviewed converted artifacts, not a bulk +import button. + +## Writing and moving between documents + +D4. Present a File/Open view with recent documents and a collapsible book/chapter navigation pane, +plus a heading outline. The Case 2 mapping supplies scope underneath it. Show book, folder and +document in the breadcrumb, without requiring Melanie to operate a vault UI. The host recon at +`/mnt/storage/src/jason-master-restart/projects/mosaic-mvp/MELANIE-HOST-RECON.md:23` describes +Markdown book folders, chapters, characters, summaries, locations, research and tracker notes, with +front matter keys `type`, `name`, `appears_in` and `relationships`. Only that structure is used +here. `.base` and `.canvas` stay untouched and are not offered as editable documents. + +D5. Reuse C2-11b's library navigation and human `library.file` / `library.file.save` boundary, plus +C2-02's writer and C2-03b's push behavior. They are dependencies, not work hidden in a UI row. The +Case 2 design, `origin/gosalyn/case2-design:agents/gosalyn/work/case2/DESIGN.md` section 7.3, +already assigns these. A usable book-editing release waits for their reviewed write and sync +semantics. Until then the new writing surface can be tested on `docs/` fixtures, but is not reported +as usable for Melanie's books. + +D6. Keep one working editor with a collapsible file tree, heading outline, recent documents and a +path/name filter. Opening a fixture such as `Lantern Book/Chapters/03 - Rain.md` uses the mapping's +document identity, not an absolute path. Back/forward and wikilink navigation use the same open +operation. Do not invent a second tree or a vault-wide search service. + +D7. Each document keeps its text, base commit, selection, scroll and undo history in memory for this +signed-in tab. Chat polling and divider movement never remount it. Switching back restores it. Keep +at most ten clean inactive editor states. Before releasing a dirty state, require Save, Copy or +explicit Discard. Never evict a dirty document silently. No unsaved text goes in URLs, localStorage +or logs. A dirty-document badge and an unsaved count remain visible. Closing/reloading a dirty tab +warns. Explicit sign-out clears text and access context, with an unsaved warning before it proceeds. +Expired credentials revoke agent shares and block writes/server reads, while preserving the tab's +local draft for Copy or reauthentication. The UI distinguishes expiry from an explicit sign-out. + +D8. Use Word-like File/Home/Review controls and a familiar Normal/Heading 1-3 style picker. Provide +a clean page-colored writing surface, readable line width (about 70 characters), text-size controls, +spacious line height, native spellcheck, keyboard formatting, find within the open file, word count +and a focus view. Keep the toolbar compact and keyboard accessible. Hide front matter behind a +collapsed “Document details” source panel, preserving its exact bytes. Unsupported blocks remain +marked source blocks. Do not reinterpret YAML or normalize wikilinks. All-day use means stable +selection/history and clear save status, not Word-style pagination. + +D9. Save is explicit (button and Ctrl/Cmd+S), with “Unsaved”, “Saving”, a returned commit, or a +refusal. No autosave commits initially. Newer content refuses `stale-base` and preserves the draft. +Show current saved text beside the draft for manual reconciliation, never an automatic overwrite. +Unknown save/push results are read back before retry. A local library commit awaiting push is +labelled as such, using C2-03b's result, never called synced. No create, rename, delete, promote or +crossover work enters this add-on's first slice. + +## Thesaurus + +D10. Use Princeton WordNet 3.0, indexed locally by synset (meaning) and part of speech. This is +substantially broader than WordCraft's small static `T` table +(`crates/engine/src/cmd/review.rs:914`). WordNet is a lexical database, so it will miss some +inflected or literary terms and does not rank words for a sentence. Group results by meaning, show +the gloss, omit the selected word and duplicates, and say “No local synonyms” on a miss. Do not +promise every alternative is interchangeable. + +Princeton's [statistics](https://wordnet.princeton.edu/documentation/wnstats7wn) report 117,659 +synsets and 206,941 word-sense pairs. The 155,287 strings total counts words again across parts of +speech. The distinct total is 147,278. Its +[license](https://wordnet.princeton.edu/license-and-commercial-use) permits copying, modification +and distribution for any purpose, retaining its copyright, terms and disclaimer on copies and +modifications. This fits this repository's private `UNLICENSED` package and source-review rules. Do +not label WordNet MIT or Apache. Preserve the actual WordNet license. + +Measured download on this design session: Princeton's archive host timed out. The NLTK project's +[WordNet data +mirror](https://github.com/nltk/nltk_data/blob/96f9b3252457a2b97e52aec64c3dfceeb5c312d5/packages/corpora/wordnet.zip) +at commit `96f9b3252457a2b97e52aec64c3dfceeb5c312d5` supplied the archive in memory. The archived +LICENSE is WordNet 3.0's Princeton license. No archive entered this repository. + +| Measurement | Exact value | +|---|---| +| Archive | 10,775,600 bytes | +| SHA-256 | `cbda5ea6eef7f36a97a43d4a75f85e07fccbb4f23657d27b4ccbc93e2646ab59` | +| All uncompressed entries | 36,353,991 bytes | +| `data.*`, `index.*` and exception files | 35,435,978 bytes | +| Measured synsets | noun 82,115, verb 13,767, adjective 18,156, adverb 3,621 | + +D11. At build time, import the original text, license and a provenance manifest under +`packages/webui/third_party/thesaurus/`. A small reviewed converter bakes a static index into a +self-hosted Web Worker asset, shipped with the Console build. Start that worker when the writing +surface loads. No runtime dependency install, upstream lookup, CDN, on-demand dictionary fetch or +model call occurs when she selects a word. Data is reviewable source in the release, like row 154's +editor source. Browser assets still come from the installed Console itself. CSP stays byte-for-byte +unchanged. Worker startup and index decoding stay off the typing thread. + +The build row records exact generated bytes and worker memory/load measurements rather than guessing +compression size here. Gate limits: at most 50 MiB shipped dictionary assets, at most 128 MiB added +worker heap on the fixture browser, warm lookup under 100 ms for 95 of 100 fixture lookups. A failed +limit requires a reviewed representation change, not dropping words silently. Worker startup never +blocks typing. Only the selected word goes to the worker, and it stays in the browser. + +D12. Right-click an explicitly selected word to open an accessible Synonyms menu. Also support +Shift+F10/Menu key and a toolbar action. Freeze its selection bookmark and document revision when +opening. Preserve selection while the menu has focus. For a whole-word selection, normalize lookup +case and use WordNet exception lists for inflections, while displaying the original word. Do not +silently inflect a replacement. Clicking a result replaces exactly that selection in one undoable +transaction and retains surrounding marks. If the document or selection changed while loading, close +the menu and ask her to select again. Empty/multiword selection, source blocks and read-only mode +offer no replacement. Escape closes and returns focus. Keep ordinary browser copy/paste reachable. + +D13. “Ask the agent for options in this sentence” is an optional second menu action, never a +fallback request sent automatically. It previews the selected word and one sentence, then sends only +that context to the chosen thread after her action. Default off pending the policy/access choices +below. With Q176 unchanged, the answer must be allowed cited advice or bounded corrections under +C2-06, never an unrestricted rewritten sentence. + +Reviewer checks: fetch the exact mirror commit, hash the archive, compare the archived LICENSE with +Princeton's published text, recompute every imported file hash and the four synset counts, and run +the converter twice from separate directories for identical output. Include license text with both +original and derived data. Check generated records against source offsets, malformed input refusals, +missing license/hash failures, no executable data, no network calls, CSP equality and absence of +document/word logging. The mirror's pin and measured hash establish repeatability, not a claim that +its bytes were compared with the unavailable Princeton archive. + +## Agent API and MCP access + +D14. Reuse the existing broker and harness typed-tool channel. Mosaic already implements +`initialize`, `tools/list` and `tools/call` in `packages/harness/src/mcp-server.mjs:23-43`, with +session-scoped tool dispatch (`tools.mjs:1-17`). WordCraft's `get_text`, `inspect_document` and +`select_text` (`crates/mcp/src/tools.rs:109-122`) illustrate small, typed operations. Its `execute`, +`type_text` and `save_document` are too broad here. Its `server.rs:130-163` exposes document +resources, but Mosaic needs no second MCP server. + +D15. The browser publishes an immutable, short-lived context snapshot only when Melanie chooses +“Share selection” or “Share document” in the visible thread. A pin does not grant access. Snapshot +identity includes owner, business, library/project, mapped path, tab ID, thread ID, editor revision, +base commit, scope, text digest and expiry. An opaque ID is a reference, not authority. The broker +binds it to the authenticated thread holder and user. No agent chooses another user's tab, changes +the active file, reads a session file or uses `library.file` to evade M4. Sign-out, permission loss +or explicit revoke removes access. A browser heartbeat lease expires after 30 seconds without +renewal, including a lost connection. Absolute expiry is 15 minutes. Navigation suspends access +until explicit sharing for the new file. Multiple tabs have separate IDs and never guess which is +“open”. + +Proposed new interfaces, all gated design contracts: + +| HTTP / broker operation | Typed MCP tool | Result and authority | +|---|---|---| +| `POST /api/editor/contexts` → `editor.context.publish` | none (human only) | Publish selection or document snapshot. Return context ID, revision, digest and expiry. Max 256 KiB snapshot UTF-8, within a 1 MiB HTTP envelope. Reject overflow without truncating silently. | +| `DELETE /api/editor/contexts/:id` → `editor.context.revoke` | none (human only) | Revoke one owned share. Browser disables its card immediately. | +| `GET /api/editor/contexts/:id` → `editor.context.read` | `editor_read_document({context,revision,cursor?})` | Only explicitly shared document text. Page whole blocks below `REPLY_CAP`, with revision/digest on every page. Selection-only sharing refuses whole-document reads. | +| Same read boundary → `editor.selection.read` | `editor_read_selection({context,revision})` | Exact selected text, optional shared sentence and offsets, no implicit surrounding document. | +| `POST /api/editor/suggestions` → `editor.suggestion.propose` | `editor_propose_edit({context,revision,expected,replacement,reason,requestId})` | Store a proposal only. Bind to shared selection offsets and exact expected text, not a browser-supplied filesystem path. No file save. | +| `GET /api/editor/contexts/:id/suggestions` → `editor.suggestion.list` | none required | Human reads proposals for this context. | +| `POST /api/editor/suggestions/:id/decision` → `editor.suggestion.decide` | none (human only) | Accept or reject the card. Acceptance authorizes one local transaction, never a git write. | + +D16. All arguments use strict schemas with unknown keys refused. Reads stay within the existing +session capability and approved universe/scope. HTTP mutations use the signed-in human, exact Origin +and same-origin Fetch Metadata fences, never a browser-selected actor. No MCP accept, save or +general execute tool ships. Publishing unsaved text is a new broker boundary and needs a reviewed +capability/policy decision. The first agent slice can remain read-only on explicitly shared saved +material through existing allowed lookups. + +D17. Use normalized LF Markdown UTF-16 offsets at valid code-point boundaries, not ProseMirror +positions or rendered DOM offsets. The browser builds a source mapping for the selected editable +text and verifies the exact substring. Refuse selections crossing raw blocks, front matter, nodes or +unmappable syntax. The context revision increases on every document edit. A changed digest/revision, +revoked share or changed text makes a proposal stale. Do not auto-rebase it. Acceptance is one +ProseMirror transaction, undoable, and a later Save uses the original file base and the existing +human writer. Applying an accepted card twice is refused. A crash leaves a proposal unapplied, never +retries it. + +D18. Bound proposals to 20 per context, each replacement/expected at most 4 KiB and reason at most +500 characters, with 15-minute expiry and idempotent `requestId` per thread/context. Deduplicate +transport retries without resending to the agent. Log IDs, hashes and outcomes, not bodies. Proposal +content remains protected context data and is deleted on expiry/revoke. Audit records retain +metadata only. Display all generated text as text, with authoring thread, old/new text, reason and +Accept/Reject. Nothing is interpreted as HTML or commands. + +D19. Q176 remains enforced on this new channel too. With no new ruling, only the already permitted +C2-06 cited corrections/advice may appear, with its exact citation and edit-distance limits, and no +agent replacement tool is exposed. Unsaved text has no git citation. Sharing it does not turn a +digest into a valid C2-06 source. Supporting cited unsaved drafts needs an explicit decision and +review of M3-M5 and the guard, not a private suggestion channel around the existing guard. Reject +arbitrary prose even when a human would later approve it until that decision is made. Direct edits +remain outside this recommendation. + +## Split pane, chat and pins + +D24. This section folds Fenton's pane, chat and pin design from `origin/fenton/editor-design` at +`7caf8008b5887c15f74303a50db2e54a9778375f`, `docs/plans/2026-10-21_q195-pane-and-pin.md`. His +separate work supplies the layout, durable thread pin and send-time context model. The following +reconciles it with Q196, Case 2 paths and this brief's explicit sharing rules. It is design input, +not his review approval of this combined document. + +D25. On writing routes put the editor container, a divider and sibling `aside#chat-pane` under +`main`. Navigation replaces the document container only. Embedded chat takes an explicit thread ID +and container, never owns `location.hash`, and reuses the same renderer as full Chat. Keep the +existing 10-second polling, paused for hidden tabs and sign-out. No new WebSocket service. Chat +polling updates only its own DOM. O2, if selected later, would use the same outer pane with an +engine adapter rather than DOM selection access. + +D26. Start at 62% document, 38% chat. The divider uses pointer capture and the WAI-ARIA separator +pattern, names both panes, reports current/min/max width, and supports arrows (2%), Shift+arrows +(10%), Home/End and Enter to collapse/restore. Double-click resets. For the recommended ribbon UI, +clamp document/chat widths to 44rem/18rem and clamp again on resize. Below 76rem show Document/Chat +tabs, preserve both drafts and show reply counts without switching focus. Store width/collapse only +in `mosaic-console-split`, with invalid values reset. No document text in browser storage. These are +design sizes, not benchmark results. The compact O1 toolbar alternative uses 28rem/18rem and tabs +below 60rem. Existing CSP stays unchanged for the recommended O3 headless-export mix. + +D27. Unpinned chat “Follows you” as documents change. A pin binds an owned bus thread UUID to a +document, never a harness run or session-file path. On A pinned to T1 and B pinned to T2, opening B +shows T2, keeping each thread's draft/read cursor. A document without a pin restores the follow-you +thread. Unpinning leaves the displayed thread following the user. Switching thread on a pinned +document offers “Pin this thread here instead?” and never changes the pin silently. A thread may +serve several documents, one pin per document/owner. Document navigation never launches a run. Reads +do not call `thread.open` or send messages. + +D28. Recommend durable pins on the bus, following Fenton's S6. Add +`thread_pins(business,owner,project,path,thread,at)`, unique per business/owner/project/path, with +`POST /api/chat/pins` → `thread.pin`, `DELETE /api/chat/pins` → `thread.unpin`, and `GET +/api/chat/pins` → `thread.pins`, under the existing chat identity/write fences. Testers retain their +own isolated pins, never the human's. Both document and thread must belong to the authenticated +business and owner. For library documents validate the mapped path/scope through the library reader, +not row 148's narrow `documentPath`. Do not widen that existing function. Keep the thread's chat +project separate from the writing repository identity and validate their declared association. Poll +pin unread metadata separately from message bodies so background threads can get a badge without +rendering or waking them. Row 121's current API has no such metadata contract, so W3a must implement +and test it rather than assume it exists. + +No automatic rename following. A missing path shows a stale pin and explicit Re-pin/Unpin controls. +A missing/forbidden thread offers Unpin only and exposes no former content. Two tabs update pins +with a revision precondition, so an old tab cannot silently replace a new pin. The follow-you thread +ID may live under an owner/business-scoped browser key and is cleared on sign-out. A pin confers no +document permission or context sharing. + +D29. First agent context is saved material at send time. A visible chip, explicitly enabled by +Melanie and removable for each send, carries `{project,path,commit,lines:[from,to]}` and no text. It +appears only after her share action. Check commit is reachable in the allowed served history, path +is mapped, caller/thread can read that scope, and both lines exist in that exact commit. When the +draft is dirty or mapping is uncertain, omit selection lines and label “Saved version only. Save to +cite this selection.” Do not pretend draft offsets are saved line numbers. The agent uses existing +approved library lookup tools and C2-06 citations, not session files or an expanded generic `read` +root. + +Store structured context in `message_context` keyed to the message, kept apart from body and +inserted atomically. `thread.send` accepts this optional strict field, and message reads return it +separately. The broker validates the source rather than trusting the browser's chip. This first +saved-context route does not enable D15's unsaved snapshots. Both tables and verb changes need +Jason's explicit schema/API approval. They grant no prose authority. + +D30. Fenton found C2-10b's file list names `bus.js`, while actual thread messages render in +`public/chat.js:68`. Sage must amend that row's ownership/acceptance to include `chat.js` or a +shared renderer before W3 starts. Otherwise cited JSON would reach the pane as plain text. C2-09a's +brief also cites older broker positions. Re-measure against `broker.mjs:3429-3438` when building. No +edits to those briefs or queue are made here. M7 and M8 remain intact, and neither row 5 nor row 29 +is a dependency. + +D31. Fenton's Q196 update adds a host contract that works with each option: `mount`, `destroy`, +`dirty`, `focus`, `selection` and `resized`. For the recommended DOM surface these adapt the +editor's real state, not a second document model. F6/Shift+F6 cycle focus among editor, divider and +chat. Scope editing shortcuts to the focused pane, so chat paste and undo never mutate the document. +Before releasing any editor state, check `dirty`; a missing/failed response counts as dirty. +Preserve the state or offer the explicit Save/Copy/Discard controls in D7. A hash navigation alone +is not a browser `beforeunload` event and must run this check itself. + +For O2, Fenton recommends an iframe so WordCraft's page-wide canvas and document/window listeners do +not capture chat input. A new browser bridge must check `event.origin`, `event.source`, message +schema, per-instance generation and request ID. It needs document load/export, dirty, selection, +focus-out, resize and a safe transaction operation for the thesaurus, not just a notification hook. +A failed dirty response after one second blocks unmounting. During divider drag capture the pointer, +prevent iframe interception, resize at most once per animation frame and send the final `resized` +notification. Test F6 escape, chat paste isolation, narrow ribbon behavior and stale messages after +document changes. A same-origin iframe is UI isolation, not a security boundary. Native file I/O and +network features still need the adapter restrictions in O2. + +An iframe-route-only `wasm-unsafe-eval` exception would be narrower than changing the Console shell +policy, but it still changes the editor's CSP and requires Q167 D3's ruling. The recommended +headless-export O3 needs neither an iframe nor a browser WASM exception. No alternative-origin +hosting or broad `unsafe-eval` is authorized as a workaround. Fenton's conditional P5 brief at the +pinned source describes the iframe bridge. If O2 is chosen, revise W2/W6 into source-import/build +and browser-bridge rows before queue entry, with their exact owned source paths and the measured CSP +delta. + +O2's DOCX selection cannot use Markdown line citations. A versioned document locator and C2 +guard/renderer support would need a separate reviewed format-policy brief. A DOCX path is not made +legal by leaving `lines` out. Until that change is approved, rich-document agent context is +disabled. Do not use paragraph indexes as if they were existing git lines. + +## Build order and review gates + +Order: W1 → W2 → W3 → W6 → W4 → W5. W3a can prepare after its Case 2 dependencies and must finish +before W3. W2 is a useful writing increment. W6 completes the recommended release's styled +production handoff. W4/W5 remain separately gated. + +These are proposed briefs, not queue entries. Jason confirms the checklist, Mos routes the decision, +then Sage accepts and schedules each brief and creates its Gitea build issue. Every code row gets an +independent Opus 5.5 reviewer who did not author that row. Q177 allows building on a reviewed parent +candidate, with landings in order. It does not allow overlapping file owners or bypassed reviews. +Sage grants suite slots and the final gate. Rows owning `serve.mjs` also serialize behind row 198's +current ownership. That is a file handoff, not a dependency on the retired board. + +Common gate G1: run each changed/touched test file independently, the affected package suites and +every `scripts/test-*.sh` on Sage's slot. Search tests for changed path/hash pins. For editor +changes use `MOSAIC_REQUIRE_EDITOR_BUILD=1` with pinned esbuild 0.28.2 and reproducible output +hashes. Browser checks use scratch roots and invented vaults only. No row activates a stack, changes +roles or pushes to protected branches by implication. + +## W1 local thesaurus data and converter + +### Problem + +WordCraft's small built-in list cannot provide general writing coverage (D10). No Console thesaurus +dataset exists in the measured editor inputs. + +### Owner and reviewer + +- Owner: Researcher in a T3 Codex gpt-6-luna seat (lower-level data import and converter). +- Reviewer: Fenton, Opus 5.5, independent of this implementation. +- After: Jason's data-source confirmation. May start independently of C2 shared-file work. + +### Files owned + +`packages/webui/third_party/thesaurus/{LICENSE,NOTICE,PROVENANCE.json,wordnet/}`, +`packages/webui/editor-data/{import-wordnet.mjs,build-thesaurus.mjs,BUILD.json}`, +`packages/webui/src/public/thesaurus-data/`, `packages/webui/tests/thesaurus-data.test.mjs`, +`packages/webui/README.md` (thesaurus section). + +### What ships + +Pinned WordNet originals and deterministic derived local data (D10-D11). Tests reproduce counts and +hashes, license preservation, invalid-input refusal and stable sorted output. No change inside +`editor/` or existing editor tests. Record actual output size. + +### Out of scope + +Menu, worker wiring, agent requests, editor source and Case 2 library writes. + +### Gate + +Fenton verifies source/license and two independent builds. Data tests pass and output stays within +D11's size budget, then G1. Sage accepts the manifest. + +## W2 writing surface and local synonyms, first usable slice + +### Problem + +F3's redraw loses undo history and no selected-word menu exists. Books also need Case 2's library +read/write path (F4, D5). + +### Owner and reviewer + +- Owner: Gyro, Codex gpt-6.1-sol (editor lifecycle and selection handling). +- Reviewer: Fenton, Opus 5.5, independent of the code. +- After: W1, C2-11a row 214, C2-10b, and C2-11b with C2-02/C2-03b for usable book saves. + +### Files owned + +`packages/webui/editor/{view.mjs,entry.mjs,editor.css,thesaurus.mjs}`, +`packages/webui/editor/BUILD.json`, +`packages/webui/src/public/{editor.js,editor.css,bus.js,bus.css,thesaurus-worker.js}`, +`packages/webui/tests/{editor.test.mjs,editor-browser.test.mjs,docs-browser.test.mjs,writing-browser.test.mjs,thesaurus-browser.test.mjs,editor-provenance.test.mjs}`, +`packages/webui/README.md` (writing section). `model.mjs` remains C2-11a's result. + +### What ships + +D4-D12, D31 and O1's familiar controls: stable per-document state, explicit save, writing controls, +navigation through the existing library tree, preserved front matter and local accessible synonyms. +Wire only reviewed self-hosted assets. Tests cover selection/focus, Unicode, stale lookup, +replacement undo, read-only, exact saved-selection source mapping, unsupported blocks, no external +requests and unchanged CSP. A fixture session edits two nested chapters with front matter/wikilinks, +saves, navigates back and checks bytes, selection and undo. Test `stale-base`, unknown result, +unpushed feedback, credential expiry preserving local text and explicit sign-out clearing it after +the unsaved warning. Measure D11's load/heap/lookup budgets and a 100,000-word fixture without lost +input during chat-style refresh events. Passing responsiveness means no typing task above 100 ms +after load in 95 of 100 measured edits, with the browser/host recorded. + +### Out of scope + +Split pane, pins, agent permissions, library writer/sync implementation and Word layout. + +### Gate + +Fenton repeats the fixture writing flow and reviews accessibility and byte preservation. `node +--test packages/webui/tests/` with the required build passes, then G1. Sage accepts. + +## W3a durable pins and saved-message context + +### Problem + +Pins and structured message context do not exist (F5-F6). Browser-only pins would differ across +machines. D28-D29 require new durable records and verified source references. + +### Owner and reviewer + +- Owner: Gyro, Codex gpt-6.1-sol (schema, broker and channel changes). +- Reviewer: Fenton, Opus 5.5, independent of the implementation. +- After: C2-09a, C2-10b ownership correction, C2-05b, and Jason's schema/API decision. + +### Files owned + +`packages/bus/{schema.sql,src/store.mjs,src/broker.mjs,src/editor-pins.mjs}`, +`packages/bus/tests/{schema.test.mjs,editor-pins.test.mjs}`, +`packages/plugins/channel/webui/index.mjs`, `packages/plugins/tests/` (pin/context tests), +`packages/webui/src/{chat.mjs,chat-http.mjs,serve.mjs,cli.mjs}`, +`packages/webui/tests/{chat.test.mjs,editor-context.test.mjs}`, `packages/webui/README.md`, +`packages/bus/README.md`. The next migration identifier is allocated by Sage's schema window before +build. + +### What ships + +D28-D29, an idempotent versioned migration in the repository's existing migration mechanism, +owned-pin revision checks, background unread metadata and atomic saved-message context. Tests refuse +another user's/thread's/business's context, wrong scope, unreachable commit, missing file and +out-of-bounds lines. Failed context insertion leaves no message. Pin tests cover tester separation, +stale paths and concurrent repin refusal. No document text stored in the new context table. +Migration/restore-count and bus tool allowlist tests remain green. + +### Out of scope + +UI, raw session access, unsaved context, new role authority and replacement prose. + +### Gate + +Fenton reviews schema/ownership and failure cases. Bus, plugins and WebUI suites pass plus G1. Sage +accepts within the allocated schema window. No live migration is part of this row. + +## W3 split pane and pinned conversations + +### Problem + +F5's page-level routing prevents a persistent conversation beside navigation. No pin exists. D24-D30 +supply the behavior to implement. + +### Owner and reviewer + +- Owner: Dewey in a T3 Haiku 5.5 high seat (mid-level pane and state wiring). +- Reviewer: Fenton, Opus 5.5, independent of the implementation. +- After: W2, W3a, C2-10b, C2-09a and row 220 C2-10a. Shared files wait behind those owners. + +### Files owned + +`packages/webui/src/public/{index.html,bus.js,bus.css,chat.js,chat.css,writing-pane.js}`, +`packages/webui/src/{serve.mjs,chat.mjs,chat-http.mjs}`, +`packages/webui/tests/{chat.test.mjs,chat-browser.test.mjs,writing-pane.test.mjs,writing-browser.test.mjs}`, +`packages/webui/README.md` (pane section). Persistent pin storage is W3a, not a hidden schema change +here. + +### What ships + +D24-D31: a resizable accessible split pane that reuses the existing owned chat thread and C2-10b +cited-item rendering, retains editor selection/history during polling and follows the pin rules in +D27-D29. Tests cover pin/unpin, two files, two tabs, removed/inaccessible thread, keyboard divider, +narrow viewport, reconnect/sign-out and navigation during delayed replies. No implicit `thread.open` +on read or navigation. Existing chat tests remain green. The saved context chip uses W2's exact +source mapping, and dirty drafts omit selection lines. + +### Out of scope + +7331 board route, row 5, row 29, raw sessions, fresh agent permissions and auto-launched runs. + +### Gate + +Fenton verifies the pane/pin scenarios against the folded design. WebUI suite and G1 pass. Sage +accepts the manifest after W3a's migration and API review. + +## W6 DOCX production export and DesignCraft fixture handoff + +### Problem + +DesignCraft's `.md` import is plain text (D21). A Word-like writing surface still needs a verified +styled book-production handoff, without creating two editable masters. + +### Owner and reviewer + +- Owner: Gyro, Codex gpt-6.1-sol (isolated headless format adapter and semantic checks). +- Reviewer: Fenton, Opus 5.5, independent of the implementation. +- After: W3, Louie's evaluated engine revision, and Jason's O3/storage choice. + This serializes shared `serve.mjs` and `writing-pane.js` ownership. + +### Files owned + +`packages/writing-export/` (new, source, tests, pinned source manifest and build records), +`packages/webui/src/{editor-export.mjs,serve.mjs,cli.mjs}`, +`packages/webui/src/public/writing-pane.js`, `packages/webui/tests/writing-export.test.mjs`, +`packages/webui/README.md`. No change to WordCraft/DesignCraft checkouts. Any copied source retains +full applicable license notices. Export-commit authorization must be covered by a separate accepted +writing-project path/policy brief before a repository write is enabled. + +### What ships + +D20-D23's bounded Markdown-to-DOCX export from a pinned source commit, style map, warning report and +manifest, plus a reproducible source build of the needed WordCraft headless component. Review the +pinned Cargo.lock and dependency licenses, preserve required notices and bundle any required fonts +locally. Hard starting caps: 1 MiB Markdown input, 16 MiB DOCX output, 30-second conversion deadline +and one conversion per user at a time. Record actual fixture results and revise these limits only in +the accepted brief when measurements justify it. Refuse filesystem/network escape, external +linked-resource fetches, scripts/macros, malformed archives, decompression bombs and unsupported +semantic loss. Run the conversion without network or credential access. Fixture tests place the +result through DesignCraft's headless MCP path and compare body, styles, Unicode, paragraphs and +warnings. Conversion is an explicit action, not every Save. The initial UI can download the export +until the reviewed git-output path is authorized. + +### Out of scope + +Legacy .doc/.qxd import, new rich-document editing, live DesignCraft control and layout work on +Melanie's actual content. No guessed “full fidelity” claim. + +### Gate + +Fenton independently runs the export/place fixture using the pinned two source revisions and +inspects the loss report. New export tests and affected WebUI suite pass plus G1. Sage accepts only +if the target chapter's tested supported features place without loss. + +## W4 scoped context API and typed reads + +### Problem + +The broker knows saved library material, not a tab's open document or selection. Exposing unsaved +drafts without explicit consent would cross D15-D16's new boundary. + +### Owner and reviewer + +- Owner: Gyro, Codex gpt-6.1-sol (broker identity and capability integration). +- Reviewer: Fenton, Opus 5.5, independent of the implementation. +- After: W6, C2-05b, C2-06, row 220, and Jason's explicit context-access decision. + +### Files owned + +`packages/webui/src/{serve.mjs,cli.mjs,editor-http.mjs}`, +`packages/webui/src/public/writing-pane.js`, `packages/bus/src/{broker.mjs,editor-context.mjs}`, +`packages/harness/src/tools.mjs`, `packages/{webui,bus,harness}/tests/` (editor-context test files +only), `packages/webui/README.md`, `packages/harness/README.md`. Any capability/role schema change +needs a separately accepted policy brief, not this allowlist. + +### What ships + +D14-D16's publish/revoke/read operations with strict schemas, expiry, bounded paging and explicit +sharing UI. Pi and Claude use the same broker checks. Tests refuse cross-user, thread, business, +universe, tab, guessed context, stale revision, revoked shares, expired heartbeat and absolute +expiry, whole-document read on selection-only access and attempts to use raw session endpoints. +Confirm raw-session `conversation-not-listed` and human-only `library.file` still refuse. + +### Out of scope + +Replacement proposals, save authority, new roles and bypass of M3-M5. + +### Gate + +Fenton approves boundary tests and confirms no tools are exposed without the approved capability. +WebUI, bus and harness suites pass with G1. Sage accepts. + +## W5 guarded proposals and optional sentence options + +### Problem + +Q195's requested editing API needs a human-controlled proposal flow, but Q176 currently prohibits +unrestricted prose. An unsaved draft is not a valid existing git citation (D19). + +### Owner and reviewer + +- Owner: Gyro, Codex gpt-6.1-sol (revision checks and undoable proposal application). +- Reviewer: Fenton, Opus 5.5, independent of the implementation. +- After: W4 and an explicit Jason ruling on proposal kinds and unsaved-draft citations. + With no ruling this row does not enter the queue. + +### Files owned + +`packages/bus/src/{broker.mjs,editor-context.mjs}`, `packages/harness/src/tools.mjs`, +`packages/webui/src/editor-http.mjs`, `packages/webui/src/public/writing-pane.js`, +`packages/webui/editor/{view.mjs,thesaurus.mjs}`, `packages/webui/editor/BUILD.json`, +`packages/webui/src/public/{editor.js,editor.css}`, `packages/{webui,bus,harness}/tests/` +(editor-suggestion test files only), `packages/webui/README.md`. Any +`packages/library/src/guard.mjs` or role-policy change is excluded until its own reviewed policy +brief names the approved change and tests. + +### What ships + +D13 and D17-D19, restricted to the confirmed policy. Tests cover old/new text rendering, +accept/reject, undo, stale and expired context, changed base, no autosave, retry deduplication, +invalid UTF-16 boundary, hostile markup and guard failures on both RESULT and tool paths. Negative +tests prove an agent cannot accept, apply or save, and no proposal widens C2 scope. + +### Out of scope + +Direct agent edits, prose permission by inference, arbitrary execute and automatic sending. + +### Gate + +Fenton verifies that the recorded ruling matches the allowed proposal shapes and source citations. +WebUI, bus, harness and library guard regression suites pass with required editor rebuild and G1. +Sage accepts. No deploy or activation authority follows. + +## Design verification receipt + +Checked 2026-10-21T16:22:36Z (from `date -u`). Both companion branches were fetched and their +report commits pinned above. Seven briefs have every BRIEF-TEMPLATE field, unique anchors +and an independent implementation reviewer. The checklist has 12 lines. Only this design +and append-only BUILD-LOG/SESSIONS records change. No product or queue files change. + +Fresh editor/provenance checks: 10 passed, zero failed, one rebuild skip because pinned +esbuild 0.28.2 is absent. This is not a claim that O3's exporter, new UI, live Console or +DesignCraft handoff has shipped or passed acceptance. Those tests belong to the build rows. +The push queue guard ran as `MOSAIC_GIT_IDENTITY=gyro` for `gyro/editor-design`, purpose +`push`, timeout/interval zero. It could not resolve the per-seat credential and recorded +`CANNOT_ASSERT credential-unresolvable` with its documented push `degraded-pass` (exit 0), +audit at `/mnt/storage/scratch/gyro-q195-ci-queue-audit.jsonl`. No identity fallback or guard +bypass was used. CI status was not asserted. Fenton reviews the combined draft through Mos. + +## Jason's checklist + +- Q1. Choose O3: Word-like DOM editor plus headless WordCraft DOCX export. Recommend yes for the first release. +- Q2. Are footnotes, comments, tracked changes or page layout required in that first release? Recommend defer them, or choose O2 for a richer editor after its bridge is proved. +- Q3. Allow O2's scoped WebAssembly/CSP change if you choose it? Recommend no blanket exception and a separate security gate. +- Q4. Keep Markdown as the first editable git source, with generated DOCX for DesignCraft. Recommend yes, never two editable masters. +- Q5. Ship writing controls, safe chapter saves and local WordNet synonyms first. Recommend yes, behind Case 2's shared-file rows. +- Q6. Store pins and saved-source message context on the bus through the reviewed schema/API change. Recommend yes. +- Q7. Pin by owner and document path, with explicit repair after a move. Recommend yes. +- Q8. Share saved context only when Melanie enables the visible chip for that send. Recommend yes. +- Q9. Keep saves explicit and unsaved drafts in the current tab initially. Recommend yes. +- Q10. Permit agents to read unsaved drafts or propose new prose? Recommend no initially, retaining Q176 and cited corrections. +- Q11. If proposals are enabled later, require Accept/Reject and a separate Save. Recommend yes. +- Q12. If O2 stores DOCX, approve a separate rich-document citation and library-policy design? Recommend yes before agent context.