From e012bab0be40499aa81868a092e2b331b7ec75c5 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 22 Oct 2026 18:03:56 -0500 Subject: [PATCH] docs: redesign Q195 for full WordCraft O2 editor --- BUILD-LOG.md | 4 + docs/SESSIONS.md | 1 + docs/plans/2026-10-21_q195-writing-editor.md | 1332 +++++++++--------- 3 files changed, 684 insertions(+), 653 deletions(-) diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 62cc1d22e..e3bba2dcb 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -5344,3 +5344,7 @@ Gander: after Duckworth-0100 design approval with C1-C5, prepared the two host-s 2026-10-22T18:11:57Z | Sage | Row 275 (#1780, Morgana, Duckworth) LANDED 3410df7c3. Before: refactor at 48e450ce8; viewers had no verb list of their own and board reads were not refused to users. After: a fast-forward of 3 commits; manifest 39847b15 (4 paths) blobs match; gate 17:52:12Z-18:05:00Z green (whole files 7/22/6, bus 834, cli 861, harness 151, business 231, seat 167, 10 scripts with 3 named skips), M6 and M10 killed; Duckworth APPROVE rev 3260 (comment 30717); note and done by sage-2897; #1780 comment 30728 and closed. N1 (board refusal test as a loop over BOARD_VERBS) is non-blocking. 2026-10-22 18:11:58 UTC | Gander row276 #1781 prepared, gate pending | Before: row253 left5legacy Case1 AS_USER calls unsupervised across sudo pty sessions. After: candidate uses its unchanged supervisor with per-call inner/outer budgets, separate streams, strict display-only failure trailer, fake-only paired process-model cases and15unique mutants. Duckworth0182 B1 corrected the plan before product code;0183 cleared build. Parse-only Bash checks pass; no Node, behavioral test, host, unit or config action. Runtime gate and publication await Sage. + +2026-10-22T23:03:39Z | Gyro Q195 O2 rewrite, #1752 / Vikunja #448, mos-1356 | Before: landed O3 design 95e3f7166/blob 4cb59999. After: Q231/Q233 full WordCraft O2 design on gyro/editor-o2 from refactor c4f77373f; canonical git DOCX, original Markdown/wiki preservation, human cadence default 0 with instant accepted-save commits, full rich-feature first slice. Ten briefs include independent source/dependency security clearance before any build queue entry, exact editor-only CSP approval gate, restricted source/build/bridge, separate reviewed DOCX citation gate and flags-only agent access. Existing Case 2 semantics unchanged; any integration requirement change goes through Mos to Jason. Static checks: ten briefs/seven fields, independent reviewers, unique anchors, current source/base/blob pins, docs scope and append-only logs pass. No builds, browser/worker runs, code, queue or live changes. Fenton review pending; CSP and implementation gates remain closed. + +2026-10-22T23:03:53Z | Gyro Q195 O2 push guard | CI queue guard identity gyro / purpose push returned exit 0, documented degraded-pass: CANNOT_ASSERT credential-unresolvable. Audit: /mnt/storage/scratch/gyro-q195-ci-queue-audit.jsonl. No credential fallback or CI-green claim. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 8197c3136..de81fc9fc 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -1549,3 +1549,4 @@ are never rewritten or removed; corrections are new entries. 2026-10-22 | Della | Row258 E01 3094e3bfa focused manifest review | APPROVED 11-path manifest/static F1/F2/N1 corrections; file and full-blob digest recipes verified. M1-M11 fixed; all execution/landing evidence still required in CLEAR. No shared-log edit, Node, tests, HTTPS Git or live action. 2026-10-22T17:55:40Z | Sage (Opus 5.5, 1ef1e4f8) | Row 253 landing; post-253 doc sweep | 253 LANDED 48e450ce8. Sweep on sage/sweep-253: Gosalyn Case 2 design and rows, 229 design, Gyro 0acbdb0d8, Della 179391055, 268 docs, seat dirs for Della, Scrooge, Huey, Louie and Ludwig, human-users-build:70 under Q173, DEFERRED 253 N1, 198 N2, row 203 text, 224 residual and 206 sharee list, and seat log lines. 2026-10-22 14:48 UTC | Researcher (Sonnet 5.5, 9bac0794) | Rows 220 and 216 resumed (sage-2708, sage-2716, sage-2719); local commits only | 220 e4a204836 on researcher/row220-r2 (on ea6dc9eff): C1 run tests, C2 default-reader M7 test, configDirectory fixture scope, BUILD.md round 2b. 216 4f3fbc25a on researcher/row216-r2 (on aca16404c): index cache, find/get/search/manuscript/universeInfo, PRD 1.14 levels. Nothing pushed, claimed or run; node --check not run. Waits for Sage's CLEAR and go; rebase onto 253 on a new branch before any gate. +2026-10-22T23:03:39Z | Gyro (Codex gpt-6.1-sol, mos-1356) | Q195/Q231/Q233 O2 design rewrite, gyro/editor-o2 from c4f77373f | Canonical queue next gyro: nothing. Ten docs-only briefs; full-feature WordCraft, independent 15-crate/199-package security review, editor-only CSP candidate, instant git DOCX saves and retained Markdown/wiki sources, committed-only DOCX citation gate, no agent story prose. Static structure/source-anchor/scope checks only; no code, build/run, queue or live change. Fenton review requested after push. diff --git a/docs/plans/2026-10-21_q195-writing-editor.md b/docs/plans/2026-10-21_q195-writing-editor.md index 4cb599999..88e65b1a8 100644 --- a/docs/plans/2026-10-21_q195-writing-editor.md +++ b/docs/plans/2026-10-21_q195-writing-editor.md @@ -1,835 +1,861 @@ -# Q195 writing editor design +# Q195 writing editor: O2 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`. +Gitea #1752, Vikunja #448. Rewrite for mos-1356 and DECISIONS Q231/Q233. Jason chose O2, +the full WordCraft editor, including footnotes, comments, tracked changes and page layout in +the first editor release. O3 and its Markdown-first feature cut are withdrawn. -## Outcome and boundaries +Base: `origin/refactor` at `c4f77373f9708037129c3918a3e72d2d71a96163`. Starting design: +`95e3f7166:docs/plans/2026-10-21_q195-writing-editor.md`, blob +`4cb5999991369225f165c2f88c3607a03417774f`. Repository references below use this new base. +This branch is `gyro/editor-o2`. Fenton reviews the rewrite. This document authorizes no +code, build, worker run, queue entry, policy change or live action. -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. +## Decisions and gates -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. +D1. Q195/Q196/Q233 settle the product: WordCraft's engine and canvas interface in the left +pane, persistent chat in the right, a draggable divider, document navigation, pins and a +right-click thesaurus. It is not a reskinned row 154 editor. The first useful release must +pass writing, footnote, comment, tracked-change and page-layout save/reopen tests together. -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. +D2. Q210/Q220 allow design and review now. All O2 code rows below remain post-October 27 +build gates and never take a gate slot ahead of MVP rows. No O2 build row enters the queue +until S0's independent source security review passes. Source import/build and bridge work +also wait for Jason's approval of the exact editor-only CSP delta. This design approval, +a source review, a CSP approval and a code review are distinct gates. -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. +D3. Q223/Q226/Q233 settle the agent boundary. Agents never modify story files or write +replacement story sentences. They may converse freely, flag issues, cite committed text +and use existing separately authorized supporting-document tools. No editor document, +selection, title, path or derived reading copy reaches an agent until W4's DOCX citation +and access design has independent approval and W4b's enforcement passes. A pin grants no +access. No unsaved-draft API, native WordCraft execute/save tool or replacement-proposal +channel is exposed to an agent. W5 is flags and chat suggestions only. -## What exists +D4. Pins and saved-context records live on the bus through a reviewed schema change. +Sharing with a send is a human-only setting, default a visible removable chip per send. +Agents read committed text only. These Q233 choices are not questions for Jason again. +Q222 makes cadence, sharing, require-citation, timeouts and limits human-only settings +with defaults. Settings cannot authorize agent story writes or bypass grants or S0/W4. -| Code | Measured finding and implication | +D5. Preserve the Case 2 Markdown library and its October 27 acceptance. O2 is an additional +rich-document store and reader, not a regexp widening of `documentPath`, a silent change +in the library's accepted formats, or a new write right for creative roles. Existing +Markdown and its wiki links are never stripped. Legacy `.doc` and `.qxd` import stays D23's +separate assignment, below. No seat opens Melanie's content or accesses her host. + +## Evidence retained and refreshed + +F1. Row 154 landed as `9353675d1` (#1648). Its source is +`packages/webui/editor/{model.mjs,view.mjs}` and `packages/webui/third_party/editor/`, with +ProseMirror and markdown-it (`model.mjs:16-18`). Its tagged-source provenance, licenses and +source build remain the standard for O2 supply-chain review. Row 148's save remains +`{project,path,base,content}` (`packages/webui/src/serve.mjs:527,531`), with an authenticated +human, Origin/Fetch Metadata checks and stale-base refusal. Its text and path bounds do not +admit DOCX. `packages/project/src/paths.mjs:14` stays unchanged. + +F2. Current Case 2 briefs have advanced since the original design. C2-11a is at +`docs/plans/2026-10-20_case2-rows.md:238`; C2-10b at `:865` now specifies free chat, +`renderReply`, optional checked citations and write notices. C2-02 at `:2031` specifies +human `library.file.save` and agent supporting-doc writes. C2-11b at `:2127` specifies the +library tree and human saves. These are briefs, not proof of implementation. +`packages/bus/src/broker.mjs:99` still lists only library.file/status/sync. O2 shared-file +rows wait behind these owners and their landings. They do not replace their MVP work. + +F3. Chat already has projects, threads, paging and explicit open/send +(`packages/webui/src/chat.mjs:19-27`). Pins retain a bus thread ID, using its default session +unless the existing chat explicitly selects another. They never name a harness run or a +raw session file. Current grant checking is verb-sensitive: +`packages/bus/src/broker.mjs:813-815`, `#grantedThread(s, verb, t)`. Pin reads/writes must use +the corresponding existing read/write grant level as well as ownership checks. A revoked +or expired grant produces a stale pin without thread content or unread metadata. Unpinning +an owned stale pin must not restore access. No `/api/conversation(s)` or 7331 board route. + +F4. WordCraft reference: `/mnt/storage/src/artcraft/wordcraft` at +`e05b7fe86f3b85454000dffc321de638d7009817` (0.9.0), read-only. Louie's evaluation is +`origin/louie/wordcraft-eval` at `880ef19e017dad0194ecc9921ae55a0cf2e8fef2`, file +`docs/plans/2026-10-21_q195-wordcraft-eval.md`. No build was repeated for this rewrite. + +| Measured baseline | Result and consequence | |---|---| -| 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. | +| Two release builds | 392.786 s and 172.324 s, four Cargo jobs, low priority. All four output hashes identical. These are build times, not browser startup measurements. | +| Browser artifact | WASM 43,994,316 bytes, JS 164,941, HTML 1,604, icon 18,378. Total 44,179,239 bytes. WASM SHA-256 `90dec375924b47b40054eb4ecafb4235b6ed0bd63880b91ec138fdbb6f939e75`. No measured compressed-transfer size. | +| Review surface | 15 local crates, 251,457 physical Rust source lines, 199 third-party name/version pairs for the web target. The workspace lock also contains packages outside that target. | +| Browser integration | `apps/wordcraft-web/src/web.rs:26-82` closes over Session/WordApp and the canvas. No document/selection page API. eframe observes canvas size, which supports pane fitting as an inference, not a tested Console integration. | +| MCP | 16 native tools, stdio/headless or desktop loopback transport. The browser has no TCP control channel (`apps/wordcraft-web/src/main.rs:7`). Native MCP cannot control the browser document. | +| Format limits | Synthetic `.doc` to `.docx` kept heading, italics and footnote but lost the comment. `.doc` to Markdown lost footnote semantics. Markdown footnote syntax became escaped ordinary text. Rich DOCX cannot use Markdown as a lossless master. | +| Thesaurus | `crates/engine/src/cmd/review.rs:914` has 29 headwords and 122 synonym values. Hunspell is a separate spelling mechanism. | -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. +F5. Fenton's pane/pin input remains pinned at `origin/fenton/editor-design`, +`7caf8008b5887c15f74303a50db2e54a9778375f`, file +`docs/plans/2026-10-21_q195-pane-and-pin.md`. Retained: sibling chat container, divider, +focus rules, dirty timeout, structured send context and bus pins. This rewrite uses O2's +44rem document minimum and tabs below 76rem, without the intermediate chat rail. The new +DOCX gate still deliberately replaces J7's proposal to send rich-document context without +lines. J6's requirement for Jason's CSP ruling remains intact. This input is not approval +of this O2 rewrite. -## Options and recommendation under Q196 +## Security scope and exact CSP candidate -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. +D6. S0 is a separate independent security review, assigned by Sage to someone other than +Gyro or Louie and other than a source/adapter author. It reviews the pinned source and actual +web-target dependency closure, not only the WordCraft license header or Louie's build success. +All 15 crates are covered: doc, docbin, docx, engine, fonts, formats, geom, layout, metafile, +pdf, proof, render, ui-egui, wordcraft-web and zotero. Inventory all 199 third-party packages, +versions, immutable source hashes, licenses, required notices, build scripts and generated +inputs. Preserve MIT/Apache-2.0 notices and every dependency/font notice that actually applies. +A target/feature/dependency change invalidates the approved inventory until reviewed. -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. +D7. The audit must trace native I/O and network paths even when cfg excludes them from WASM. +The embedded adapter permits only host-mediated owned-document bytes and explicit local +human editing. Disable or replace the following, with refusal tests and no fallback: -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 | +| Surface | Required host restriction | |---|---| -| 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 | +| Open/New/Save/Save As, drop, picker and downloads | Host-owned document IDs and approved import/export operations. No arbitrary native path, browser File System Access persistence, generic fallback file browser or silent local-download save. `Services` is at `crates/ui-egui/src/lib.rs:98`; setting one hook to None is insufficient if another path falls back. | +| Local fonts and persisted document data | Do not enumerate system fonts or read external font folders. Ship reviewed fonts. Disable added-font IndexedDB and document recovery stores unless a separate human-controlled feature is reviewed. Preference storage may contain UI settings only, never prose or credentials. | +| Clipboard, pictures, HTML and embedded objects | User-initiated clipboard only, bounded decoded data, safe text/raster parsing. No HTML execution, arbitrary file drop, external relationship fetch, macros, OLE activation or network-linked image/font fetch. Reject malformed/oversized archives without mutation. | +| Hyperlinks, bibliography/Zotero, updates, help and external resources | No automatic remote requests, update checks, local service connection or iframe-initiated popup/navigation. Explicit outbound links go to a host URL gate and a separate human action. Audit `ui-egui/src/lib.rs:2244-2245`, not just connect-src. | +| Print/PDF preview | Disable WordCraft's hidden blob PDF iframe (`web.rs:548-604`). Keep canvas page layout and an explicit human PDF export through the host. No blob-frame exception in the proposed first policy. | +| Native MCP/execute/control ports | No browser-to-native control server, agent execute/batch/type_text/save_document or generic command tunnel. Native binaries and credentials are not shipped to the iframe. | -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. +S0 passes only with a complete inventory, license findings resolved, no unresolved blocking +security finding, and an accepted list of mandatory adapter mitigations and rejection tests. +It is baseline-source clearance under those restrictions, not approval of unbuilt adapter +code. Every implementation still gets independent code review, and W6 must prove the +mitigations before any release. If the baseline cannot meet the restrictions, S0 fails. +Do not queue build rows on a promise to fix a failing security review later. -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. +D8. The current shell CSP is at `packages/webui/src/serve.mjs:605`. Source inspection and +Louie's existing generated artifacts establish the narrow candidate below. The generated +HTML also contains an inline module bootstrap (`dist/web/index.html:9` in Louie's scratch +artifact). W2 externalizes that bootstrap and its styles into reviewed self-hosted files. +No `unsafe-inline` script exception, nonce exception or broad `unsafe-eval` is proposed. +No browser enforcement measurement or relaxed policy was run in this docs-only task. -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 | +| Directive | Shell, unchanged | O2 iframe document only, proposed | |---|---|---| -| `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. | +| default-src | `'self'` | `'self'` | +| script-src | `'self'` | `'self' 'wasm-unsafe-eval'` | +| style-src | `'self' 'unsafe-inline'` | `'self' 'unsafe-inline'` (no new allowance) | +| connect-src / font-src | `'self'` / `'self'` | `'self'` / `'self'`, only reviewed asset reads permitted by adapter code | +| object-src / base-uri | `'none'` / `'none'` | `'none'` / `'none'` | +| frame-ancestors | `'none'` | `'self'` | +| frame-src | absent, falls back to `'self'` | `'none'` (PDF preview disabled) | +| form-action | `'self'` plus configured SSO targets | `'none'` (frame has no form flow) | -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. +The two increased allowances are WASM compilation and same-origin embedding of the editor +response. frame-src/form-action tighten that response. The shell can already load a same-origin +iframe through its default-src fallback. No alternative origin, CDN, blob script, broad eval, +worker or GPU-specific exception is needed by the measured baseline. No policy changes until +S0 passes and Mos obtains Jason's approval of the exact reviewed delta. If browser checks +later require any extra source or PDF framing, stop that change and return the new delta to +Mos. Do not silently add `blob:` or treat the existing policy approval as unlimited. -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. +D9. Serve the editor document only at authenticated `GET /editor/wordcraft/frame` and its +versioned assets under `/editor/wordcraft/assets/`. Apply the frame policy only to that HTML +response. Shell, chat, API, error, redirect and sign-in responses retain their existing +policies. No raw Trunk development server, auto-reload code or unrestricted static mount. +Unknown assets and traversal refuse. WASM uses application/wasm and nosniff. Test the header +on success and every refusal path. The frame is not mounted before the approval gate is met. -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. +## Rich storage, saves and the Markdown boundary -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. +D10. Canonical editable O2 content is DOCX in git, including styles, sections/page layout, +footnotes, comments and tracked changes. No Markdown-to-DOCX-to-Markdown save loop. Each +managed document has a stable document ID and manifest naming its canonical DOCX path, +source origin, format revision, current blob and commit. DOCX and manifest changes publish +atomically in one commit. They are not two editable masters. -## Split pane, chat and pins +D11. Existing Markdown remains byte-for-byte at its current path. Human adoption into O2 +creates a DOCX working document in the separate O2 writing project and retains the original +Markdown, front matter and all wikilink forms as source evidence. The adoption manifest +records the source commit/blob/path and new document ID. The UI labels the old source and +new working document distinctly. It never silently replaces an existing chapter's Markdown +master, rewrites its links, or claims the retained source is the current edited DOCX. -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. +The adoption adapter preserves `[[target]]`, `[[target|label]]`, `[[target#heading]]` and +embeds as exact literal text in the DOCX body, with source-token metadata in the manifest. +It must not rely on WordCraft's default Markdown exporter to reconstruct those bytes. +Front matter and unsupported source blocks are retained in the source, never discarded. +A fidelity report and a human confirmation precede adoption. A failed token/format check +refuses adoption and leaves the original untouched. Rich editing in the new DOCX does not +write a lossy Markdown projection over the original. Human edits to a literal wikilink are +ordinary deliberate document edits; agents cannot change chapter links. -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. +D12. O2's store is outside generic worker roots and the Case 2 `.md` mirror, under +`/writing///`. Its human writer and, after W4, its committed +reader use explicit new verbs. It does not widen `LIBRARY_VERBS`, `documentPath`, a library +mapping, generic read/grep roots or a Gitea grant. No agent receives a raw repository grant +to this store before the citation gate. Existing Case 2 `.md` files retain their normal +MVP reader/writer semantics and remain selectable in the existing library interface. -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. +Requirement boundary for Mos: making Case 2's existing library_get/library_manuscript or +supporting-doc writer follow an adopted DOCX, indexing DOCX as a `.md` story, or keeping a +live Markdown projection synchronized would change a Case 2 requirement. None is authorized +by this design. If shared-library integration is required instead of the separate O2 project, +Mos must take that requirement change to Jason before that integration is built. It is not +hidden inside a format-conversion row or added to today's CSP approval question. -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. +D13. Setting `editor.commitCadenceMs` is human-only in UI and CLI, default 0. Zero submits a +save after each completed document transaction, including comments, review changes, section +layout and undo/redo. IME composition commits only when the composition completes. A human +may choose a positive autosave delay; it changes when a save is submitted, never whether an +accepted save immediately commits. Ctrl/Cmd+S always flushes without delay. No save is held +for a later batch, a timer after acknowledgment, or an agent turn. Unchanged revisions are +already-saved status reads, not new save requests. There is no source or message text in logs. -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. +D14. Every accepted save has immutable bytes, document ID, revision, expected base blob, +request ID and authenticated human identity. Serialize saves per document in revision order. +Under the git lock, compare the base, make one commit and advance the canonical served ref +and committed-reader index before replying Saved. That ref is the source for the next lookup, +with no 60-second cache delay. Do not let a broker cache serve the previous commit after a +successful save. Pin/context generation must use the returned commit, never pending text. -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. +Network push is a separately reported sync outcome. A local committed/served save is visible +to the local agent's next authorized lookup even while remote push is pending. Show “Saved +locally, push pending” rather than “Synced”. Credentials and policy are checked server-side +using the human's authorized writer path and existing chief-of-staff grant machinery, never +in WASM. No force push. A remote divergence stops sync and preserves the local commits and +original evidence, not an automatic overwrite. This separate O2 storage choice does not +change C2-02/C2-03b's remote-push-before-served acceptance or its refusal codes. -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`. +D15. Lost save responses use request-ID readback, not blind retry. A stale base keeps the +full draft, review state and undo history and offers manual reconciliation. Save backlog, +byte/ZIP limits, expiry and idle cadence are human-only settings with documented defaults. +Start with 16 MiB DOCX input, 128 MiB expanded ZIP, 32 pending snapshots and a 30-second save +outcome deadline. Backpressure stops further autosave submission and preserves the draft, +never drops an accepted snapshot. These are proposed defaults, not measured capacity. +W3b/W6 must measure them on full-feature fixtures before acceptance. A limit cannot turn a +story write into an agent action or a failed save into a success. -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. +## The pane and the browser bridge -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. +D16. Keep a sibling `aside#chat-pane`, not a child of the document container. The editor is +an iframe within the left pane. Navigation changes its document through the host contract, +not by replacing chat. Default split is 62% document, 38% chat. Minimums are 44rem and 18rem. +Below 76rem use Document/Chat tabs deliberately throughout the 62–76rem band. Preserve both +drafts and scroll positions and mark unread replies without switching focus. The divider +uses the WAI-ARIA separator pattern, pointer capture, arrows (2%), Shift+arrows (10%), +Home/End and Enter collapse/restore. Double-click resets. Persist only UI proportions. -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. +D17. The host contract is `mount`, `destroy`, `dirty`, `focus`, `selection`, `resized`, +`loadCommitted` and `exportSnapshot`. No generic execute method. Parent and iframe handshake +with a protocol version, a fresh instance generation and a per-instance message token. +Every message checks exact same origin, expected `event.source`, schema, message type, +request ID, generation, size and document binding. The token correlates messages; it is +not an authorization capability. No wildcard targetOrigin, paths, arbitrary URLs, bearer +credentials or caller-selected backend verbs. Host binds document ID to the authenticated +open operation. Buffers have bounds and transfer ownership explicitly. -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. +D18. Parent-to-frame messages load validated owned bytes and acknowledge/refuse a specific +save revision. Frame-to-parent messages report ready, dirty/revision, local selection, +save snapshot, focus-out and resize completion. Unknown, duplicate or stale generations +are refused. Changing documents invalidates outstanding selection/save callbacks. Serialized +snapshots may cross to the human host for saving; never to the agent or chat by default. +Selection locators for agents resolve against a returned committed blob, not live WASM text. -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. +D19. An iframe gives UI containment, not a security sandbox for trusted same-origin code. +If `sandbox="allow-scripts allow-same-origin"` is used, do not claim it prevents that code +from reaching the parent. No popup, top-navigation, form or download grants are added. +The source/adapter must therefore be reviewed as application code, including the same-origin +API surface it could call. The bridge does not substitute for broker authorization or S0. -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. +D20. Only the focused pane owns editing keys. F6/Shift+F6 cycle editor, divider and chat. +The iframe forwards F6 out so the canvas cannot trap a keyboard user. Chat paste/undo must +never edit the story. Resize at most once per animation frame while dragging, temporarily +prevent iframe pointer interception, and call resized at drag end. Before unmount, ask dirty; +no response after the human-configurable one-second default counts as dirty. Navigation, +refresh, sign-out and tab close preserve or warn about uncommitted work. Credential expiry +revokes sharing and blocks saves, retaining the local draft for copying or reauthentication. -## Build order and review gates +D21. Full-feature acceptance uses an invented DOCX with styled headings, footnote reference +and body, a comment anchored to text, tracked insertion/deletion and a section/page layout +change. Edit all four in the embedded UI, commit, reopen and compare semantics and layout. +No flattening comments or accepting all revisions on save. Check long documents, Unicode, +IME, undo/redo, keyboard escape, focus, save contention and reload recovery. The baseline +build report is not this proof. A failure in one required feature blocks the first release, +not a rationale to defer that feature without a new ruling. -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. +## Thesaurus and agent review -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. +D22. Keep the local Princeton WordNet 3.0 source choice. The earlier design measured the +pinned NLTK mirror at `96f9b3252457a2b97e52aec64c3dfceeb5c312d5`: archive 10,775,600 bytes, +SHA-256 `cbda5ea6eef7f36a97a43d4a75f85e07fccbb4f23657d27b4ccbc93e2646ab59`, all entries +36,353,991 bytes, lookup data/index/exception files 35,435,978 bytes. Princeton's +[statistics](https://wordnet.princeton.edu/documentation/wnstats7wn) give 117,659 synsets and +147,278 distinct strings. Its [license](https://wordnet.princeton.edu/license-and-commercial-use) +permits use/modification/distribution with its copyright, terms and disclaimer preserved. +Do not relabel it MIT/Apache. The mirror pin/hash establish repeatability, not a comparison +with the Princeton archive that timed out in the original investigation. -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 retains original text, LICENSE, NOTICE and per-file provenance, plus a deterministic +converter and derived static data. Review archive/per-file hashes, license bytes, synset +counts and repeat generation. Bake the data into the installed release. No runtime download, +CDN, upstream lookup or automatic model call. O2 can use an internal lookup over bundled data, +so this design adds no worker-source CSP allowance. Record actual generated size and heap +cost, with tunable defaults, rather than reusing old browser-memory estimates as facts. -## W1 local thesaurus data and converter +A selected-word right-click, Menu key/Shift+F10 or ribbon action shows meanings/glosses and +synonyms. Keep a revision-bound bookmark. Choosing a local synonym is a human-triggered, +undoable WordCraft transaction, preserving formatting. Stale selection, nonword selection, +read-only document or a pending document switch refuses replacement. Native spelling and +local synonyms are distinct. Full keyboard and clipboard menus remain reachable. + +D23. Legacy import is its own assignment. Retain original `.doc`/`.qxd` bytes and hashes, +produce a converted editable artifact with styles, attachment mappings, stable document +identity, source correspondence and a loss report, then get human acceptance. WordCraft's +measured `.doc` comment loss must be disclosed. Neither WordCraft nor DesignCraft currently +reads `.qxd`; extraction needs its own evaluated tool/license. No original is overwritten. +No Melanie files, host access or bulk legacy-import button in these O2 rows. + +D24. Native WordCraft MCP is not an agent bridge. After W4 and W4b pass, Mosaic offers only +`editor_read_committed`, `editor_resolve_citation` and `editor_flag`, over the existing +runner tool socket/MCP server (`packages/harness/src/mcp-server.mjs:23-43`). No native +execute/batch/open/type/save route is reachable from an agent. Generic read/grep, raw session +views, O2 exports/source copies, indexes and direct git access cannot bypass the gate for +O2 documents or their derived material. Existing Case 2 Markdown access stays unchanged; +retaining a previously authorized original does not expose the DOCX or its later edits. Support-document permissions remain Case 2's own +human-configured supporting scopes, never the DOCX chapter store. + +D25. Proposed DOCX citations bind `{business,project,document,commit,blob,part,paragraph, +start,end,textView,quote,quoteDigest}`. Parts are explicit document body, footnote/endnote +or comment stories. Resolve paragraph IDs when present, otherwise an ordinal within that +exact part/blob. Offsets are Unicode code-point offsets in a deterministic committed-text +projection with a named extractor version. Never interpret them as Markdown line numbers. +A locator is immutable within its commit; after another commit, show stale and resolve the +old quoted version, never auto-relocate a flag to similar text. + +W4's separate reviewed design must fix the precise XML/relationship allowlist, paragraph +fallback, tracked-change reading view (default final accepted reading, source revision history +retained), footnote/comment ownership, quote verification, non-story supporting scopes, +authorization, paging, and denial of external relationships/macros/ZIP bombs. It must cover +source-like text inside comments and tracked deletions without treating it as instructions. +Tests must independently recompute locators from a committed fixture, distinguish two identical +paragraphs/notes, reject a modified quote/blob/part and refuse unsaved or ungranted data. A +citation design is not approved merely because this outer plan describes a shape. + +D26. Sharing is a human-only setting, default `visible-chip-per-send`. Until the citation gate, +the chip says editor context unavailable and sends no editor metadata. Once enabled, the +visible removable chip binds the exact saved document/commit and selected committed range. +If the live selection cannot map to that commit, do not send a nearby passage or draft text. +A pin or earlier send does not silently grant future context. Recheck scope and live grants +on every lookup. A successful later save becomes the next lookup's latest committed version; +an already sent citation retains its original commit for verification. + +D27. W5 creates read-only flags and cited findings outside the document: Jump to source and +Dismiss, not Accept/Replace/Apply. No comment node, tracked change, sentence suggestion patch +or metadata insertion is written into a chapter by an agent. Chat can discuss ideas, consistency +and wording, but its text is never passed to the engine as a replacement. “Ask the agent about +this passage” sends only a resolvable committed locator after the sharing gate, never the draft. +Local dictionary replacement remains an ordinary human action, not an agent proposal. + +Free chat replaces the old short-item-only M5 premise under Q223. A human-only require-citation +setting defaults off (Q226). Supplied citations are always checked; flags always carry checked +locators. If citation requirement is enabled, the response follows the approved rule for missing +citations rather than bypassing it via a flag or raw session view. Caps have human-only settings +with defaults, not the superseded fixed 120-character chat restriction. + +## DesignCraft handoff + +D28. The committed DOCX is the production source for DesignCraft, not a lossy Markdown export. +At DesignCraft `3ce3a24f08d03935bc8cf7cb23755aca8065558c`, +`crates/textimport/src/lib.rs:94-126` recognizes Markdown but imports it as plain text. +DOCX named styles and footnotes are read in `crates/textimport/src/docx.rs:493-548`. +`tracked_changes_import_as_accepted_including_moves` at `:706` shows placement takes the +accepted reading, not editable review history. `file.place` and its style mapping are the +MCP handoff. Jason's later layout agent uses an approved workspace and a pinned source commit. + +Keep the original rich DOCX with all comments/revisions in git. A human-approved production +copy has a named reading view and style map, source/output hashes and a loss report. Validate +text, notes, styles, list levels and layout warnings on synthetic fixtures before claiming +placement fidelity. Do not silently accept revisions in the source file. The editor neither +runs Jason's layout agent nor automatically grants it access or sends book text elsewhere. + +## Proposed rows + +All rows follow BRIEF-TEMPLATE. They are not queue entries. S0 and W4 are independent design/ +review work that can proceed now. No code row W1/W2/W6/W3a/W3b/W3/W4b/W5 enters the queue +before S0 PASS. Each also observes its explicit dependencies, source ownership, the CSP gate +and the MVP gate-slot priority. Q177 permits chaining reviewed candidates, not overlapping +owners. Sage assigns model-only seats. Each implementation reviewer is Opus 5.5 and did not +author the code. Fenton reviews this design and can review code only when not its author. + +G1. Future code acceptance runs each touched test file independently and affected package +suites on Sage's slot after MVP priority, plus required repository checks. Source builds need +pinned tools, reproducible hashes, license/source manifests and independent review. Browser +proofs use scratch fixtures only, after the CSP ruling. Tests never use a live stack, private +books or host credentials. These are future gates, not checks run for this docs rewrite. + +## S0 independent WordCraft source security review ### Problem -WordCraft's small built-in list cannot provide general writing coverage (D10). No Console thesaurus -dataset exists in the measured editor inputs. +The measured 15-crate/199-package canvas application is much larger than row 154's editor. +An independent source and trust-boundary review is a prerequisite, not a build success claim. ### 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. +- Owner: an independent Opus 5.5 security-review seat assigned by Sage, neither Gyro nor Louie, + and not an author of WordCraft imports/patches or the browser adapter. +- Reviewer: a second Opus 5.5 seat assigned by Sage, not the report author or adapter author. +- After: no build dependency. Review the exact pinned source and existing evaluation artifacts. ### Files owned -`packages/webui/third_party/thesaurus/{LICENSE,NOTICE,PROVENANCE.json,wordnet/}`, +`docs/reviews/2026-10-22_q195-wordcraft-security.md`, +`docs/reviews/2026-10-22_q195-wordcraft-security.json`, +`docs/reviews/2026-10-22_q195-editor-csp.md`. + +### What ships + +D6-D9's source/dependency/license inventory, native I/O/network analysis, mandatory adapter +restrictions, residual risks, source hash/feature manifest and verdict. The CSP report names +full old/new headers, affected response routes, baseline artifact hashes and disabled PDF +preview/inline-bootstrap mitigation. Distinguish source inference from browser proof. +Review all 15 crates, all 199 target dependencies and applicable fonts/build scripts/notices. + +### Out of scope + +Production code, a relaxed live policy, source imports, building the O2 integration, private +files and an approval on Jason's behalf. No queued build row until this review passes. + +### Gate + +Sage records PASS only on both independent review reports with no unresolved blocker and +explicit required mitigations. Mos then asks Jason the one exact CSP question. A failure +holds every O2 build row. Changed target dependencies or a wider CSP re-open this gate. + +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. +Copy Mos on the final security/CSP report so Mos can obtain Jason's exact-delta ruling. + +## W1 reviewed local thesaurus data + +### Problem + +WordCraft's 29-headword table is inadequate. O2 needs a local reviewed dataset and licenses. + +### Owner and reviewer + +- Owner: a Codex gpt-6-luna seat assigned by Sage for data import/conversion. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: S0 PASS. No runtime or frame route in this row. + +### Files owned + +`packages/webui/third_party/thesaurus/`, `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). +`packages/webui/tests/thesaurus-data.test.mjs`. ### 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. +D22's source text/license/provenance and deterministic derived data. Compare the pinned +archive hash, per-file hashes, Princeton license, counts and two converter outputs. A missing +license, changed source, malformed record or unexplained count change refuses the build. ### Out of scope -Menu, worker wiring, agent requests, editor source and Case 2 library writes. +WASM bridge, right-click UI, worker/runtime data fetch and agent requests. ### 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. +Independent license/provenance approval, data tests and G1. The dataset adds no CSP source. -## W2 writing surface and local synonyms, first usable slice +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W2 WordCraft source import and reproducible restricted web build ### 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). +Louie's scratch build is evidence, not an owned release asset with source and license receipts. +The generated inline bootstrap cannot run under the proposed self-hosted script policy. ### 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. +- Owner: Gyro, Codex gpt-6.1-sol, for source import, supply chain and build integration. +- Reviewer: an Opus 5.5 seat assigned by Sage, independent of the imported/modified code. +- After: S0 PASS and Jason's exact CSP approval. No build row is queued before S0 passes. ### 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. +`packages/webui/third_party/wordcraft/{upstream/,cargo-vendor/,PROVENANCE.json,NOTICE}`, +`packages/webui/wordcraft/{build.mjs,toolchain.json,BUILD.json,frame.html,frame.css,frame-bootstrap.js}`, +`packages/webui/wordcraft/patches/source-build.patch`, +`packages/webui/src/public/wordcraft/`, +`packages/webui/tests/{wordcraft-provenance.test.mjs,wordcraft-build.test.mjs}`. ### 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. +Pinned original source and the approved dependency closure, required licenses/notices and +recorded local patches. Any workspace reduction/feature selection is explicit and cannot +expand the reviewed 199-package target unnoticed. No dist/target or unreviewable prebuilt +vendor input. Build offline from reviewed sources with pinned Rust/Cargo 1.99.1, Trunk 0.22.0, +wasm-bindgen 0.2.129 and wasm-opt 131, plus tool binary hashes. External bootstrap and CSS +replace generated inline markup. Record every input/output hash, size and tool version. +Two different absolute roots must yield identical integration outputs. New sizes are +measured; the 44,179,239-byte baseline is not promised after patches. ### Out of scope -Split pane, pins, agent permissions, library writer/sync implementation and Word layout. +Serving the frame, live CSP, git saves, native desktop binaries and agent MCP. The protected +WordCraft checkout is never modified. Build outputs remain inert until W6 passes. ### 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. +S0's reviewer rechecks the imported target/patch inventory. Independent implementation +review, reproducibility/provenance tests and G1 pass. A dependency/tool change returns to S0. -## W3a durable pins and saved-message context +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W6 owned browser bridge and editor-only route ### 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. +The current WASM closure exposes no host document API, native-style save cannot commit to +Mosaic git, and same-origin embedding alone does not enforce D7's restrictions. ### 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. +- Owner: Gyro, Codex gpt-6.1-sol, for the WASM host boundary and restricted service adapter. +- Reviewer: an Opus 5.5 seat assigned by Sage, not the adapter author. S0's security seat + separately verifies all mandatory mitigations before release. +- After: W2, W3b, W1 and Jason's exact CSP approval. Serial ownership after W2. + +### Files owned + +`packages/webui/wordcraft/patches/host-bridge.patch`, +`packages/webui/wordcraft/{build.mjs,frame-bootstrap.js,frame.html,frame.css,BUILD.json}`, +`packages/webui/src/public/wordcraft/`, +`packages/webui/src/{serve.mjs,wordcraft-http.mjs}`, +`packages/webui/src/public/editor-wordcraft.js`, +`packages/webui/tests/{wordcraft-bridge.test.mjs,wordcraft-csp.test.mjs,wordcraft-browser.test.mjs}`. + +### What ships + +D7-D9 and D17-D21: typed load/dirty/revision/save/focus/resize/selection operations, restricted +Services and no fallback I/O. Human local thesaurus lookup/replacement lives inside the +reviewed adapter, not a general parent execute channel. Test wrong origins/sources/tokens, +stale generations, document switches, replay, malformed/oversized payloads, dirty timeout, +F6 escape and chat paste isolation. Refuse all disabled I/O/network routes. Test full-feature +DOCX save/reopen, no comments/revision loss, and exact source/wiki preservation on adoption. +CSP tests compare shell/error/redirect headers byte-for-byte and assert only the approved +frame HTML delta, no PDF iframe, no inline bootstrap and no additional CSP source. + +### Out of scope + +Native MCP/TCP, alternative origin, extra CSP allowances, agent document access and legacy import. + +### Gate + +Independent code review, S0 mitigation checklist with evidence for every surface, browser +header/bridge/full-feature tests and G1. A missing required Word feature or a new CSP need +blocks release and returns to Mos. No silent feature cut or security exception. + +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W3a bus pins and human-only editor settings + +### Problem + +Pins, saved-context records and tunable commit/sharing settings need durable human-owned +state with current grants, not browser defaults that an agent can widen. + +### Owner and reviewer + +- Owner: a Codex gpt-6.1-sol seat assigned by Sage. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: S0 PASS, C2-09a/C2-10b and the current schema window. No overlap with W3b/W4b broker work. ### 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. +`packages/bus/src/migrations/editor-o2-pins.sql`, +`packages/business/src/{editor-settings.mjs,business.mjs,cli.mjs}`, +`packages/plugins/channel/webui/index.mjs`, +`packages/webui/src/{chat.mjs,chat-http.mjs,cli.mjs}`, +`packages/bus/tests/editor-pins.test.mjs`, `packages/bus/tests/schema.test.mjs`, +`packages/business/tests/editor-settings.test.mjs`, `packages/plugins/tests/editor-pins.test.mjs`, +`packages/webui/tests/editor-pins.test.mjs`. ### 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. +Pins keyed by business, human, project and stable document ID; path is display/repair metadata. +Reuse verb-sensitive ownership/grant checks. Stale grant/path/thread redacts content and unread +counts but permits owned-pin deletion. Store saved-context envelopes on the bus, deny their +publication to an agent until W4/W4b. Human-only settings with version checks/defaults include +commit cadence 0, sharing visible-chip-per-send and require-citation off. UI/CLI use the same +backend validation. Migration/restore, grant revocation, tester separation, concurrent repin, +unknown key and agent settings-write refusal tests are required. Sage assigns the schema edge; +if naming conventions require another exact migration path, amend this brief before acceptance. ### Out of scope -UI, raw session access, unsaved context, new role authority and replacement prose. +DOCX parsing, agent story-write rights, live migration, iframe policy and raw sessions. ### 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. +Independent schema/authorization review, bus/business/plugins/WebUI tests and G1. Pins/sharing +are Q233 engineering decisions; no further owner question for those settled choices. -## W3 split pane and pinned conversations +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W3b human DOCX store and instant commits ### Problem -F5's page-level routing prevents a persistent conversation beside navigation. No pin exists. D24-D30 -supply the behavior to implement. +The existing row 148/C2 Markdown save contracts cannot safely accept canonical DOCX, nor +preserve full rich state via Markdown round trips. Next-lookup visibility needs an explicit ref. ### 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. +- Owner: a Codex gpt-6.1-sol seat assigned by Sage. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: W3a, C2-02/C2-03b/C2-11b shared-file handoff and the schema window. No MVP gate priority. ### Files owned -`packages/webui/src/public/{index.html,bus.js,bus.css,chat.js,chat.css,writing-pane.js}`, +`packages/writing/{package.json,README.md}`, +`packages/writing/src/{git.mjs,store.mjs,settings.mjs,adopt-markdown.mjs}`, +`packages/writing/tests/{store.test.mjs,adopt-markdown.test.mjs,fixtures/}`, +`packages/bus/src/{broker.mjs,client.mjs,server.mjs}`, +`packages/webui/src/{cli.mjs,writing-http.mjs}`, +`packages/bus/tests/writing-save.test.mjs`, `packages/webui/tests/writing-save.test.mjs`. + +### What ships + +D10-D15: authenticated human open/adopt/save/readback operations, exact schemas, one immediate +commit per accepted save, revision ordering, base CAS, deduplication and served-ref publication +before Saved. New writing store stays outside worker roots; all agent reads refuse before W4b. +Tests cover comments/notes/revisions/layout, every wikilink fixture form, byte-identical retained +Markdown/front matter, malformed DOCX/ZIP limits, no-op status, stale base, lost replies, +backpressure, rapid autosaves and remote push pending/diverged. A mocked clock alone cannot +prove instant commit: assert ref and committed reader state before the HTTP response. No extra +runtime fetch, credential exposure, shared bot or force push. + +### Out of scope + +Case 2 reader/mapping changes, synchronized Markdown projections, native legacy import, +agent reads/writes, deployment and a relaxed CSP. + +### Gate + +Independent writer/security review, writing/bus/WebUI tests and G1. No accepted-save receipt +may precede its commit/ref/index. Static ownership checks prove no generic agent root includes +the store. Any Case 2 requirement change follows D12 to Mos and Jason before implementation. + +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W3 full editor pane, navigation, pins and right-click synonyms + +### Problem + +A restricted engine and writer are not yet an all-day writing workspace beside persistent chat. + +### Owner and reviewer + +- Owner: a Haiku 5.5 high seat assigned by Sage, separate from C2-10b's reviewer. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: W6, W3a, W3b, C2-10b/C2-11b and C2-11a shared-file handoffs. + +### Files owned + +`packages/webui/src/public/{index.html,bus.js,bus.css,chat.js,chat.css,writing-pane.js,writing-pane.css}`, `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. +`packages/webui/tests/{writing-pane.test.mjs,writing-browser.test.mjs,chat-browser.test.mjs}`, +`packages/webui/README.md`. ### 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. +D16-D22's navigation, familiar full WordCraft surface, splitter, settings controls, save/sync +status and local right-click/ribbon thesaurus. Two pinned documents keep separate chat drafts +and cursors; background unread metadata never wakes a run. No remount on chat polls. Test +keyboard divider/tabs, dirty navigation, credential expiry, stale pins, disabled sharing before +W4b and a writer's multi-document fixture session. Full footnotes/comments/tracked changes/ +page layout and local synonyms must all save and reopen. No first-release deferral of those +features. Distinguish retained Markdown source from the canonical DOCX working document. ### Out of scope -7331 board route, row 5, row 29, raw sessions, fresh agent permissions and auto-launched runs. +Raw session views, the retired board writer, row 5/row 29, legacy import and agent story editing. ### 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. +Independent UX/accessibility review, complete full-feature writing session evidence, WebUI +suite and G1. This is the first useful O2 writing slice, not W2's baseline build alone. -## W6 DOCX production export and DesignCraft fixture handoff +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W4 committed DOCX citation and access design ### 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. +C2 line citations cannot identify rich document stories, notes, comments and revision views. +No agent access is allowed until this design is reviewed, even if the human editor is usable. ### 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. +- Owner: a Codex gpt-6.1-sol design seat assigned by Sage. +- Reviewer: an independent Opus 5.5 seat assigned by Sage, not the design author. +- After: no code dependency. Design/review may proceed now under Q210/Q220. ### 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. +`docs/plans/2026-10-22_q195-docx-citations.md`, +`docs/reviews/2026-10-22_q195-docx-citations.md`. ### 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. +A complete separate design for D24-D26, with exact locator/extraction schema, story/part +classification, grant/share semantics, committed-only visibility, reading views, validation, +staleness, paging and an implementation acceptance matrix. It closes all bypasses through +new O2 source copies, generic reads, git grants and raw sessions, while preserving existing +Case 2 authorization to its original Markdown. That old source is never current DOCX context. A quote must verify against the +specified committed blob and extractor revision. No unsaved context or agent write path. +Resolve any Case 2 schema/meaning change explicitly through Mos; do not amend its line-cite +contract by calling a DOCX paragraph a line. Supply a reviewed migration/compatibility plan. ### 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. +Agent read enablement, code, live docs, story replacement proposals and a CSP ruling. ### 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. +Independent APPROVE and Sage's accepted implementation brief, with no unresolved locator or +permission ambiguity. Changes to a Case 2 requirement go to Jason through Mos before code. +Only after that review may W4b implement access. Outer O2 plan approval alone does not pass W4. -## W4 scoped context API and typed reads +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. +Copy Mos on any Case 2 requirement change that needs Jason's ruling. + +## W4b committed reader, citation resolver and typed tools ### 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. +An approved DOCX citation design still needs enforcement across bus, tools, grants and UI. ### 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. +- Owner: a Codex gpt-6.1-sol seat assigned by Sage. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: S0, W4 APPROVE, W3 and the broker/schema handoff. No queued build before S0 PASS. ### 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. +`packages/writing/src/{read.mjs,citations.mjs,index.mjs}`, +`packages/writing/tests/{read.test.mjs,citations.test.mjs}`, +`packages/bus/src/{broker.mjs,store.mjs}`, +`packages/bus/src/migrations/editor-o2-citations.sql`, +`packages/harness/src/tools.mjs`, `packages/harness/tests/editor-tools.test.mjs`, +`packages/business/src/vocabulary.mjs`, +`roles/{companion,ideas,research,proofreader,fact-checker,continuity}.json`, +`packages/bus/tests/editor-access.test.mjs`, `packages/webui/src/public/writing-pane.js`, +`packages/webui/tests/editor-context.test.mjs`. ### 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. +The exact reviewed W4 schema, committed-only reader and tool mapping, least-privilege role +intersection and per-lookup grants. All access remains off until the extractor, resolver and +sharing gates pass together. Test all part/view/quote failures, identical passages, stale +commits, another user/project/universe, revoked grants, unsaved data and denied generic roots. +After a successful human save, the next authorized lookup returns that commit, never a cached +pre-save view. All agent write/execute/save attempts into story content refuse. Pinning alone +never grants reads. Named migration files use Sage's allocated version edge before acceptance. ### Out of scope -Replacement proposals, save authority, new roles and bypass of M3-M5. +Expanding Case 2 Markdown semantics without its own approved amendment, unsaved reads, +native MCP and agent story writes. ### 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. +Independent policy/parser/tool review, writing/bus/harness/business/WebUI tests and G1, plus +fixture bypass probes. No partial rollout where UI hides context but another tool can read it. -## W5 guarded proposals and optional sentence options +### Handoffs + +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. + +## W5 read-only flags, citations and chat suggestions ### 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). +Agents can help review committed passages without modifying the chapter or injecting a +replacement sentence. The old W5 replacement proposal flow violates Q223/Q233 and is removed. ### 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. +- Owner: a Haiku 5.5 high seat assigned by Sage for flag cards and chat integration. +- Reviewer: an independent Opus 5.5 seat assigned by Sage. +- After: W4b, C2-10b and shared WebUI ownership handoff. ### 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. +`packages/writing/src/flags.mjs`, `packages/writing/tests/flags.test.mjs`, +`packages/bus/src/{broker.mjs,store.mjs}`, +`packages/bus/src/migrations/editor-o2-flags.sql`, +`packages/harness/src/tools.mjs`, `packages/harness/tests/editor-flags.test.mjs`, +`packages/webui/src/public/{writing-pane.js,chat.js}`, +`packages/webui/tests/{editor-flags.test.mjs,chat-browser.test.mjs}`. ### 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. +D27: metadata-only flags bound to checked committed locators, Jump/Dismiss and free chat +with optional required citations under the human setting. Store flags on the bus, outside +the chapter file and its tracked changes/comments. Test stale/dismissed flags, changed +quotes, unauthorized source, settings writes by agents and denied replacement/execute/save +messages. Snapshot the typed tool list: no propose_edit, apply_patch, accept_suggestion, +replace_selection or equivalent story-writing route. Verify every human local synonym action +is distinct from an agent flag. No automated story insertion from chat text. ### Out of scope -Direct agent edits, prose permission by inference, arbitrary execute and automatic sending. +Replacement-sentence payloads, Accept/Apply UI, agent-created story comments/revisions, +unsaved context, supporting-doc CRUD already governed by Case 2, and native MCP. ### 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. +Independent review, flags/bus/harness/WebUI tests and G1. Evidence shows unchanged story +blob before and after every agent flag/chat operation. Human story edits still commit normally. -## Design verification receipt +### Handoffs -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. +Owner sends the pushed commit/blob directly to the assigned reviewer and Sage through T3. +The reviewer sends the verdict directly to the owner and Sage; revisions repeat that handoff. -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. +## Current verification and Jason's remaining item -## Review-fix verification receipt +This is a docs-only rewrite. Source and existing build artifacts were inspected, not built +or run. The 44,179,239-byte figure and format findings remain Louie's pinned measurements. +Static checks cover branch/base, row fields/dependencies, source anchors, source/measurement +pins, one owner question, documentation-only scope and append-only logs. No security PASS, +CSP approval, DOCX citation approval or implementation acceptance is claimed here. -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. +After S0 passes, Mos asks only: approve the exact editor-frame CSP delta in S0's reviewed +report, with the shell unchanged? Recommendation: allow only `'wasm-unsafe-eval'` for that +frame document and `'self'` framing, keep embedded PDF preview disabled, and add no other +allowance. If the reviewed measurement differs from D8, replace the question with that exact +reviewed delta. This sentence is not Jason's approval and does not enable the frame.