Compare commits

...
3 changed files with 847 additions and 0 deletions
+6
View File
@@ -5177,3 +5177,9 @@ 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.
2026-10-22T16:06:34Z | Q195/Q196 design review fixes, #1752 / Vikunja #448, mos-1300 / fenton-0004 | Before: draft 105811400 had owner-only thread wording, stale source positions, two mismatched seat/model assignments, an assumed library save boundary and 12 owner questions. After: grant-aware pin validation and stale/revoked access redaction; references refreshed against aca16404c, including public/bus.js and README offsets; Sage assigns model-only seats; unimplemented library.file.save/C2-11b brief blocks book editing; tabs explicitly cover 62-76rem; J7 stricter context choice recorded; pronouns removed; six owner questions. Static docs/source-anchor checks only, no builds, product suites, MVP gate slot or live action. Fenton re-check pending; O3 and both companion folds retained.
+6
View File
@@ -1419,3 +1419,9 @@ 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.
2026-10-22T16:02:06Z | Gyro (T3 Codex gpt-6.1-sol) | Q195/Q196 independent-review follow-up, mos-1300, Q220 | Recovered candidate 105811400 and current refactor aca16404c; canonical queue next gyro returned nothing; sent read-only reference drift map to Fenton, whose review is active. Design candidate left unchanged pending verdict. Docs-only fixes authorized on gyro/editor-design, no MVP gate slot.
2026-10-22T16:06:34Z | Gyro (T3 Codex gpt-6.1-sol) | Q195/Q196 fenton-0004 F1-F8 docs fixes, mos-1300, #1752 / Vikunja #448 | Verified findings against aca16404c, retained O3, corrected grants/dependencies/model routing/folds/citations and reduced checklist to six; docs-only candidate for Fenton re-check, no product checks or MVP gate slot.
@@ -0,0 +1,835 @@
# Q195 writing editor design
Gitea #1752, Vikunja #448, DECISIONS Q168, Q177, Q194, Q195 and Q196. Design for review, not build
authority. Originally measured at `6c75887b0`, rechecked against `origin/refactor` at
`aca16404c` for Fenton's fenton-0004 review. Repository line references use `aca16404c` unless
a different revision is named. WordCraft and DesignCraft retain their separately pinned revisions.
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. Editor build gates are
post-October 27 work and never take the gate slot ahead of MVP rows. Design and review
continue now under Q220.
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:892-911,949-951` 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:572`) 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:999-1010`, `serve.mjs:522-555`, keys :527 and handler :531). 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:1124-1128`), 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:845-853` exposes thread state and idle release. Thread creation at `:5716-5728` checks FED R3 grants; open/send at `:5766-5780` also use `#grantedThread` (`:790-793`) after thread ownership checks. Open requests launch explicitly. Current chat uses the thread's default session; pins remain thread IDs, never individual runs. 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 (`:784`). 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:522`). Row 198 (#1696) retires the 7331 board writer, currently referenced at `serve.mjs:14`. 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. |
Original draft verification at `6c75887b0`: `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`. Louie built a scratch clone of WordCraft
`e05b7fe86f3b85454000dffc321de638d7009817` (0.9.0), with no source modifications.
These are Louie's 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. The report's Console CSP reference was `serve.mjs:495` at
`6c75887b0`; the identical policy is now `packages/webui/src/serve.mjs:605` at `aca16404c`.
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-04's human-only `library.file` read (`packages/bus/src/broker.mjs:99,4610-4616`).
The future `library.file.save` verb does not exist at `aca16404c`. C2-11b has no accepted
brief yet (`docs/plans/2026-10-20_case2-rows.md:11-14`), and the Case 2 design
(`origin/gosalyn/case2-design:agents/gosalyn/work/case2/DESIGN.md`, section 7.3) proposes
its navigation and save UI. C2-11b's brief, the future human save verb, C2-02's writer and
C2-03b's push behavior must be implemented and independently reviewed before W2 can ship
book editing. They are explicit blockers, not an existing save boundary or work hidden in
a UI row. Until then only `docs/` fixtures can exercise the new writing surface.
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`. Fenton's
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 Fenton's 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. For the ribbon UI, tabs deliberately start at 76rem, including the entire
62–76rem band where the two pane minimums alone would fit. That leaves room for navigation
and avoids another intermediate layout. This deliberately replaces Fenton's E6 2.5rem chat
rail in that band. Existing CSP stays unchanged for the recommended O3 headless-export mix.
D27. Unpinned chat “Follows you” as documents change. A pin binds a bus thread UUID that passes current ownership and FED R3 grant checks 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. The pin belongs to its authenticated business/user.
`thread.pin` and `thread.pins` reuse `#grantedThread` after the existing thread ownership
check, as open/send/messages do (`packages/bus/src/broker.mjs:790-793,5766-5780`). Ownership
alone is insufficient. Pin operations never grant thread or document access. 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 or revoked/expired thread grant shows the stale-pin state,
offers Unpin only and exposes no former content or unread metadata. The owner may remove
that stale pin without regaining access to the thread. 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. `packages/project/src/paths.mjs:34-40` now refuses a library repository unless
`allowLibrary` is explicit. Use the library reader and do not widen `documentPath`.
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:5716` 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. This deliberately replaces Fenton's J7 proposal to send DOCX context without
lines. 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: a T3 Codex gpt-6-luna seat, assigned by Sage (lower-level data import and converter).
- Reviewer: Fenton, Opus 5.5, independent of this implementation.
- After: Jason's first-slice approval. WordNet is the design's routine data-source choice.
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's future accepted brief and the unimplemented human `library.file.save` verb,
with C2-02/C2-03b for usable book saves. No acceptance claim until all are reviewed.
### 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, grant revocation/expiry and concurrent repin refusal. `thread.pin` refuses an
owned thread whose grant no longer covers it. `thread.pins` redacts thread content and
unread metadata after revocation while permitting stale-pin removal. No document text
is 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: a T3 Haiku 5.5 high seat, assigned by Sage (mid-level pane and state wiring),
separate from C2-10b's reviewer.
- 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 grant-accessible 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, revoked/expired grant, 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 initial checklist had 12 lines before fenton-0004. 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.
## Review-fix verification receipt
Checked 2026-10-22T16:06:34Z (from `date -u`) against `aca16404c`. Addressed fenton-0004 F1-F8:
grant-aware pins and revoked-access redaction, refreshed source references, model-only
seat allocation, the unbriefed save dependency, deliberate tabs below 76rem, the explicit
J7 replacement, seat-name wording and six owner-choice questions. Additional reference
refresh: `public/bus.js` moved by 24 lines, and the Visual editor README heading is at 572.
The code behavior cited there is unchanged. The O3 recommendation and companion report
measurements are unchanged. Fenton re-checks this revision before approval.
Validation is static: current-source anchors, seven complete brief templates, six checklist
lines, documentation-only diff and append-only logs. No build, product suite, gate-slot
reservation or live action is part of this review fix. The earlier 10-pass/one-skip result
above is the original draft's test receipt, not a new test run on `aca16404c`.
## Jason's checklist
- Q1. Choose O3 with Markdown source, generated DOCX, and footnotes/comments/tracked changes/page layout deferred? Recommend yes.
- Q2. Ship writing controls, safe chapter saves and local WordNet synonyms first, after the Case 2 dependencies? Recommend yes.
- Q3. Store pins and saved-source message context on the bus through the reviewed schema/API change? Recommend yes.
- Q4. Share saved context only when Melanie enables the visible chip for that send? Recommend yes.
- Q5. Keep Q176, with no agent prose and no unsaved-draft reads? Recommend yes. Any later relaxation requires Accept/Reject and a separate Save.
- Q6 (O2 only, if Q1 is declined). Require a Q167 D3 CSP exception and rich-document citation design before O2? Recommend yes.