diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 4d3187cf5..daef03af0 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -5358,3 +5358,9 @@ Gander: after Duckworth-0100 design approval with C1-C5, prepared the two host-s 2026-10-22T23:13:27Z | Gyro Q195 O2 fenton-0007 F7/F8 | Named human-only editor.saveGroupPauseMs=2000 and editor.saveGroupMaxMs=15000 with integer/range/cross-field validation and W3a UI/CLI refusal tests. W3b owns production adoption refusal until W4b; isolated fixture conversion remains testable without request-flag bypass. W4b owns adoption module/API tests and reviewed lifting only with committed-reader/citation readiness and, if Q36 approves, the separate notice row PASS. Q36 unresolved stays closed. Static ten-brief, setting-key/bounds, refusal/lift ownership and two-question checks pass. Docs only; no build, browser/worker run, product/queue/live change. Fenton checks F7/F8 on next push. 2026-10-22T23:13:48Z | Gyro mos-1359 / r3 push guard | D13 records save-group timing as Mos's accepted reading of Q226 F41, not Jason's ruling; both defaults remain human-only settings. Push guard identity gyro/purpose push: exit 0 documented degraded-pass, CANNOT_ASSERT credential-unresolvable; audit gyro-q195-ci-queue-audit.jsonl, no credential fallback or CI-green claim. + +2026-10-23T00:52:58Z | Gyro Q235-Q237 policy rewrite started, Vikunja 571, mos-1366/1367 | Before: approved O2 e36bce352 keeps Markdown originals at their paths and Q36 notices open; landed W4 2af460ab7 has the same boundary. Imported that byte-identical W4 baseline as 1ac76a417, from refactor 062646487, to make the policy-only revision diff explicit. Prepared P1-P6/B1-B4: human one-way per-story import, human-set source-repo archive, DOCX current reader, scoped format map/archived non-canon reads, W7 conversion publication after W4b/approved PRD/10-27 and Jason first-real-book go. Q234 exact CSP, mos-1363 and S0 M1-M14 retained. W4 locator/extractor, shares and restore-fence blocks compare byte-identical to the approved baseline. Scope/source review ongoing; Mos impact map must be folded before Fenton handoff. No build/browser/worker run, code, queue, private-book or live action. + +2026-10-23T01:37:07Z | Gyro Vikunja571 final impact-map / mos-1372/1375 fold | Prepared parent/W4 rewrite against brain-redux d183246 impact map at stack 062646487. P1-P6/B1-B4 and engineering Q1-Q16 are mapped to eleven briefs. D9 replaces the earlier private O2-only context/per-document/share model: normal Case 2 access in any authorized thread/room, supporting writes intact, changed policy awaits PRD 1.17 approval. New DOCX story creation has the same opening gate as human per-story import. Host-only push to human-set off-host remote replaces the no-remote ban; remoteURL defaults unset and same-host bare is disallowed. W7 gates on Hermes #423 step5, W4b, PRD approval, post-10-27 and first-real-book go; owns conversion events COUNTED/--events/pre-conversion restore reconciliation, manifest order/next_chapter, creative role cite wording, archive/old-path edits and format/link/citation routing. Store+off-host acknowledgment precedes archive commit/push, then catalogue publication; post-push failures remain resumable pending with pinned source. Current checks pass: complete brief fields, policy/map coverage, exact Q234 CSP, locator/projection mechanics byte-equivalent except explicit authority wording, A01-A35 IDs, immutable map pin, four-doc scope and append-only logs. W4 authority/remote/recovery sections reopened for Fenton; older APPROVE not reused. No product/build/browser/worker/private-book/queue/live action. Earlier entry describing preserved shares/fence applies only to the pre-D9 intermediate draft; D9 now withdraws those unimplemented structures. + +2026-10-23T01:37:55Z | Gyro 571 push guard | identity gyro/purpose push: exit 0 documented degraded-pass CANNOT_ASSERT credential-unresolvable, scratch audit gyro-q195-ci-queue-audit.jsonl; no credential fallback or CI-green claim. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index e032a2071..3372e01a5 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -1552,3 +1552,5 @@ are never rewritten or removed; corrections are new entries. 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. 2026-10-22T23:09:38Z | Gyro (Codex gpt-6.1-sol, fenton-0006) | Q195 O2 design corrections on gyro/editor-o2 | F1 requirement boundary sent to Mos, adoption gated; F2-F6 source-checked docs fixes prepared. Ten briefs and two open owner items checked statically. No implementation, build/browser/worker run, queue or live action; Fenton re-check after push. 2026-10-22T23:13:27Z | Gyro (Codex gpt-6.1-sol, fenton-0007) | Q195 O2 r3 F7/F8 | Save-group keys/defaults/validation and W3b refusal/W4b lift ownership explicit. Static docs checks only. Q36 remains open; no implementation or gate lift. Direct Fenton/Mos handoff after push. +2026-10-23T00:52:58Z | Gyro (Codex gpt-6.1-sol, mos-1366/1367) | Vikunja571 Q235-Q237 O2 parent/W4 format-policy rewrite on gyro/editor-o2 | Canonical queue next gyro: nothing. Prepared P1-P6 and B1-B4 docs, baseline W4 import 1ac76a417; no product/build/browser/worker/private-file/queue/live action. Mos impact map fold precedes review/push handoff. +2026-10-23T01:37:07Z | Gyro (Codex gpt-6.1-sol, mos-1368/1372/1375) | Vikunja571 O2 parent/W4 revision complete for review | P1-P6/B1-B4 and A17-A41/Q1-Q16 folded; same-thread Case 2 lookups/support writes, human-set host-pushed off-host remote, Hermes/restore/counting/order/role gates. Static docs checks pass; old locator/projection mechanics retained, authority/access review reopened. No code, build/browser/worker run, private conversion, queue or live action. Direct Fenton/Mos/Sage handoff 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 322ec50f2..0ea9e7117 100644 --- a/docs/plans/2026-10-21_q195-writing-editor.md +++ b/docs/plans/2026-10-21_q195-writing-editor.md @@ -1,6 +1,6 @@ # Q195 writing editor: O2 design -Gitea #1752, Vikunja #448. Rewrite for mos-1356 and DECISIONS Q231/Q233. Jason chose O2, +Gitea #1752, Vikunja #448 and #571. Policy revision for mos-1366, Q234–Q237 P1–P6. 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. @@ -8,41 +8,56 @@ Base: `origin/refactor` at `c4f77373f9708037129c3918a3e72d2d71a96163`. Starting `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. +code, build, worker run, queue entry or live action. Q234–Q237 are confirmed owner policy. +The PRD amendment is Sage's Vikunja 570 and returns to Jason for approval before code relies +on changed Case 2 requirements. W4 baseline is `origin/refactor` 062646487, blob +`2af460ab772f8d204598dc8cb79b3c161f311623`; only conversion/format-policy sections change +in its companion `2026-10-22_q195-docx-citations.md`. Technical evidence anchors remain +pinned to c4f77373f unless another source pin is explicit. Impact source: brain-redux `d183246`, +`projects/mosaic-mvp/case2-docx-impact-map.md` at stack pin 062646487, mos-1368. This revision +reopens W4 M1, A19/A20/A28, remote durability and conversion-restore accounting for independent +review. Locator/extractor mechanics remain; the unimplemented private-share restore fence is +replaced by existing Case 2 authority and W7's durable conversion-registry recovery; prior APPROVE +is not approval of this changed context/tool/durability contract. ## Decisions and gates 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 +right-click thesaurus. It is not a reskinned row 154 editor. The first useful release, opened at W7 after the required gates, must pass writing, footnote, comment, tracked-change and page-layout save/reopen tests together. -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. +D2. Q210/Q220 allow design and review now. O2 builds remain after the October 27 MVP work +and never take its gate slot. S0 baseline clearance is conditional on M1–M14, Fenton/Filbert +at `origin/fenton/q195-s0` 74ec32013 (#1798, Sage PASS comment 30917). Q234 approves the +exact measured frame CSP; the shell stays unchanged. mos-1363 requires W2 to remeasure zero +violations with style-src 'self'; no rfd style hash is approved. These gates are satisfied +only for the pinned baseline/policy, not unbuilt adapters. No seat is assigned code by this +document. Changed dependencies or policy reopen the applicable independent gate. +D3. Q223/Q226/Q233 forbid agent story writes, replacement patches, DOCX comments/revisions +or conversion. Agents converse, flag, cite committed material and write supporting Markdown +under the existing Q223 scopes. W4/W4b and the approved Case 2 PRD remain prerequisites to +DOCX reads. mos-1372 D9 reopens W4: reads through Case 2 lookups use the same live business, +project, universe and source scope as Markdown, in any authorized thread/room. No O2-only +conversation, per-document grant or per-send share gates those reads. D9 is a marked choice +in PRD 1.17 for Jason, not an already approved tool/policy change. No unsaved-draft reader, +native WordCraft execute/save route or agent proposal that inserts story prose is introduced. -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. - -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. - -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. +D4. Pins and saved-context records stay on the bus through a reviewed schema change. +The human-only send setting defaults to a visible removable committed-context chip. It points +at a passage, not an authorization token or a cap on the agent's normal lookup rights. +Agents read committed versions only. Q222 settings/defaults remain human-only; none can +substitute for project/universe access, reviewed runtime readiness or first-real-book go. +D5. Q235–Q237 P1–P6 replace the old parallel-store proposal. The October 27 Case 2 release +and its Markdown requirements stay intact. After that release, Case 2 chapters/story files +use DOCX only, edited in O2. Supporting agent files, instructions, PRDs, documentation, +character sheets, summaries and agent-maintained cross-links remain Markdown under Q223. +Human-only one-way import archives and marks converted Markdown, never leaves two current +masters. Its first real use on Melanie's books additionally waits for Jason's explicit go. +No seat opens those books during design. `.doc`/`.qxd` legacy import stays D23's assignment. +The Case 2 PRD/brief amendment, reviewed implementation and W4b readiness precede conversion; +Q237's confirmation is not permission to convert private books now. ## Evidence retained and refreshed F1. Row 154 landed as `9353675d1` (#1648). Its source is @@ -53,7 +68,7 @@ source build remain the standard for O2 supply-chain review. Row 148's save rema 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 +F2. At the pinned c4f77373f baseline, Case 2 briefs had 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 @@ -94,15 +109,16 @@ DOCX gate still deliberately replaces J7's proposal to send rich-document contex lines. J6's requirement for Jason's CSP ruling remains intact. This input is not approval of this O2 rewrite. -## Security scope and exact CSP candidate +## Security scope and approved editor-frame CSP -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 +D6. S0 is the separate independent review by Fenton, reviewed by Filbert, neither a +source/adapter author. Its conditional baseline PASS does not clear implementation mitigations. 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. +inputs. S0 also inventories 10 build-only packages and 25 packages with build scripts; its +209-package license inventory and notice elections are binding, not just the 199 normal edges. 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. D7. The audit must trace native I/O and network paths even when cfg excludes them from WASM. @@ -125,48 +141,35 @@ code. Every implementation still gets independent code review, and W6 must prove 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. -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 rewrite. -S0 must measure before Jason is asked: serve Louie's existing artifact in an isolated scratch -harness with an externalized, reviewed bootstrap, under the exact candidate response header. -Do not rebuild WordCraft or mount the Console/live stack for that check. Try style-src 'self' -first after CSS externalization. Drop 'unsafe-inline' if the measured canvas/UI needs none. -Record browser/version, artifact/wrapper hashes, full headers and all CSP violations while -loading, embedding, editing the full-feature fixture, resizing and exporting a snapshot. -S0 must reach zero violations with required functions intact, or report the actual failures -and hold the question. The final measured header supersedes this source-inferred candidate. +D8. The current shell CSP is pinned at `packages/webui/src/serve.mjs:605`. Q234 approves +exactly this editor-frame response header, with the shell unchanged: -| Directive | Shell, unchanged | O2 iframe document only, proposed | -|---|---|---| -| default-src | `'self'` | `'self'` | -| script-src | `'self'` | `'self' 'wasm-unsafe-eval'` | -| style-src | `'self' 'unsafe-inline'` | test `'self'` first; retain `'unsafe-inline'` only if S0's measurement proves necessary (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) | +```text +default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; connect-src 'self'; font-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; frame-src 'none'; form-action 'none' +``` -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. +S0's measurement is `origin/fenton/q195-s0` 74ec32013, +`docs/reviews/2026-10-22_q195-editor-csp.md`. The unmodified artifact had an rfd inline-style +violation under style-src 'self'. mos-1363 rejects retaining that hash; host-owned Open must +remove rfd from the web path. W2 must remeasure zero violations with full function coverage, +including host-owned Print. Do not misreport the baseline as a zero-violation integration. +Externalize the module bootstrap/styles; remove embedded blob PDF preview. No inline script, +style hash, unsafe-inline, broad eval, worker or alternative-origin allowance is authorized. +Any change to this header or the shell goes back to Jason through Mos. No browser, build or +CSP experiment was performed for this policy rewrite. +M1–M14 in S0's security report and machine inventory remain mandatory with their exact rejection +tests. W2/W6 own proving them on the adapter, not reopening the elected license terms or +pretending a baseline conditional PASS already proves the patched build. M13's shipped notice +bundle covers 199 normal plus 10 build-only packages, fonts and the license elections. 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. +on success and every refusal path. Only the approved header is used. Frame mounting still waits for reviewed code and mitigation gates. -## Rich storage, saves and the Markdown boundary +## DOCX chapters, one-way import and Markdown supporting documents D10. The default document unit is one DOCX per chapter, grouped by a book manifest. Do not put a whole multi-chapter book into one default save ZIP. Canonical editable O2 content is DOCX in git, including styles, sections/page layout, @@ -175,60 +178,164 @@ managed document has a stable document ID and manifest naming its canonical DOCX source origin, format revision, current blob and commit. DOCX and manifest changes publish atomically in one commit. They are not two editable masters. -D11. Existing Markdown remains byte-for-byte at its current path. Human adoption into O2, gated by the open D12 decision and W4b PASS, -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. +D10's book manifest also owns chapter order. Seed from row216's existing path-order rule, +then keep stable chapter IDs in order across conversions; human reordering commits the +manifest. library_manuscript and next_chapter use this order, never archived paths. Each +answer/page names format, owned location/ID and captured commit. A visible Console Connections +view shows current authorized Markdown/DOCX links and backlinks with canon/playground/archive +labels. Obsidian's archive graph is historical, not the live chapter graph. No hidden scope's +titles/counts leak through the view. New Story chooses universe/book or playground and gets +its place in that manifest from its first DOCX commit, without an MD copy. -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. -Match wiki tokens across adjacent DOCX runs, including formatting changes within a token. -W3b adoption and W4 extraction must test split-run tokens, not scan each run independently. -First release: literal wikilinks are clickable through the host's owned-document resolver; -unmapped targets display unresolved and never fall through to a file path or external URL. -The retained Markdown keeps Obsidian's original graph only. DOCX edits do not update that -graph, so its links become historical after adoption. This stale-source issue is part of -D12's open notice decision, not a claim of live Obsidian graph parity. -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. +D11. Human-started, one-way import converts a Markdown chapter into canonical DOCX. The +source no longer remains editable at its old path. Move its unchanged bytes to the source +repository's human-set archive folder plus `` and mark it converted in a conversion +manifest. Keep original history intact. Never strip wiki tokens or overwrite source bytes to +hide conversion. Record source repo/commit/blob/path, archive path/blob, conversion date, new document ID, +DOCX blob/commit, book/project and operation ID. Preserve the same book/chapter identity: +keep an existing stable chapter ID, or allocate one once and bind the source alias to it. +The archive entry is read-only, labelled converted with date and replacement document ID; +the ordinary tree lists that chapter once, as DOCX, never as two editable documents. There is no sync back, parallel current +Markdown master, automatic reconversion or Convert back action. Git history is evidence, +not a supported reverse conversion. The conversion unit is one story file (mos-1367 B2): one fidelity report, human confirmation, +manifest and DOCX conversion commit for each. Its source-repository archive commit also +covers only that file; the operation receipt binds both commits without pretending they +are one git transaction. First import UI selects one file per operation. A future batch +picker may queue independent confirmations, never imply a reversible book-wide transaction. +`editor.archiveFolder` is human-only, default `archive/converted`, scoped to source project. +Validate a nonempty relative directory (at most 1024 characters), no absolute path, dot/dotdot, +.git, symlink/hardlink escape, current-file or supporting-write-target collision or destination +collision. Changing it never reclassifies older archives. Record the resolved owned archive +location in each conversion receipt. Book chapters remain one DOCX each. -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. +Preserve `[[target]]`, `[[target|label]]`, `[[target#heading]]` and embeds as exact literal +text with source-token metadata. Match across adjacent formatted DOCX runs. The human pushes and closes the source in Obsidian first and confirms it in the UI. +The service validates the exact source remote tip and its own clean transaction state; it +cannot inspect or guarantee that a private desktop buffer has no unpushed changes. A human reviews the conversion/loss report before publication; unhandled constructs refuse conversion before archiving. All front-matter keys move into +the canonical book manifest's chapter metadata (bounded validated fields plus preserved +extension values), with source bytes retained in the archive. type/name/appears_in/relationships +are indexed from that manifest, not lost or read from stale Markdown. DOCX custom properties +may mirror them but are not a second authority. A reviewed importer must cover headings, +emphasis, footnotes, lists, block quotes, scene breaks, raw HTML, embeds and URLs. Use row154's +reviewed markdown-it source for the parser plus a first-party AST-to-WordCraft-DOCX adapter; +never rely on WordCraft's measured lossy Markdown importer. Unsupported raw HTML stays an +explicit refusal, never executed. Fixtures cover every construct and independently compare +semantics/wiki tokens/metadata. Run W4's pinned extractor before the archive step; conversion +emits only v1-readable constructs and fails on extraction, quote, budget or link mismatch. +W3b and W4 test split-run tokens; W7 owns conversion fidelity for the source corpus. First-release clicks use the owned-document format map: +converted chapter target -> DOCX ID, supporting documentation -> Markdown, unmatched -> +unresolved. Never open a guessed file path, archived chapter or external URL as a current +link. Supporting-document cross-links keep their Markdown source bytes; resolver mappings +follow stable identities without an agent rewriting story links. -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 without a Case 2 amendment. +Obsidian's old Markdown graph is historical after conversion. It does not track later DOCX +edits, and it is not a parallel writing surface. The Console's authorized book/format map +shows current DOCX chapter relationships and Markdown support links. No Obsidian graph +parity or Markdown export is promised. `.doc`/`.qxd` imports remain separate D23 work. -OPEN with Jason as Q36 / Vikunja 562 (mos-1358, Fenton F1): leaving that original readable without a notice lets agents mistake -stale Markdown for the current chapter. Before W4b, the new current DOCX would also be -unavailable, contrary to Q226 F41's next-lookup availability. Recommendation: the O2 store -owns a superseded record `{sourceCommit,sourceBlob,sourcePath,documentId,adoptionCommit}`. -Case 2 library readers return a `superseded` notice with that record, and C2-06 displays it -on replies citing the old source. This notice behavior is not decided and must not be built -before Jason answers Q36. Keep original Markdown bytes unchanged. +D12. Q235–Q237 withdraw the superseded-notice proposal and its open-Q36 boundary. Current +Case 2 chapter reads after conversion use W4b's committed DOCX reader/citations. Agent +supporting-doc CRUD remains Markdown-only under Q223. No generic `.docx` path regexp, native +MCP or new story-write permission. This covers story drafts/playground files as well as canon chapters; P4's supporting-doc +exception is not a Markdown story-drafting exception. A draft/playground story keeps that +scope/status when converted to DOCX; conversion never promotes it to canon. Preserve the +source scope in the manifest and apply existing live project/universe access; no per-document +grant or per-send share is required for lookups (mos-1372 D9). W4's final +revision view is unrelated to draft-versus-canon status. The host-only DOCX store remains +`/writing///`. mos-1368 C4 replaces the no-remote ban with a +human-set off-host remote pushed only by the host process, unreachable to every seat token. +No object alternates or generic worker mounts. The exact host-only durability policy goes +into PRD 1.17 approval before conversion opens; this design does not provision that remote. Old Markdown bytes remain in their source git +history and converted archive as historical evidence, not O2 edits or current chapter input. +Do not copy later DOCX content into that archive/history or existing C2 sessions. -Mos ruling, mos-1358: human adoption of a Markdown chapter stays refused until W4b passes. -This is settled build order within O2, separate from Jason's open notice decision. If Q36 -approves notices, the reviewed notice path must also pass before that adoption workflow ships. Until this is resolved, do not adopt existing books -or present O2 as replacing the current Case 2 chapter workflow. Scratch/new-document fixtures -can exercise the human editor while this gate is closed. +After each file's conversion publication, the authorized format map is a typed host catalogue: `{documentId,kind,format,state,scope,location, +sourceCommit,conversionCommit}`. kind is chapter or supporting-document; current chapter +format is docx, supporting format markdown; state is current or converted-archive. scope distinguishes canon, playground, supporting +and archived without format-based promotion. Type-folder entity notes remain Markdown; +an unmarked-folder story is eligible for human selection, one file at a time (mos-1368 Q18). location +is an opaque owned location, never a host path/capability. Publish only entries the caller's +live scopes allow, no title/path leak from denied documents. Agents get this map through +reviewed library/universe lookup results and normal authorized Case 2 context so they know formats +and locations. The checked Case 2 query adapters reuse W4's exact committed-reader/locator primitives; +there is no native-engine or raw-store access. General current catalogue, +find/get/search/manuscript, graph and chat selection exclude archived Markdown chapters. +mos-1367 B4 adds an explicit `archived` read scope. It returns only requested archive records, +subject to the caller's live authorized source/archive scope, always marked archived/historical +and `canon:false`. It cannot supply canon quotations, satisfy a current-chapter citation, +join a manuscript or enter a default search. Archive requests still need normal project/universe/archive-scope access; a converted +identity alone is not permission. Preserve source commit/blob provenance, never add later DOCX edits to an archive. +An old current-chapter path/identity lookup returns a typed conversion record and routes +chapter reads to W4b in the caller's authorized Case 2 thread/room. No special writing conversation or share +is required (mos-1372 D9); no stale Markdown is returned in place of the current DOCX. Metadata also +requires scope; archive access alone grants no current DOCX read outside the normal project/universe scope. The record is routing, +not a stale-text response or the withdrawn banner. No DOCX-as-lines or implicit context share. +Old commit-bound citations stay historical and cannot become current context or a new grant. +This is format routing and refusal, not the withdrawn superseded-notice/reply-banner design. -These reader/reply changes alter Case 2 semantics and are a recommendation for Mos to take -to Jason, not authorized by this O2 brief. No row here owns the C2 reader/reply changes. -Sage adds their exact paths and acceptance through a separately approved brief amendment -only after that ruling. A synchronized Markdown projection is not an implicit fallback. -This open item remains alongside CSP in the owner checklist until Mos resolves it. +W7 owns the post-MVP routing/conversion change under Sage's approved PRD amendment. It stages +the validated DOCX store commit first, then the source archive commit/push through the +existing human bus writer, before one authoritative catalogue publication +switches current chapter identity to DOCX. Readers capture that publication generation: +before the switch the old Markdown is current; after it only the committed DOCX is current. +The first DOCX commit is on an import staging ref, not an active document publication. +Only final host publication advances W4's writing-published ref and catalogue under its +publication/read lock; authorization rejects staged conversion IDs until the catalogue CAS +succeeds. If interrupted between those writes, durable pending state still serves the old +snapshot and hides the staged DOCX until recovery. Staged DOCX artifacts are invisible to readers. Conversion holds the served source snapshot +at its recorded commit; normal mirror sync cannot advance that chapter snapshot during the +pending operation. A pre-archive refusal leaves Markdown unmoved. After the archive has been +pushed, no failure may claim nothing moved: return an operation receipt with pending/recovery +state, preserve both commits and finish through idempotent readback. Do not attempt a rollback +push or reverse conversion. Keep the old served snapshot current until final publication. Cache keys bind the publication generation; recheck it +immediately before emission. A query paused across conversion must retry/refuse as current +Markdown, never return an old cached chapter as current. A stale source/base refuses. The switch cannot occur until +archive marking, DOCX, normal project/universe access, reader/citation readiness and map all verify. If +repositories differ, use a durable host-only operation journal and CAS publication; never +claim git makes two repositories atomic. A crash before publication leaves the old published +snapshot current and blocks new chapter mutations until recovery completes. After publication, +retries read the receipt and never reconvert or restore a Markdown working copy. Test every +journal/commit/publication crash point. No observable gap or two current masters. Tests cover a sync tick immediately after archive +push, failure before final publication, and recovery after readiness changes. Irreversible +archive effects remain visible in operation status; recovery never says the archive was undone. +The durable conversion journal/format registry lives outside bus release backups. W7's +release preflight refuses a reader/writer version that cannot enforce converted state on +that project. Restoring an older bus/mirror snapshot cannot revive Markdown as current or +reverse the conversion record; require compatible recovery that rechecks the journal and +existing stack restore/grant rules and W7's conversion-registry reconciliation. No claim to stop privileged manual history tampering. + +Production conversion requires all of: after October 27 release, approved Case 2 PRD/brief +amendment, W4b PASS and live committed-reader/citation readiness, W7 reviewed import/routing +release, Hermes retirement (#423 step 5, with its old write/store access removed), verified +host-only off-host durability and an authenticated human start. `library.convert` is a +human-only CLI/Console verb run through the host async processing adapter, outside agent +vocabulary/role grants and off the read-verb list. Its action remains a hard wait under +REQ-WAIT-2/3 until the approved PRD says otherwise; it never joins ROUTED silently. +`editor.conversionHumans` is human-only, default business owner only. Folder setting/mapping +have one authoritative archive-prefix value; the library mapping and editor cannot disagree. +Archive prefixes cannot overlap playground/supporting prefixes. Conversion preserves bytes +and history rather than deleting data, per Mos's PRD reading. No seat retires Hermes or +starts a conversion under this design assignment. The first real conversion of Melanie's books +also requires Jason's recorded go bound to the selected book scope. No agent/tool or ordinary setting/request flag can substitute for these release/go gates. Initial missing/revoked readiness refuses before any archive, conversion commit or catalogue +mutation. In-flight readiness loss after archive push follows the pending recovery protocol, +never a false no-mutation refusal. Scratch fixtures remain testable in an +isolated store inaccessible to production routes. Design approval never starts conversion. +Human New Story also waits for this opening gate (mos-1372 D2). It chooses a permitted +universe/book or playground and creates DOCX plus its manifest from the first commit, with +no Markdown copy or archive move. It keeps the selected scope, uses the human's author +identity and normal local-commit/remote-push receipts. Type-folder/supporting notes remain +Markdown. The first real-book go covers the selected book's production opening, not a request +flag on either API. Before that gate, only isolated fixtures can create/import stories. + +Import requires the human to push and close Obsidian before confirming the exact source tip; +no seat surveys/reads the private working tree. The UI makes that precondition explicit. +A user may still push edits with her own tools later. Sync flags changed archive blobs and +Markdown recreated at a converted old path; neither becomes canon/current, syncs to DOCX or +triggers conversion. Console Markdown save refuses every archive path. Newly created .md +story files in converted manuscript locations are flagged awaiting import and excluded as a +second current chapter; no auto-conversion. Preserve unexpected bytes for human resolution. +A new problem-state version records these states while keeping R1–R7 meanings fixed; W7 +owns the migration and tests, not a silent new code in the v1 state parser. D13. Setting `editor.commitCadenceMs` is human-only in UI and CLI, default 0. Zero means submit immediately when a save group closes, not on every keystroke. WordCraft coalesces @@ -246,7 +353,7 @@ never whether an accepted save commits immediately. Ctrl/Cmd+S flushes the curre without delay. In-flight save snapshots are immutable; later groups queue in revision order. The UI marks unsealed typing as unsaved, never Saved. No save waits for a later batch after acknowledgment or for an agent turn. Unchanged revisions are status reads, not save requests. -No source or message text in logs. W3b measures the tradeoff rather than assuming compressed +No source or message text in save/audit logs. W3b measures the tradeoff rather than assuming compressed DOCX commits delta efficiently. Mos's reading of Q226 F41, mos-1359: with cadence 0, each closed save group commits at once, @@ -262,13 +369,25 @@ and committed-reader index before replying Saved. That ref is the source for the 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. -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. +mos-1368 C4 / mos-1372 D7 / mos-1375 resolve the Q176 conflict: `editor.remoteURL` is a +human-only setting, default unset. Only the host process pushes; agents never push. The URL +points off the stack host, for example a private Gitea repo. A same-host bare/filesystem or +loopback repo cannot be the default or qualify. A human provisions/selects the private +remote and host-only auth before production opening; neither is created by this design. Only the stack host has its push credential; no seat grant/account/token +can list, fetch, clone, fork or push it. Do not expose its credential/URL through the frame, +tool responses or logs. Allow only the configured host-owned remote, verified branch and +fast-forward CAS push; refuse object alternates, unexpected remotes and divergence. Each +accepted local save commits/publishes immediately; host push follows without a human action. +Receipts distinguish locally committed from off-host synced and expose retry/readback status, +never call an unpushed commit durable. A human-only remote retry deadline defaults 30 seconds; +failed push preserves local commits and blocks conversion, with a visible pending sync status. +Before irreversible archive push, the staged DOCX commit must already be acknowledged by +the off-host remote. Source archive push uses the separate existing human library writer. +No force push or seat-token fallback. W3b tests remote acknowledgment, outage/divergence, +restart recovery and absence of seat access; W7 proves remote-ready state before archiving. +The human-set remote covers the DOCX git store/history/manifest. Ordinary Case 2 messages, +run evidence and supporting notes keep their existing approved storage policy; the old W4 +private-only/no-backup transcript model is withdrawn. Stack-copy is not a story backup. Deployment/provisioning is separate. 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, @@ -306,7 +425,7 @@ snapshots may cross to the human host for saving; never to the agent or chat by Selection locators for agents resolve against a returned committed blob, not live WASM text. 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 +Use `sandbox="allow-scripts allow-same-origin"` under S0 M7. It does not prevent 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. @@ -359,25 +478,25 @@ measured `.doc` comment loss must be disclosed. Neither WordCraft nor DesignCraf 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. +D24. Native WordCraft MCP is not an agent bridge. After W4/W4b and PRD approval, the checked +reader backs Case 2 find/get/search/manuscript/universe lookups in any authorized thread or +room. Standard library_doc_write/delete still write only supporting Markdown. The host +applies existing live project/universe/source-scope checks before every extraction/index hit +and reply; no per-document grant/share or special conversation is required. No raw store +mount/git credential/native execute channel reaches an agent. October 27 Markdown semantics +stay intact; after conversion old source lookups return the conversion record and current +DOCX, with explicit historical archived reads separated. Store access is host code only. 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 +or comment stories. Use W4's mandatory paragraph ordinal with xmlId as a cross-check within that +exact part/blob; an ID alone is never the lookup key. 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, split-run wikilink matching, tracked-change reading view (default final accepted reading, source revision history +W4's separately reviewed design fixes the precise XML/relationship allowlist, paragraph +ordinal/xmlId verification, split-run wikilink matching, 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. @@ -385,13 +504,13 @@ Tests must independently recompute locators from a committed fixture, distinguis 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. +D26. The human-only send setting defaults visible-chip-per-send. Before DOCX readiness, +no draft/selection metadata is exposed. Once enabled, chips point only at verified committed +ranges. A live selection that cannot map to a committed locator sends no draft substitute. +The chip is convenient context, not a grant and not a restriction on authorized Case 2 +lookups. A latest lookup after a save returns that local publication or later, independent +of an older chip. Historical citations retain their immutable commit. Multiple authorized +threads, rooms and humans follow the existing Case 2 controls (mos-1372 D9). 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 @@ -414,7 +533,8 @@ At DesignCraft `3ce3a24f08d03935bc8cf7cb23755aca8065558c`, 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. +MCP handoff. Jason's later layout agent needs a separately approved content handoff and pinned source commit. +The host-only remote/private-store boundary is not bypassed by a layout workspace or Gitea clone. 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 @@ -424,9 +544,10 @@ runs Jason's layout agent nor automatically grants it access or sends book text ## 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 +All rows follow BRIEF-TEMPLATE. They are not queue entries. S0 M1–M14 remain binding throughout W2/W6; source/target +changes return to security review. W7 adds the policy conversion/routing row. S0 and the original W4 design have reviewed verdicts; this policy revision goes to Fenton. +Their implementation gates remain separate. No code row W1/W2/W6/W3a/W3b/W3/W4b/W5/W7 enters the queue +before S0 PASS (recorded for this baseline, with M1–M14 still binding). 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. @@ -435,7 +556,8 @@ G1. Future code acceptance runs each touched test file independently and affecte 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. Integration browser proofs use scratch fixtures only, after the CSP ruling. S0's pre-ruling scratch measurement -of the existing artifact is separate and precedes the exact-delta question. Tests never use a live stack, private +of the existing artifact is prior evidence; Q234 settles the exact header. W2 remeasurement +is still mandatory under mos-1363. 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 @@ -447,9 +569,8 @@ An independent source and trust-boundary review is a prerequisite, not a build s ### Owner and reviewer -- 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. +- Owner: Fenton, independent Opus 5.5 security-review seat, not a source/adapter author. +- Reviewer: Filbert, independent Opus 5.5 reviewer. - After: no build dependency. Review the exact pinned source and existing evaluation artifacts. ### Files owned @@ -461,35 +582,28 @@ An independent source and trust-boundary review is a prerequisite, not a build s ### 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. Execute D8's isolated existing-artifact measurement -before the CSP question, including the narrower style policy trial. After preliminary source -safety review, run with fixture-only data, no credentials and no external network. Own the scratch harness -under `/mnt/storage/scratch/q195-csp-review//`; keep its source/hash/header/violation -receipts in the review report. No WordCraft compilation or Console policy change. Distinguish -source inference from actual browser evidence. Zero CSP violations and complete required -function coverage are necessary for a measured-policy recommendation. -Review all 15 crates, all 199 target dependencies and applicable fonts/build scripts/notices. - +Completed baseline evidence is pinned at 74ec32013 in `origin/fenton/q195-s0`: inventory, +license elections/notices, native I/O/network analysis, conditional PASS and M1–M14 rejection +tests. The companion CSP report records both the rfd violation and measured alternative; +mos-1363 rejects the style hash and Q234 approves only style-src 'self'. W2 must remove rfd +and remeasure zero violations with full function coverage. Do not overwrite S0's report or +claim its baseline was already violation-free. A changed source/target returns for review. ### Out of scope Production code, a relaxed live policy, source imports, compiling WordCraft/O2, private -files and an approval on Jason's behalf. No queued build row until this review passes. +files and an approval on Jason's behalf. Conditional baseline PASS does not clear any W mitigation. ### Gate -Sage records PASS only on both independent review reports with no unresolved blocker and -explicit required mitigations and the pre-ruling measured header/zero-violation evidence. -Mos then asks Jason the exact CSP question. D12 remains a separate open Case 2 item. A failure -holds every O2 build row. Changed target dependencies or a wider CSP re-open this gate. - +Sage recorded baseline PASS on #1798 comment 30917, conditional on M1–M14. Q234 clears the +exact header gate. Every mitigation and independent implementation review remains required; +changed target dependencies or any wider CSP reopen review/owner approval. W2's zero-violation +adapter remeasurement is still a release gate, not a baseline result claimed here. ### 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. +Copy Mos if source/policy changes require a new Jason ruling. Q234 remains the approved header. ## W1 reviewed local thesaurus data @@ -558,7 +672,10 @@ expand the reviewed 199-package target unnoticed. No dist/target or unreviewable 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 +Carry S0 M1–M14 into the source/adapter build acceptance, including M13's full notices. +Do not call rfd on the web. Remeasure the build with the exact Q234 header, zero CSP +violations and full function coverage including host-owned Print (mos-1363/M5/M8). +A style hash is not a fallback. Two different absolute roots must yield identical integration outputs. New sizes are measured; the 44,179,239-byte baseline is not promised after patches. All served runtime HTML/JS/CSS/WASM/fonts/data land in shipped `src/public/wordcraft/`; the route never reads unshipped `wordcraft/` or `third_party/` build-input directories at runtime. @@ -620,7 +737,7 @@ Native MCP/TCP, alternative origin, extra CSP allowances, agent document access ### 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 +header/bridge/full-feature tests and G1. M1–M14 include the malformed-input/font/print corpus. A missing required Word feature or a new CSP need blocks release and returns to Mos. No silent feature cut or security exception. ### Handoffs @@ -660,7 +777,13 @@ Reuse verb-sensitive ownership/grant checks. Stale grant/path/thread redacts con 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 `editor.commitCadenceMs` 0, `editor.saveGroupPauseMs` 2000 and `editor.saveGroupMaxMs` 15000, -sharing visible-chip-per-send and require-citation off. UI/CLI use the same backend validation. +`editor.archiveFolder` archive/converted, `editor.conversionHumans` owner-only, +`editor.markdownImportMaxBytes` 1048576 (1..16777216 integer), +`editor.remoteURL` unset/off-host-only, `editor.remoteRetryDeadlineMs` 30000 (1000–300000 integer), sharing visible-chip-per-send and require-citation off. UI/CLI use the same backend validation. +The archive-folder key uses D11's path/collision checks and one canonical library-mapping +value. Validate allowed human IDs and remote destinations against owned projects/host policy; +no setting grants agent story writes or substitutes for release/go authority. +All new keys have UI/CLI default/change/boundary/unknown-key/agent-refusal tests. Both save-group keys use D13's bounds and cross-field validation. Test defaults, valid changes, fractional/nonfinite/out-of-range values, pause > maximum, stale settings versions and agent write refusals for each key through both interfaces, with prior values preserved on refusal. Migration/restore, grant revocation, tester separation, concurrent repin, @@ -700,8 +823,8 @@ preserve full rich state via Markdown round trips. Next-lookup visibility needs ### Files owned `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/writing/src/{git.mjs,store.mjs,settings.mjs,convert-markdown.mjs,new-story.mjs,remote.mjs}`, +`packages/writing/tests/{store.test.mjs,convert-markdown.test.mjs,new-story.test.mjs,remote.test.mjs,fixtures/}`, `packages/bus/src/{broker.mjs,client.mjs,server.mjs}`, `packages/webui/src/{cli.mjs,writing-http.mjs}`, `scripts/stack-copy.sh`, `packages/cli/tests/stack-copy.test.mjs`, @@ -710,19 +833,20 @@ preserve full rich state via Markdown round trips. Next-lookup visibility needs ### What ships -D10-D15: authenticated human open/adopt/save/readback operations, exact schemas, one immediate +D10-D15: authenticated human open/convert/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. -W3b ships the production adopt verb closed: refuse adoption of every real project document -with `editor-adoption-unavailable` until the reviewed W4b release passes, per mos-1358. -Refusal tests assert no DOCX, manifest, git commit or superseded record is created and the -Markdown stays byte-identical. Test the actual human API, not just a hidden button. No human -setting or request flag can lift this gate. Pure fixture conversion remains testable through +before Saved. New writing store stays outside worker roots; all agent reads refuse before W4b. Local save and off-host sync use D14's distinct receipts. +W3b ships production conversion and New Story closed for every real project +with `editor-conversion-unavailable` / `editor-create-unavailable` until W4b/W7 and all D12 gates pass. +Refusal tests assert no DOCX, manifest, git commit or conversion record is created and the +Markdown remains current and byte-identical on refusal. Test the actual human API, not just a hidden button. No ordinary setting or request flag can replace the required go/readiness receipts. Pure fixture conversion remains testable through an isolated scratch store unavailable to production routes; a caller cannot label a real -project as a fixture. W4b owns the later release of the production refusal. -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 +project as a fixture. W4b supplies reader readiness; W7 owns the final import/New Story release/refusal tests. +Fixture gates also exercise store-before-archive and archive-before-publication crash states; +no production route can call the fixture bypass. +Tests cover comments/notes/revisions/layout, every wikilink fixture form, byte-identical archived +Markdown and manifest front matter, malformed DOCX/ZIP limits, no-op status, stale base, lost replies, +backpressure, rapid autosaves and unexpected/unreachable remotes, seat-token denial and object alternates. 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. @@ -738,7 +862,7 @@ W4b/W5 retain this same separation and rerun the closure/no-store-mount checks. ### Out of scope -Case 2 reader/mapping changes, synchronized Markdown projections, native legacy import, +W7's Case 2 routing/archive publication, synchronized Markdown projections, native legacy import, agent reads/writes, deployment and a relaxed CSP. ### Gate @@ -751,7 +875,7 @@ input, notes/comments/revisions and explicit Save. Report document ZIP size and history size before/after git packing, with the actual save-group settings. No assumed delta compression or fixed capacity claim. Independent review accepts the measured defaults before release. Pinned-copy asset/service tests and sandbox import/mount checks pass. Static ownership -checks prove no generic agent root includes the store. D12's adoption gate remains closed. +checks prove no generic agent root includes the store. W7 owns the final D12 conversion gate. Any Case 2 requirement change follows D12 to Mos and Jason before implementation. ### Handoffs @@ -775,19 +899,19 @@ A restricted engine and writer are not yet an all-day writing workspace beside p `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/{writing-pane.test.mjs,writing-browser.test.mjs,chat-browser.test.mjs}`, +`packages/webui/tests/{writing-pane.test.mjs,writing-browser.test.mjs,chat-browser.test.mjs,writing-connections.test.mjs}`, `packages/webui/README.md`. ### What ships -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 +D10/D16-D22's navigation and Connections view, familiar full WordCraft surface, splitter, settings controls, save/sync +status and local right-click/ribbon thesaurus. Two distinct DOCX chapters keep their separately pinned ordinary 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. Test click-through wikilinks split +page layout and local synonyms must all save and reopen. A converted chapter appears once; its labelled archive cannot be edited. Test click-through wikilinks split across formatted runs and unresolved-target refusal. No first-release deferral of those -features. Distinguish retained Markdown source from the canonical DOCX working document. +features. Show conversion/archive status and current DOCX identity without offering an archived Markdown editor. ### Out of scope @@ -796,7 +920,8 @@ Raw session views, the retired board writer, row 5/row 29, legacy import and age ### Gate 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. +suite and G1. The first real human release is W7 after opening gates, not this candidate alone. This is the first useful human O2 writing slice for the full DOCX workspace, not W2's baseline build alone. +Production New Story and import both stay closed until W7's opening gate and Jason's first-real-book go. ### Handoffs @@ -812,8 +937,8 @@ No agent access is allowed until this design is reviewed, even if the human edit ### Owner and reviewer -- 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. +- Owner: Rocko, Codex gpt-6.1-sol, for the original W4 design; Gyro owns this assigned policy delta. +- Reviewer: Megavolt for the original design; Fenton, independent Opus 5.5, for this policy delta. - After: no code dependency. Design/review may proceed now under Q210/Q220. ### Files owned @@ -824,10 +949,11 @@ No agent access is allowed until this design is reviewed, even if the human edit ### What ships A complete separate design for D24-D26, with exact locator/extraction schema, story/part -classification, grant/share semantics, committed-only visibility, reading views, validation, +classification, existing Case 2 authority, 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 +new O2 source copies, generic reads, git grants and raw sessions. The October 27 Markdown path +stays unchanged; after W7, archived source is never current context. DOCX routing uses the +reviewed format map and committed reader, preserving Markdown supporting-document CRUD. 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. @@ -840,8 +966,8 @@ Agent read enablement, code, live docs, story replacement proposals and a CSP ru 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. Resolve D12's superseded-source/adoption -requirement through Mos and Jason, with separate C2 reader/reply ownership before adoption. Outer O2 plan approval alone does not pass W4. +Only after that review may W4b implement access. Apply D12's confirmed one-way/archive policy through W7 and the approved PRD amendment. +The superseded-notice proposal is withdrawn. Outer O2 plan approval alone does not pass W4. ### Handoffs @@ -863,9 +989,9 @@ An approved DOCX citation design still needs enforcement across bus, tools, gran ### Files owned -`packages/writing/src/{read.mjs,citations.mjs,index.mjs}`, -`packages/writing/tests/{read.test.mjs,citations.test.mjs}`, -`packages/writing/src/adopt-markdown.mjs`, `packages/writing/tests/adopt-markdown.test.mjs`, +`packages/writing/src/{read.mjs,citations.mjs,index.mjs,queries.mjs}`, +`packages/writing/tests/{read.test.mjs,citations.test.mjs,queries.test.mjs}`, +`packages/writing/src/convert-markdown.mjs`, `packages/writing/tests/convert-markdown.test.mjs`, `packages/bus/tests/writing-save.test.mjs`, `packages/webui/tests/writing-save.test.mjs`, `packages/bus/src/{broker.mjs,store.mjs,server.mjs}`, `packages/bus/src/migrations/.sql` (edge allocated by Sage at landing order), @@ -881,34 +1007,32 @@ An approved DOCX citation design still needs enforcement across bus, tools, gran ### What ships 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 +intersection and existing project/universe/source-scope checks. Access stays off until +extractor/resolver/query readiness and the approved PRD pass together. No per-document +access/share/conversation tables are added for D9. 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. -W4b owns lifting W3b's production adoption refusal only in its independently approved release, -with server-owned readiness for the committed reader, citation resolver and sharing enforcement. -No agent, human setting or request flag asserts readiness. Q36 unresolved keeps adoption closed. -If Q36 approves notices, lifting also waits for the separately approved C2 notice row to pass; -otherwise follow Jason's recorded Q36 disposition without inventing a notice implementation. -Tests prove refusal before readiness, after revoked/missing readiness, and while required notice -readiness is absent; a ready authorized human adoption succeeds and its new committed DOCX is -readable through the checked tool on the next lookup. Keep isolated fixture adoption available. -Run both package and human API refusal/success tests. This row owns the adoption module/tests -listed above after W3b's handoff. No gate is lifted by this documentation change. +W4b supplies server-owned committed-reader/citation/query readiness, not permission to +convert a real book by itself. Tests keep production conversion refused until D12's post- +October-27/W7/PRD/human-start gates pass; W7 then owns the final lift. No setting or request +flag asserts readiness. The first Melanie conversion still needs Jason's go. Readiness loss +refuses new conversion while preserving existing committed documents and denying unauthorized +reads. Run fixture readiness/revocation tests plus human API refusal tests. W7 takes the +conversion module/tests after W3b/W4b handoff. No gate is lifted by this document. ### Out of scope -Expanding Case 2 Markdown semantics without its own approved amendment, unsaved reads, +W7's post-MVP conversion/routing release, unapproved Case 2 amendments, unsaved reads, native MCP and agent story writes. ### Gate Independent policy/parser/tool review, writing/bus/harness/business/WebUI tests and G1, plus -fixture bypass probes and the production adoption refusal/lift tests. No partial rollout where -UI hides context but another tool can read it, or adoption succeeds before all required gates. +fixture bypass probes and the production conversion readiness/refusal tests. Reopen W4 M1/A19/A20/A28 for query/supporting-write and durability changes. No partial rollout +where UI hides context but another tool can read it, or conversion succeeds before all gates. ### Handoffs @@ -965,20 +1089,185 @@ blob before and after every agent flag/chat operation. Human story edits still c 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. -## Current verification and Jason's remaining item +## W7 human one-way chapter import and Case 2 format routing -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, the CSP question and open D12 item, documentation-only scope and append-only logs. No security PASS, -CSP approval, DOCX citation approval or implementation acceptance is claimed here. +### Problem -Q1. After S0's scratch measurement passes, approve its exact editor-frame CSP header with -the shell unchanged? Recommend only the measured WASM compilation and same-origin framing -allowances, embedded PDF preview disabled, and no inline-style allowance if the narrower -trial works. Use the full measured header, not D8's source-inferred candidate. +Q235–Q237 require DOCX-only current story files after conversion. An archived Markdown +chapter must not survive in current library search, manuscript, citations or wiki navigation. +The source archive and private DOCX repository cannot publish atomically through git alone. -Q2. OPEN with Jason as Q36 / Vikunja 562: approve superseded notices in C2 readers and -C2-06 replies citing adopted sources? Recommend yes. Original files stay unchanged. No notice -implementation before that ruling. Separately settled by Mos in mos-1358: refuse human -Markdown adoption until W4b passes. That build-order gate is not another Jason question. +### Owner and reviewer + +- Owner: a Codex gpt-6.1-sol seat assigned by Sage for conversion/publication and authorization. +- Reviewer: Fenton or another independent Opus 5.5 seat assigned by Sage, not the code author. +- After: W4b, W3, approved Case 2 PRD/brief amendment (Vikunja 570), October 27 release and + C2-01d/01e/01f, C2-02/03b/04/05a/05b/06/10b/11a/11b file-owner handoffs. No MVP slot priority. Hermes retirement #423 step5 and verified off-host remote are required. First real books + also need Jason's go; production New Story shares this gate. + +### Files owned + +`packages/writing/src/{convert-markdown.mjs,import-markdown.mjs,new-story.mjs,conversion.mjs,format-map.mjs,opening.mjs}`, +`packages/writing/tests/{convert-markdown.test.mjs,import-markdown.test.mjs,new-story.test.mjs,conversion.test.mjs,format-map.test.mjs,opening.test.mjs,fixtures/}`, +`packages/library/src/{index.mjs,reader.mjs,scope.mjs,links.mjs,mirror.mjs,sync.mjs,mapping.mjs,render.mjs,problems.mjs,index-build.mjs,query.mjs,guard.mjs,supporting.mjs,write.mjs,survey.mjs,format-router.mjs}`, +`packages/library/tests/{reader.test.mjs,scope.test.mjs,links.test.mjs,mirror.test.mjs,sync.test.mjs,mapping.test.mjs,render.test.mjs,index-build.test.mjs,query.test.mjs,guard.test.mjs,supporting.test.mjs,write.test.mjs,survey.test.mjs,format-router.test.mjs,helpers.mjs,fixtures/mapping.json}`, +`packages/bus/src/{broker.mjs,server.mjs,runtime.mjs,client.mjs,store.mjs}`, +`packages/bus/schema.sql`, `packages/bus/src/migrations/.sql` (Sage allocates at landing), +`packages/bus/tests/{writing-save.test.mjs,chapter-format.test.mjs,schema.test.mjs,conversion-events.test.mjs}`, +`packages/harness/src/tools.mjs`, `packages/harness/tests/chapter-format.test.mjs`, +`packages/business/src/{vocabulary.mjs,business.mjs}`, +`packages/business/tests/{vocabulary.test.mjs,business.test.mjs,hard-waits.test.mjs}`, +`scripts/mosaic`, `packages/cli/src/library.mjs`, `packages/cli/tests/library-convert.test.mjs`, +`roles/{companion,continuity,fact-checker,ideas,proofreader,research}.md`, +`packages/webui/src/{writing-http.mjs,library-http.mjs,cli.mjs,serve.mjs,bus.mjs}`, +`packages/webui/src/public/{writing-pane.js,bus.js,chat.js}`, +`packages/webui/tests/{writing-save.test.mjs,chapter-conversion.test.mjs,editor-context.test.mjs,library-cli.test.mjs}`, +`packages/seat/tests/sandbox.test.mjs`, `packages/cli/tests/stack-copy.test.mjs`, +`scripts/stack-release.sh`, `packages/cli/tests/stack-release.test.mjs`, +`packages/library/README.md`, `packages/writing/README.md`, `packages/webui/README.md`, +`docs/case2/{SETUP-SHEET.md,SURVEY-RUN.md}`. + +### What ships + +D11/D12's human import and conversion manifest/journal, exact-source archive with converted +marking, authorized format map and one CAS publication. Consume W4b's live readiness and +existing live project/universe access checks. W7 takes convert-markdown from W3b/W4b serially. Conversion is a human-only verb outside the agent vocabulary, with no role grant or agent +request path (mos-1367 B3). No agent can convert, archive, choose current chapter state or +reverse conversion. The human runtime adapter uses processing.work/async completion, not a +loop of single-path library.file.save calls for the move plus marker commit. Agent-visible format-map/archive read tools cannot call that verb. The format map and +chapter reader are host services, never mounts/imports added to the sandbox or raw git grants. + +Current library catalogue/find/get/search/manuscript and wiki resolution select DOCX chapters +through W4b and Markdown supporting documents through existing read scopes. Exclude +all recorded human-set archive locations before ordinary mapping classification; a permissive supporting-doc glob +cannot reclassify an archived chapter as current documentation. Converted path/identity lookups return the conversion record and route to the checked DOCX +reader with normal access checks; they never return stale Markdown or fake DOCX lines. Explicit archived-scope requests may return only +requested, authorized archived records, always marked and never usable as canon citations. +Test archive-folder changes, archived-scope filters, quoted archived text and supporting-doc +wildcards so none silently becomes current canon. Existing authorized Case 2 threads/rooms route the converted identity through W4b +under their normal project/universe checks; no dedicated conversation is needed. Agent-maintained character sheets/summaries/cross-links remain Markdown and writable +only inside their supporting scope. mos-1372 D9 replaces M1's dedicated-session/per-document/per-send gates, so the normal +read-story then write-character-sheet workflow works under existing Case 2 authority. +Never allow that writer to target DOCX or archive files. + +Tests prove all P1–P6, per-story-file reports/confirmations/manifests/commits, human-set archive folder, +archive blob equality/history retention, human loss-report confirmation, +wiki tokens/front matter/metadata and draft/canon-status preservation, converted-marker discovery, map scope filtering, +link graph routing, no sync back/current Markdown editor, source CAS conflicts, in-flight/cached pre-conversion query invalidation and idempotent +request readback. Kill at every stage/publication boundary: before switch serve the captured +old Markdown; after switch serve committed DOCX only; crash recovery never presents two/zero +current masters. No production fixture bypass, request-based go flag or agent-started import. +The first real-book go must be Jason's durable scoped authorization, not this design or a test. + +W7 records `writing_conversion_events` as the STRICT append-only metadata table specified +in W4 section 7.4, adds it to schema/migration tests, stack-release COUNTED and T46, and counts +conversion stages toward --events. Its durable host journal/format registry survives an older +bus restore. Test the third case explicitly: convert, then rollback --restore a pre-conversion +backup, losing the bus conversion event while archive and DOCX commits remain. The normal +counted-event approval/loss protocol applies; reconcile immutable commits/journal with new +recovery events before lookups resume. Never revive Markdown or replay authorization grants. +Old release capability preflight must refuse converted projects it cannot interpret. + +Update the six creative .md role contracts' obsolete 'Every item cites the lines' text: +free chat under requireCitation, checked Markdown line cites or DOCX locators as appropriate, +source format/scope from the map, archived never canon, and no story/conversion write. Roles +still use only their approved lookups/message/supporting-write tools. Schema/role expansion +waits for the approved PRD, and existing role JSON never grants library.convert. Expose the +human CLI/Console conversion verb through runtime/processing.work and async readback, not +the agent tool list. Hard-wait tests are at business/tests/hard-waits.test.mjs:22; the new +action remains GATED_ONLY unless the approved PRD explicitly changes it. + +The importer lives at `packages/writing/src/import-markdown.mjs`, owns a reviewed AST mapping +from vendored markdown-it to the WordCraft DOCX model, and validates source token/metadata, +output extraction and all losses before archive push. No pandoc runtime dependency or +unreviewed WordCraft Markdown import. Source input defaults 1 MiB under human setting; +output uses D15's operational bound and W4's ZIP/XML safety ceilings (32 MiB compressed/128 MiB expanded, with its per-entry, ratio +and parser bounds); conversion also respects D15's lower operational DOCX default. No real-source census +is run here; survey gains aggregate awaiting/archived/construct counts for fixture validation +and later human-authorized local use, without snippets. Preserve type/name/appears_in/ +relationships and all extension metadata in the manifest. Index hybrid exclusions by stable +DOCX ID, retain R5 canon-to-playground/R6 universe checks and existing entity-note pin behavior. +Secret checks run on extracted text/metadata, not on ZIP bytes alone. + +### Out of scope + +Actual conversion of private books, executing Jason's go, code before PRD approval, a live +cutover, `.doc`/`.qxd` legacy import, superseded banners, Markdown projections or new agent +story-write rights. No raw writing-store mount or unrestricted git/engine API reaches a worker. + +### Gate + +Independent conversion/parser/authorization review, writing/library/bus/harness/WebUI suites, +pinned-copy and sandbox closure tests, plus W4 A19/A20/A33–A35 and G1. Source archive, off-host acknowledged DOCX and +format-map snapshot must match the new DOCX publication before completion. No real import +opens before all D12 gates. The October 27 Markdown and supporting-doc fixtures still pass. + +### Handoffs + +Owner sends commit/blob and fixture publication/crash evidence directly to the reviewer and +Sage through T3. Reviewer sends verdict to owner/Sage. Copy Mos for the later first-real-book +go or any proposed policy change, never ask an agent to execute that go. + +## Engineering choices from mos-1368 + +This table resolves the map's engineering prompts; these are design decisions, not questions +for Jason. Source map A17–A41 is covered by D5/D10–D15, D24–D28 and W3/W3b/W4b/W6/W7. +Later mos-1372/1375 override A32/A33's per-document/dedicated-session assumptions. + +| Map item | Choice and owner | +|---|---| +| Q1 / A27 / C5 | W7: durable DOCX staging+off-host ack, then one human archive move/mark commit+push, then catalogue publication; resumable pending state; counted events and pre-conversion restore reconciliation | +| Q2 / A34 / C4 | W3b: human-only editor.remoteURL, default unset, off-host private git, host pushes every commit; no agent/seat access, no force push; local agent reads with visible push status | +| Q3 / A20 | W7: all front matter in canonical chapter manifest metadata; index type/name/appears_in/relationships; optional DOCX property mirror never authoritative | +| Q4 / A22/A39/A40 / C7 | W7: owned stable source-path/base-name aliases and document IDs, ambiguous/unresolved -> R4; split-run wiki literals preserved. Plain links/appears_in always resolve or R4; chapter ![[embed]] must not be silently dropped; non-story images/.canvas/.base remain attachments | +| Q5 / A36 | W4b/W7: one typed index fed by Markdown metadata and pinned DOCX extraction, keyed by publication/extractor, source scope/universe/hybrid filtered | +| Q6 / A30 / C1 | W7/C2-06 guard: legacy Markdown cite or explicit kind:docx locator union; commit/blob historical verification and converted labels, as:canon/requireCitation/trailer checks in both; role cite wording updated | +| Q7 / A32/A33 | mos-1372 D9: ordinary Case 2 access in any thread/room, no per-document grant/share/dedicated session; existing supporting writes continue; marked for PRD 1.17 approval | +| Q8 / A36 | W4b/W7: preserve Case 2 find/get/search/manuscript/universe tools via host committed-reader adapters, not fewer tools or raw ZIP access | +| Q9 / A73 / C2 | W7: D10 manifest order, typed next_chapter, paragraph cursors bound to snapshot/access; both W4 byte cap and harness REPLY_CAP apply, never cut paragraphs or invent line equivalents | +| Q10 / A22 | W3/W7: Console Connections view, current cross-format links/backlinks with scope/format labels; Obsidian graph explicitly historical after conversion | +| Q11 / A37 | W7: Console archive saves refuse; sync flags later archive edits or recreated old paths and excludes them from current canon; no remote-push refusal/protected-pattern guarantee | +| Q12 / A21 | W7: reviewed markdown-it AST + first-party DOCX adapter; no new runtime converter; input cap 1 MiB default, W4 ZIP/XML validation, construct/token/extractor fidelity before archiving | +| Q13 | W7 survey: synthetic construct corpus and aggregate-only count capability; no seat reads real text or claims a corpus census happened | +| Q14 / D23 | W7 covers Markdown conversion and gated new DOCX creation; legacy .doc/.qxd and arbitrary outside-DOCX import remain separate assignments | +| Q15 | D10/D13/D14: DOCX review history plus git commit per closed save group; host remote push, no replacement for git | +| Q16 / A24 | Sage rebriefs C2-11b before implementation handoff: Markdown support/type notes remain row154, chapters open O2, archive read-only, human import gated. No queue edits in this assignment | +| C3 | W7: Hermes retirement #423 step5 with old store-read/story-write paths removed before production import/new-story opening | +| A18/A19/A25/A26/A28/A29/A31 | W3/W3b/W6/W7 and W4 A19/A20/A33–A35: same identity, one current DOCX, renamed convert modules/refusals, archive equality, pre/post opening and routing tests | +| A35 | W7 conversion checks v1-readable output before archive; W3 warns on later unsupported edits without flattening/loss, lookup returns actionable unsupported rather than stale source | +| A38/A41 | W7: archived saves refuse; direct New Story is DOCX; human archive is a fourth source-repo commit kind, with obsidian-git pull/setup documentation and human authorship | + +R1–R7 meanings stay fixed. W7 versions new pending-import/archive-edit problem state; survey +and the Console show counts and new format states. Fixture acceptance adds cross-universe and +hybrid links/exclusions, R4/R5/R6, archived non-canon citations, converted path routing and +supporting-save refusal to archive/DOCX. C2-18 Discord stays independently gated; sharing a +renderer does not enable it. No change is imposed on the October27 release. + +## Confirmed policy coverage + +| Policy | Owner and design | Acceptance | +|---|---|---| +| P1 DOCX-only story files | D5/D10/D12, W4b reader and W7 routing | W4 A19/A34; no current Markdown story after switch | +| P2 human import/archive | D11/D12, W7 | per-file fidelity/confirmation/manifest/commit; archive blob equals source | +| P3 one way | D11/D12, W7 | W4 A33/A35; no reverse/sync-back/parallel master | +| P4 Markdown supporting files and map | D5/D12, W7 | scoped format map, Q223 supporting CRUD, split-run cross-links | +| P5 no agent conversion; first-book go | D12, W3b refusal and W7 gate | no agent verb/grant/path, no request-flag bypass, scoped Jason go | +| P6 after 10-27 and W4b | D2/D12, W4b readiness/W7 publication | old release fixtures pass; no reader gap at switch | +| B1 human-set archive in user's repo | D11, W3a setting/W7 | safe archive path, host-only off-host remote under D7/C4 | +| B2 one story-file unit | D11, W7 | one report/confirmation/manifest/commit per operation | +| B3 human-only conversion boundary | D12, W7 | vocabulary snapshot has no conversion grant/tool | +| B4 explicit archived read scope | D12, W7 | requested/authorized/marked/non-canon only; excluded from current canon | + +## Current verification and remaining gates + +This is a docs-only policy rewrite for Vikunja 571. S0's conditional baseline PASS, Q234's +exact CSP approval and W4's prior reviewed design are recorded with their pins. Its changed access/remote/recovery +sections are reopened; the earlier APPROVE does not apply to them. They do not +prove any implementation or enable private conversion. Static checks cover P1–P6/B1–B4, mos-1368 A17–A41/Q1–Q16, mos-1372 D1/D2/D3/D7/D9, matching +parent/W4 gates and format routing, complete row fields, source pins, docs-only scope and +append-only logs. No build, browser run, conversion, queue entry or live change was performed. + +Jason's format and CSP choices are settled by Q234–Q237. No question repeats Q1 or Q36. +Before real conversion: Sage's Case 2 PRD amendment (Vikunja 570) needs Jason's approval; +W4b/W7, Hermes-retired and post-10-27 gates must pass; Jason must explicitly give the first real Melanie-book +conversion go. These are later authorization gates, not requests to convert anything now. diff --git a/docs/plans/2026-10-22_q195-docx-citations.md b/docs/plans/2026-10-22_q195-docx-citations.md index 2af460ab7..f51af6a51 100644 --- a/docs/plans/2026-10-22_q195-docx-citations.md +++ b/docs/plans/2026-10-22_q195-docx-citations.md @@ -1,78 +1,91 @@ -# Q195 O2 W4: committed DOCX citations and access +# Q195 O2 W4: committed DOCX citations and Case 2 access -Design for Gitea #1799, assignment sage-3060/mos-1360. Owner Rocko; -independent reviewer Megavolt. Normative parent: `e36bce352`, -`docs/plans/2026-10-21_q195-writing-editor.md`, blob -`322ec50f2669cffc0f8256d6beffdaccc4d8dba8`, D12, D24-D26, W4 and W4b. -This is a proposed implementation contract, not access enablement or a parser -security PASS. Reviewer owns the separate verdict file; the author does not -write an approval there. +Policy rewrite for Vikunja 571, mos-1366/1367/1368/1372/1375, Q234–Q237. +Normative parent: `docs/plans/2026-10-21_q195-writing-editor.md` in the same revision. +Original W4: Rocko/Megavolt, #1799, refactor 062646487, blob +`2af460ab772f8d204598dc8cb79b3c161f311623`. Gyro writes this assigned revision; Fenton +independently reviews it. The reviewer-owned verdict file is untouched. +Impact map: brain-redux d183246, `projects/mosaic-mvp/case2-docx-impact-map.md`, stack pin +062646487. Sections 1/2/6/7 and A19/A20/A28 are reopened, plus part/view authorization +wording. Exact locator, package-validation and projection mechanics in sections 3–5 remain +from the reviewed baseline except their replaced per-document-scope wording. -## 1. Gates and compatibility +## 1. Confirmed format policy and approval gates -W4b implements this contract only after independent W4 APPROVE and Sage's -accepted implementation brief, S0 and its other parent gates. A release must -ship extractor, resolver, authorization and sharing together; no partial -agent read rollout. Missing server readiness refuses every O2 read, resolve, -share and flag. A human setting, pin or request field cannot assert readiness. -W5 owns flags, not chapter writes. No agent execute, edit, replace, save, -tracked-change or comment-writing operation is introduced. +Q235–Q237 P1–P6 and mos-1372 D1/D2 settle the design basis: canon and playground story +files become DOCX, retaining universe/book and source scope. Type-folder notes, agent files, +instructions, PRDs, character sheets, summaries and supporting documentation stay Markdown. +An unmarked-folder story is eligible; the human selects one story file at a time. New +stories start directly as DOCX in the human-selected universe/book or playground, without a +Markdown precursor, under the same production-opening gate as import. -Q36 / Vikunja 562 is OPEN. Production Markdown adoption remains closed under -mos-1358, independently of whether this design is approved. If Jason approves -superseded notices, a separate C2 reader/reply row must implement and pass -them before adoption; otherwise Mos records Jason's disposition before any -adoption brief proceeds. This document neither implements nor decides notices. +The October 27 release stays Markdown. Production import/new-story opening waits for W4b, +W7, the post-10-27 release, the approved Case 2 PRD/brief amendment, Hermes retirement +(#423 step 5) and configured off-host durability. The first real use on Melanie's books +also waits for Jason's scoped go. All starts are human-only; `library.convert` has no role +grant or agent request path and stays a hard wait unless an approved PRD changes it. +Nothing in this document authorizes conversion, new private story creation or deployment. +Q234's exact frame CSP, mos-1363 and S0 M1–M14 remain unchanged implementation gates. -Existing C2 Markdown, its line-cite schema, library grants and supporting-doc -writer remain unchanged. An authorized old Markdown original is historical -source, never the current DOCX or a permission to its later edits. No DOCX -paragraph is called a line. Following an adopted source from a C2 read, -indexing it as Markdown, changing C2 replies or a synchronized Markdown -projection requires a separately approved Case 2 amendment through Mos/Jason. -W4b must test old C2 fixtures unchanged alongside the new discriminated DOCX -contract. It may migrate only new O2 records, with a named schema edge Sage -allocates; it must not reinterpret existing line citations in place. +mos-1372 D9 replaces the prior W4 O2-only-conversation, per-document-grant and per-send-share +requirements for Case 2 lookups. Agents read converted stories through the normal Case 2 +lookups in any thread or room under the same live project/universe/source-scope checks as +Markdown canon/playground. They can then use existing supporting-Markdown write tools under +Q223. The agent never writes a story/DOCX/archive file. D9 is marked as a choice for Jason +in PRD 1.17 approval; it is design text, not an already approved role/policy expansion. +No code may rely on that changed requirement before the approved PRD and independent review. -## 2. Trust and document identity +Human import commits the verified DOCX to a private staging ref first and obtains its +off-host push acknowledgment. It then creates/pushes the source archive move+mark through +new human-only bus plumbing on the C2-02/C2-03b writer, not two single-path saves. Finally +one host publication protocol advances writing-published and the catalogue under the +publication/read lock. No staged ID is reader-visible before catalogue CAS. Before that +switch, agents read the source at its pinned commit; sync cannot advance it early. After +it, only the current DOCX is a chapter. Pre-push failure leaves source Markdown unmoved; +after archive push, failure is a visible resumable pending operation, never an assertion +that nothing moved, a rollback push or Markdown revival. Old bytes/history remain. -The host reader alone opens `/writing///`. -Business, project and document are opaque IDs resolved through the host's -owned manifest, never request paths. Each document has a stable ID and one -canonical DOCX path; a rename does not change its identity. A copy/new import -gets a new document ID and no inherited grant, share, pin or cache authority. -Origin metadata is evidence only. Copying a source does not launder access. +The archive is in the human-set source-repository folder, default archive/converted, with +converted date, source commit/blob/path and replacement ID in the operation record. It is +read-only in the Console. Explicit `archived` scope returns only requested authorized +records, always marked and non-canon; default/current queries never opt into it. An old +source lookup returns a typed conversion record and routes an authorized DOCX read, never +stale Markdown or fake DOCX lines. Historical line cites still verify at commit/blob and +show converted/historical state; archive access alone is not current story authorization. -A read snapshots one reachable committed manifest and its DOCX blob from the -same commit. It never combines HEAD's manifest with another commit's DOCX. -The reader accepts only server-resolved commits reachable from that document's -published history; arbitrary git objects and another document's same blob -are not selectable. Historical access also requires the document's current -live authorization. Removed history, missing blobs or missing extractor -revisions refuse; there is no worktree, export or engine-memory fallback. -The commit/blob field is a locator, not an authority token. +Every conversion runs the pinned extractor before archiving and refuses unsupported output. +An independently reviewed importer preserves every wiki token and front-matter key; metadata +moves to the canonical manifest (type/name/appears_in/relationships feed the index). Links +resolve across Markdown/DOCX through owned aliases, not host paths. A lost link fails the +fidelity report. Plain links/front-matter values resolve or raise R4; unresolved chapter +embeds must not take the old silent attachment-drop path. Images/.canvas/.base remain attachments. -The project's sole publication ref is `refs/heads/writing-published`; only -the human writer advances it, atomically and without force updates. Each -commit contains the book manifest. For a document, its publication commits -are the first-parent commits on that ref that add or change its DOCX blob or -its canonical manifest entry (including deletion/reinstatement). The first -commit is a publication; a sibling-only save is not. `currentCommit` is the -latest such commit for this document at the captured ref tip. Version latest -selects that commit; a locator commit must be one of those publication commits, -not an arbitrary intervening project commit. Deleted document entries refuse -current reads, including history, until explicitly reinstated and granted. -Published history is exactly that document's reachable publication sequence. -A sibling save does not change its currentCommit, stale flag or cursor. -Staleness is still exact commit inequality within that document, even if a -human deliberately saves an earlier byte-identical blob as a new publication. +## 2. Document identity, order and freshness -The writer's successful commit publishes atomically before Saved. A latest -lookup begun after that receipt resolves that published commit, not an old -cache entry. A lookup already in progress remains internally on its captured -commit. Return the captured version explicitly; never label it latest after -observing a newer publish. Recheck live grants immediately before returning -content, not just before asynchronous extraction. +Host code alone opens `/writing///`. Opaque document IDs resolve +through the canonical manifest, never caller paths. Conversion preserves book/chapter identity +and scope, binding the original path/name as an alias to the DOCX ID. New stories get a fresh +ID and the human-selected universe/book or playground. No format-based canon promotion. +The map tells authorized agents format, source scope, owned location and current version; +archived entries are available only in explicit archived requests. No host paths/credentials. + +A lookup snapshots the reachable committed manifest and DOCX blob from one publication. +No worktree, draft, archive or engine-memory fallback. `refs/heads/writing-published` is the +canonical served ref. A document's publications are the first-parent commits adding or +changing its blob/manifest entry; sibling-only saves do not change its currentCommit. +History locators name only such reachable publications, with current project/universe checks. +Deleted entries refuse until explicitly reinstated by an authorized human. New local saves +publish before acknowledgment. A lookup starting after an acknowledged save returns that +save or a later one and names it. A lookup already in flight stays on its captured version; +never label an observed older snapshot latest. Recheck live access before emitting text. + +D10's ordered chapter-ID manifest drives manuscript paging and next_chapter after conversion, +replacing row216's initial path-order rule (RULINGS.md:32–34). Before the first conversion, +seed the order from that existing rule; replace each source entry with its DOCX identity in +place. A human reorder is a manifest commit. next_chapter never names an archive. Pending +unconverted files retain their legacy identity/scope until their individual publication +switch; no file has two working formats and new stories start as DOCX. Book-null notes +stay out of manuscript; hybrid exclusions and source-universe boundaries still apply. ## 3. Exact wire schema, version 1 @@ -81,7 +94,7 @@ commits/blobs are lowercase 40-hex Git object IDs in the repository's current SHA-1 object format. A future object format requires a new schema revision. Digest values are lowercase 64-hex SHA-256. Integers are safe nonnegative JSON integers. No floats, coercion, duplicate JSON keys or implicit defaults -except the explicitly listed request defaults below. These are proposed O2-only records. +except the explicitly listed request defaults below. These are proposed DOCX records for the Case 2 lookup/citation union. A locator is exactly: @@ -214,10 +227,10 @@ extractor supports them; never guess equivalent namespaces. | Class | Exact part names | Story selector | Agent exposure | | --- | --- | --- | --- | -| body | word/document.xml | main | final by default, explicit grant | -| footnote | word/footnotes.xml | w:footnote/@w:id | own story plus owning document grant | -| endnote | word/endnotes.xml | w:endnote/@w:id | own story plus owning document grant | -| comment | word/comments.xml | w:comment/@w:id | only explicit comment scope | +| body | word/document.xml | main | final by default; existing project/universe access | +| footnote | word/footnotes.xml | w:footnote/@w:id | own story; same project/universe access as its document | +| endnote | word/endnotes.xml | w:endnote/@w:id | own story; same project/universe access as its document | +| comment | word/comments.xml | w:comment/@w:id | explicit part request; same project/universe access | | layout | word/headerN.xml, word/footerN.xml (N positive decimal) | none | denied in v1 | | supporting | separately declared non-story document | separate identity | C2 tools/scopes only; no DOCX scope inheritance | | opaque | media, styles, numbering, theme, fonts, custom XML, embedded objects | none | no raw bytes through O2 reader | @@ -288,8 +301,9 @@ kind paragraph-mark-insert or paragraph-mark-delete with its revision ID; it never becomes a whole-paragraph deletion span. A mark-only insertion's text stays in original; a mark-only deletion's text stays in final. Inline run revisions remain independent. No view edits or accepts/rejects changes. -Original/markup and comments require separate scopes, so final body access -never reveals hidden deletion/comment text. Revision author/date metadata +Original/markup and comments are explicit view/part requests under the same project/universe +authorization; no per-document grant is added. A default final-body read never silently +includes deleted revisions or comment stories. Revision author/date metadata is omitted from agent responses in v1. Closed story/run leaf table (all names in w namespace unless stated): @@ -372,7 +386,8 @@ plain text, and tokens cannot cross paragraph/view boundaries. ## 6. Reading APIs, verification, paging and staleness These are proposed typed tool schemas over the existing runner socket, not -native WordCraft MCP. Caller/session/business come from the bound broker. +native WordCraft MCP. The same reader backs Case 2 lookups in any authorized thread or +room under mos-1372 D9. Caller/session/business come from the bound broker. Agents cannot override them using object fields. - `editor_read_committed({project,document,version,textView,part,cursor,limit})`: @@ -412,14 +427,14 @@ without progress. Cursor is a host-authenticated opaque token binding principal, session, project/document, commit/blob, extractor, view, part, next ordinal, the complete -authority revision vector defined in section 7 and expiration (5 minutes). It carries no plaintext content. +project/universe authorization and format-publication revision vector defined in section 7 and expiration (5 minutes). It carries no plaintext content. Tampering, reuse by another session, wrong request parameters or a revoked scope refuses. A latest cursor continues its captured snapshot with stale metadata if a save intervenes; starting again with null cursor returns the new publication. Cursor is not a capability and grants are rechecked every page. Repeated ordinal ranges are stable within one committed projection. -Resolver steps: authorize the current principal tuple, live scopes and exact/historical share (there is no separate undefined historical-view scope); load +Resolver steps: authorize the current principal, live project/universe/source scope and publication membership; load that commit's manifest/blob; validate package; run the exact pinned extractor; select exact part/story/ordinal and mandatory XML-ID value; select code-point range; require literal quote equality and SHA-256(UTF-8 quote) equality. Require both @@ -431,14 +446,13 @@ an explicit old-version label. If current grant no longer allows it, even old quote resolution refuses and the UI hides cached content. Errors: `editor-context-unavailable` for missing readiness; `editor-access-refused` -for absent ownership/grant/share (same response for nonexistent or foreign IDs); +for absent live project/universe authorization (same response for nonexistent or foreign IDs); `editor-document-unsupported` for parser limits or unsupported features after authorization; `editor-version-unavailable` for authorized missing history or extractor; `editor-citation-invalid` for locator/quote mismatch; `editor-cursor-invalid` for invalid paging; `editor-range-too-large` for size. The exact refusal envelope is `{ok:false,error:{code,message}}`; code is one -of those enum strings or editor-policy-conflict/editor-sharing-unsupported -(both 409, defined in section 7), and message is fixed server text for that code (no user +of those enum strings or editor-policy-conflict (409, stale catalogue/settings revision), and message is fixed server text for that code (no user input). Both missing/foreign and ungranted IDs use the same code/message/status 403. Syntax errors before identity lookup use editor-citation-invalid, 400; context unavailable is 503, cursor-invalid 400, version unavailable 409, @@ -446,417 +460,131 @@ unsupported/range-too-large 422. Successful tools return `{ok:true,result}` where result is the defined response; errors never include result/partial rows. Return no source text, XML, path or untrusted parser error in refusals. -## 7. Authority data, dedicated sessions and sharing -### 7.1 Scope and principal records +### 6.1 Case 2 query and citation adapters -O2 context is permitted only in newly created **O2-dedicated conversations -and execution sessions**. Existing C2 threads/sessions cannot be converted, -attached to O2 context or resumed/forked into O2 mode; new IDs and a fresh -empty context are mandatory. There is no mixed-thread turn. The UI offers -"Open dedicated writing conversation", never silently changes an existing -chat's permissions. Existing C2-02 supporting-doc writes and C2-06 replies -retain their semantics. The narrowing below belongs only to this explicitly -opted-in O2 mode, closing review M1 without a Case 2 amendment. It changes -neither the Case 2 schema nor the meaning of its replies/line citations. +Keep `library_find`, `library_get`, `library_search`, `library_manuscript` and the universe +lookup. Host adapters join Markdown metadata/read results and the committed DOCX extractor +into one typed, scope-filtered index; only current identities enter normal lookups. A request +on a converted alias returns its conversion record and the authorized DOCX result. Every +answer names format, store/owned ID and captured commit. No loss of chapter search/manuscript +or supporting-doc workflow is accepted. Same project/universe/source-scope rules apply in +all threads/rooms; archive/draft scope never becomes canon because its format is DOCX. -Authorization principal is a tuple, not a seat's display name: -`{business,human,agentInstance,conversation,executionSession}`. human is the -stable authenticated identity that owns the O2 conversation; agentInstance -and executionSession come from its bound broker run. The request cannot -supply/replace them. All human readers and all agent lookups require live -R5 project/universe access plus the O2 grant below; role files grant the -operation only. The business owner is not an implicit reader of someone -else's private conversation. A viewer can read only their authorized human -view, never write a share/settings change or invoke an agent by sharing. -An owner/collaborator with current project write access may share within -their own readable O2 scope. Agent scope and sharing human scope intersect; -a human cannot share a part or view they lack. +DOCX pages use paragraph locators and opaque cursors, not invented line equivalents. +Retain section 6's 64-KiB/1..100 paragraph bounds (default20); human reply limits still apply. +A manuscript cursor binds ordered-manifest commit, the selected document publication vector, +principal/request/scope revisions and expiry. Resume only that snapshot with current access; +changed/foreign cursor refuses. next_chapter uses the next visible current manifest ID, +never an archive or a guessed sort of DOCX names. Index/cache keys include local publication +and extractor revisions; no minute-old Markdown refresh window is copied to DOCX. -O2 scopes live in the new append-only bus table writing_access_events, not -access.json or role-file wildcard changes. Proposed human-only verb -`editor.access.set({project,document,subject,scope,expectedRevision})` takes -subject exactly `{kind:"human"|"agent",id}`; agent id is the business's -bus agent **instance ID**, equal to principal.agentInstance, never a role -definition ID or a seat display name. scope is exactly -`{enabled,parts,views,history,mayShare}`. parts is a sorted unique nonempty -subset of body/footnote/endnote/comment (all stories within the selected -class); views is a sorted unique nonempty subset final/original/markup; -history and mayShare are booleans. mayShare must be false for agent subjects. -enabled=false revokes all access; even its otherwise populated scope cannot -authorize. No wildcards or implicit note/comment inheritance. A comment -requires parts including comment and the requested view. history=true permits -older publications subject to a matching share; history=false permits only -the current publication. The document is always explicit. +C2-06's checked cite union preserves legacy `{path,commit,lines,quote,as?}` for Markdown and +adds `{kind:"docx",locator,as?}` where locator is section3's exact range/selection. Never infer +a cite kind from a .docx suffix or parse DOCX as lines. The host checks project/universe, +source canon/playground/archive status, fetched provenance, quote and commit before message +storage. requireCitation and as:canon apply to both; historical converted/archived sources +cannot assert current canon. The host reads Mosaic-Agent trailers from the correct source +repository or writing-store publication, never trusts an agent author field. Console and +the shared reply renderer show format, locator/lines, version, staleness and converted state. +C2-18 Discord remains a separate ruled delivery task, not enabled by a shared renderer. -Only the existing business-owner human proof may write these policy grants, -through the existing trusted human CLI or authenticated write-enabled Console -transport, with the existing origin/session/proof checks. No new proof file, -caller or exemption. Not tester, agent, viewer or collaborator policy writes. -Sharing and scope are different: an authorized collaborator may send context -but cannot change grants. expectedRevision is the latest sequence for that -business/project/document/subject, zero when none. Compare, append and audit -are atomic; conflict returns editor-policy-conflict (409, fixed message). -Receipt is `{ok:true,result:{id,revision,previousRevision,scopeDigest}}`, where -revision is the appended seq, id is host-generated, and scopeDigest is SHA-256 -of canonical scope JSON using section 3 serialization. Missing grant denies. +## 7. Existing Case 2 authority, remote durability and restore -Each access decision records an authority vector exactly -`{restoreEpoch,humanAccess,agentAccess,projectAccess,threadAccess,sharingPolicy,share}`. -humanAccess and agentAccess are the respective latest writing_access_events -seq values; projectAccess is the existing R5 access revision; threadAccess -is the latest O2 conversation membership-event seq; sharingPolicy is the -latest writing_policy_events seq; share is the exact writing_shares seq. -restoreEpoch is the independent restore-fence epoch in section 7.5. -Missing inputs deny rather than zero-default except initial policy explicitly -materialized by the human writer as the default. A cursor binds every value; -any change invalidates it. Each new lookup reevaluates rights, including a -revocation between asynchronous extraction and response emission. +### 7.1 Access and supporting writes (reopened M1) -### 7.2 One human per context; settings and chip requests +Reuse existing bound business/project/universe access, live holder/role and source scope. +No private O2 conversation ID, per-document access table or send/share token gates a Case 2 +lookup. Any existing authorized thread/room may use the checked reader and normal library +tools. No arbitrary native WordCraft MCP, execute, open/save or raw filesystem/git tool is +added. The host store is never mounted in a worker. Rendered/extracted content travels over +the ordinary authorized Case 2 tool/message path and existing transcript/run-record policy; +the withdrawn private-only transcript/output rule cannot forbid that documented workflow. +Grant loss blocks later lookups through existing checks; do not promise erasure of earlier +delivered text or rewrite immutable run evidence. This is the D9 choice for PRD approval. -An O2 conversation has exactly one owner human and one agent instance. No -second human joins it in v1: a thread-share attempt refuses -editor-sharing-unsupported (409), rather than borrowing the sender's grants -for someone else. A second human starts a separate O2 conversation, supplies -their own grant/share and gets no previous content. This is a new O2 mode, -not a restriction on existing C2 sharing. Human and agent must still have -matching business/project/universe rights. Read-only previews cannot send. +The existing `library_doc_write`/`library_doc_delete` still require library.write plus the +live supporting-repo Gitea grant and supportingPath before git. They operate only on human- +marked supporting Markdown, with the existing size/base-CAS/seat-author/push/notice/revert +rules. An agent can read a DOCX story and update its character sheet in the same authorized +thread. There is no agent write to DOCX, original story, archive or conversion manifest. +The archive prefix wins over supporting globs; conflicts refuse mapping. Format/status/type +notes in the six creative contracts replace stale 'every item cites lines' wording with +free chat plus optional checked line/DOCX citations under requireCitation. No per-document +export grant or O2-only session is a hidden prerequisite. -Human-only `editor.sharing.set({conversation,mode,expectedRevision})` is -available only to that authenticated owner with current write access over -the same trusted write transports. mode is off/visible-chip-per-send/ -conversation-current. It atomically appends writing_policy_events and returns -`{ok:true,result:{id,revision,previousRevision,mode}}`. Default is the explicit -visible-chip-per-send policy on new conversation creation. Selecting off -immediately invalidates **all** prior shares, reads, resolves and cursors for -that conversation, not only new sends. Selecting another mode later does -not revive shares from the earlier policy revision. No pin changes a mode. +The cursor authority revision is the server's current project grant, universe/mapping/scope +revision and format-publication generation for the bound caller/session. It contains no +sharing human or writing_access_events/writing_shares sequence. Recheck before every page, +resolution, index hit and message insertion. Scope revocation and format changes invalidate +cached authorization; metadata for missing/foreign IDs uses the same refusal as before. -In visible-chip-per-send the human sends exactly -`{conversation,message,expectedPolicyRevision,chip}` via the human send path. -message is human-authored free-chat text; W4b's bounded human API handles it, -never an agent-supplied impersonation. chip is null or one of: +### 7.2 Selection convenience and ordinary messages -- `{kind:"range",document,baseCommit,selection}` where selection is one - docx-range/docx-selection locator, with its business/project/document/ - commit equal to the server-owned conversation/document and baseCommit. -- `{kind:"document",document,baseCommit,parts,views,history}` selecting a - whole-document **exact publication**, with explicit part/view lists and - history boolean constrained by both grants. +Keep Q233's human-only setting, default a visible removable chip on each send. A chip may +attach only a verified committed locator/version, never unsaved selection text. It helps the +writer point at a passage; it neither grants nor limits the agent's ordinary project/universe +lookup rights and does not freeze a later latest lookup to that older commit. The sent cite +remains immutable historical evidence. Multi-human/thread/room behavior follows existing Case 2 +permission checks, not a new one-human conversation restriction. Saved-context/pin records +remain on the bus through their reviewed schema, with no share-token authority layer. -Both chips require a server-issued human editor selection token as an -additional required `selectionToken` key. It binds authenticated login, -conversation, document, baseCommit, saved editor model revision, and either -exact locator or whole-document scope digest, expires in 2 minutes and is -single-use. The human editor adapter creates it only after exact mapping to -the committed projection. The request supplies no draft text or engine path -for mapping; mismatched/edited selection fails locally and server-side. -A stale base or document change before send refuses, requiring a fresh -visible chip; an old citation remains resolvable through its already-sent -share while authorized. Null chip sends no editor context. Before readiness, -the chip says unavailable and sends no document ID, title, path or selection. +### 7.3 Host-only off-host remote (replaces the ban) -A range share permits only editor_resolve_citation for that exact locator -(or a range wholly contained within it with newly verified quote/digest). -It always refuses editor_read_committed, since rows would expose surrounding -text. A document exact share allows paging only its named publication, -parts/views; it never grants future saves. No implicit body-to-note/comment -or final-to-markup expansion occurs. +`editor.remoteURL` is a human-only setting, default unset. No same-host bare/filesystem/loopback +remote is the default or qualifies as off-host durability. The human selects an off-stack-host +private destination (for example private Gitea) and separately configures host-only auth. +Only the host process pushes. No seat token can list/fetch/clone/fork/push the writing repo, +no seat gets its credential, and no raw Gitea grant or store mount is created. Validate the +owned remote, TLS/host policy and off-host storage identity; reject URL userinfo, unexpected +remotes/object alternates and non-fast-forward updates. No silent fallback or force push. -conversation-current is an explicit human policy with a persistent visible -indicator and a required whole-document chip. The same chip fields bind -baseCommit and scope, but the share record has versionMode=latest: baseCommit -is the acknowledged publication at issuance, not a future-version ceiling. -The next authorized latest lookup after Saved follows currentCommit within -the granted part/view/history bounds. This exception to exact-version sharing -exists only in this explicit mode. Range chips are refused in this mode, -not silently upgraded. Pins and earlier exact shares never become latest. +Every writing-store commit pushes there. Agents read the local publication immediately; +receipts/UI distinguish local commit and remote pending/failed/synced. Missing remote blocks +production opening. Before source archive push, the staged DOCX must have remote acknowledgment. +A failed later push keeps local commits, queues bounded host retry/readback and shows failure; +it never rolls back the local story. Source archives push through their separate human +library writer. The configured retry deadline is human-only (default30s, 1s..300s). +Remote/provisioning changes require the normal owner authority, never this design execution. +The remote exception is for story git history/manifest; generic stack copies/releases are +not story backups and contain no host credentials. Normal Case 2 output/notes follow the +existing project's approved storage/sharing policy; the former blanket no-backup/no-remote +rule is withdrawn. PRD 1.17 explicitly presents this D7/C4 change to Jason. -Latest shares expire on explicit policy revocation, owner grant loss, O2 -conversation close or **execution-session end/clear**. This means the new -O2 execution session, not the Console login, bus connection or a C2 thread -session. Relaunch/clear requires a fresh chip; a dropped socket/login does -not silently widen or prolong one. Exact shares may remain verifiable across -execution sessions through their same human conversation while live policy, -history permission and grants hold, but never supply replay context to a -new agent session without a new share. Their scope is citation verification -only after the issuing execution session ends. No cross-human context reuse. +### 7.4 Conversion events, rollback --restore and irreversible recovery -### 7.3 Stored share schema +W7 owns `writing_conversion_events`: a STRICT append-only table with seq INTEGER PRIMARY KEY, +at TEXT, business/project/document/operation_id/stage TEXT, record_ref/record_digest TEXT; +All fields except seq are NOT NULL; operation_id+stage is unique, no update/delete. The private host journal/record contains source +commit/blob/path, archive path/commit, DOCX commit and conversion date; the row is metadata +and never prose/credentials. Records are flushed before their bus references. Table rows +join stack-release COUNTED and T46 exactly once, so post-backup conversion events contribute +to --events and the existing restore approval/counting behavior. No new private conversation, +per-document grant or per-send share tables are created for D9. -The immutable writing_shares payload is exactly -`{version,id,restoreEpoch,business,project,document,conversation,executionSession,message, -human,agentInstance,mode,versionMode,baseCommit,blob,extractor,scope,selection, -authority,policyRevision,issuedAt}`. version=1; IDs use section 3 grammar; -mode is the policy at issuance; versionMode is exact/latest; baseCommit/blob -are the acknowledged snapshot and extractor is its exact pinned revision. -scope is `{parts,views,history}` as above; selection is the verified locator -for a range, otherwise null. authority is the complete revision vector at -issuance; its share field equals this row's seq (assigned atomically). -restoreEpoch must equal authority.restoreEpoch and the live independent -fence. issuedAt is canonical UTC millisecond ISO timestamp. policyRevision equals -authority.sharingPolicy. message names a new writing_messages row, not a C2 -message. A unique `(conversation,message,document)` constraint and operation -idempotency key prevent duplicate grants on retry. No user-provided human, -agentInstance, authority, issuedAt, blob or share id is accepted. -A scope decrease/revocation denies even historical shares; an unrelated new -policy revision also invalidates prior policy-bound shares. A human who -needs them again explicitly reshares. Missing session/share is no context. - -### 7.4 Dedicated storage and every output surface - -Every turn receiving O2 context runs with the new O2-only allowlist of -read/resolve/flag plus its dedicated conversation reply. No generic file, -shell, git, supporting-doc writer or arbitrary outgoing tool is available. -This narrows only new O2 sessions, never C2 turns. All agent output from such -a turn is conservatively O2-derived; it stays in the dedicated conversation -with the union of the document provenance/scopes. No semantic quote detector -or agent self-labelling supplies this boundary. Human text and titles in that -conversation use the same dedicated storage, so a human pasting an O2 passage -cannot accidentally route it into an old renderer. O2 replies never enter -C2-06 processing. An O2 flag is metadata stored by W5, not a story edit. - -| Existing surface | Required O2 behavior | -| --- | --- | -| threads///session and claude-projects | no O2 content, prompt, model transcript, title or derived reply | -| threads///sessions//session and claude-projects | same; O2 mode never binds these native stores | -| session-workspaces/// | no O2 text or exports; no store mount | -| launches// including bundle, turns, runner.log and session | opaque IDs/status only, never O2 prompts/output; host transient O2 adapter instead | -| bus events, messages, message_threads and existing sessions rows | no O2 text/titles/quotes; only fixed readiness/status audit with opaque IDs if needed | -| Console legacy thread view | no O2 rows; dedicated writing view reauthorizes every read | -| CLI thread, talk, follow and raw-session tools | no O2 content; unsupported mode refuses, not generic rendering | -| Discord journal.mjs/context.mjs and control-board Discord delivery | no O2 conversation subscriptions/context/output; fixed unavailable notice only | -| /runs write-once evidence | never O2 text, prompts, titles, excerpts, stdout/stderr or derived output; only opaque run status | -| bus-host/sessions.json, launch logs and activity projections | IDs/liveness only, no document or conversation title | - -Host-only `/writing-context/` (0700 owner, no generic mount/remote) -holds the immutable dedicated message/share objects defined below, transient -O2 adapter material and any unavoidable encrypted native transcript. Object -files are regular 0600 owner files, no symlink/hardlink aliases. This is an -O2-classified content store; it is never included in the bus release backup, -post-attempt store, stack-copy, rehearse input or generic backup. Revocation -changes permission at read time, never rewrites a write-once run record. It is keyed to O2 session, not an alias/symlink into seat stores. -Release readiness requires an independently tested adapter that prevents -plaintext native persistence/logging outside this boundary, including crash -and timeout paths. If either Pi or Claude cannot meet it, that harness's O2 -tools stay off; do not expose the session then attempt post-hoc redaction of -write-once run records. Readiness is per adapter. No O2 text enters immutable -legacy evidence, even briefly. Stored dedicated replies are authorized afresh -at read time; live grant loss hides cached UI content and prevents prompt -replay/fork. Revocation cannot erase already delivered knowledge and the UI -must not promise that it can. - -O2-derived exports, extraction indexes, caches, previews, source copies and -git history retain document classification outside generic roots and C2 -library mappings. O2 repositories have **no git remotes**. No push, mirror, -fork, plaintext backup or remote replication of an O2 repository is allowed, -including through human credentials; no seat Gitea account can discover, -list, fork or clone one. Backup transport is out of scope and disabled, not -an implied exception. Stack-copy/release copies source code and extractor -artifacts only, never writing/, writing-context/, writing-control/, O2 content -objects, exports or repository object directories. The separate release bus -backup retains metadata rows only, under the private-store rules below; -it is not a source copy or permission to read context. No raw O2 Gitea grant may be minted. -Validate absence of remotes at store creation, before save/read and activation; -a new remote or object alternate disables O2, rather than trusting a read-only -mount. Symlinks, hardlinks, alternate worktrees and parent mounts must not -expose it to generic tools. Native engine APIs remain human-only. - -### 7.5 Named migration and rollback contract - -W4b adds the following new STRICT append-only bus tables (seq INTEGER primary -key, at TEXT canonical timestamp, id TEXT unique, all other fields NOT NULL -unless stated). Each row also has restore_epoch TEXT NOT NULL, equal to the -independent current fence epoch at write time. Every update/delete/replace -refuses; latest seq **within that epoch** is state. -JSON columns contain the exact canonical schema named above, not arbitrary -unvalidated JSON. No existing C2 messages/events/sessions column changes. - -| Table | Additional columns and key | -| --- | --- | -| writing_access_events | business TEXT, project TEXT, document TEXT, subject_kind TEXT (human/agent), subject_id TEXT, by_human TEXT, previous_revision INTEGER, scope_json TEXT, operation_id TEXT UNIQUE; latest per document/subject | -| writing_conversations | business TEXT, project TEXT, owner_human TEXT, agent_instance TEXT; one creation row per id, private O2 identity only | -| writing_conversation_events | conversation TEXT FK, op TEXT (close), by_human TEXT; latest membership/close revision, creation seq is initial threadAccess | -| writing_execution_sessions | conversation TEXT FK, execution_session TEXT UNIQUE, adapter_revision TEXT; no native transcript path | -| writing_session_events | execution_session TEXT FK, op TEXT (end/clear), by_principal TEXT; terminal event invalidates latest shares | -| writing_policy_events | conversation TEXT FK, mode TEXT, by_human TEXT, previous_revision INTEGER, operation_id TEXT UNIQUE | -| writing_messages | conversation TEXT FK, execution_session TEXT FK nullable for human-only messages, from_kind TEXT (human/agent), from_id TEXT, content_ref TEXT, content_digest TEXT, operation_id TEXT UNIQUE | -| writing_shares | conversation TEXT FK, message TEXT FK, document TEXT, payload_ref TEXT, payload_digest TEXT, operation_id TEXT UNIQUE; UNIQUE(conversation,message,document) | - -Each table also has business/project columns if not otherwise listed; FK and -application checks require agreement, not just ID existence. The canonical message content object is exactly `{version:1,business,project,row,nonce,body,provenance}`: -row is the owning writing_messages row ID; nonce is fresh cryptographically -random 32-byte lowercase hex, stored only inside the private object, not its -metadata backup. body is -the complete human/agent message string; provenance is an array of `{document,share,commit,blob,extractor}`, -sorted by document/share; every entry requires live scopes. The share content -object is exactly `{version:1,business,project,row,nonce,payload}`, where row -is its writing_shares row ID, nonce has the same fresh/private rule, and -payload is the full section 7.3 record including any quoted selection. -Neither message bodies nor share payloads/quotes enter bus.sqlite, WAL, -events, SQL error logs or backup manifests. Human messages with no O2 -attachment have provenance=[] but use the same private content store. -content_ref/payload_ref are opaque 64-hex object names, not paths; their -corresponding digest equals SHA-256 of the exact canonical UTF-8 object. -Objects reside at writing-context/objects///.json; -row/business/project must match both reference metadata and the authorized -caller. No cross-business or cross-row deduplication; retention is per owning -row and cannot delete another business's object. The private random nonce -prevents a metadata digest from confirming a guessed short body. No remote or -release-backup copy. Write/flush the immutable object before committing its -bus reference. A failed transaction leaves only an inaccessible orphan, -never a visible partial message/share; a missing or mismatched object refuses. -Object reads always require current authority, not knowledge of a digest. -No -existing renderer queries these new tables; generic bus recordEvent and -recordTask cannot write their rows. Access/policy/shares use only the trusted -handlers and atomic transactions. Grant seq values are table-specific, with -kind-qualified revision vector fields; never compare unrelated seq counters. - -Sage allocates the schema edge; migration creates these empty tables and -triggers, with no backfill/conversion of C2 citations, messages or raw sessions. -Production adoption stays refused. The writer registers new documents without -creating grants; the owner explicitly sets both human/agent document scopes. -O2 session creation and its default policy are one atomic operation behind -owner write proof; receipt `{id,executionSession,policyRevision}` contains no -content. No legacy thread/session can be attached by guessed ID. - -Old release rollback must not render O2 data. The new store schema version -normally makes old binaries refuse opening it, but security does not depend -on that: even a restored pre-W4b database reader can see only its unchanged -legacy tables with no O2 content. O2 messages/share/provenance remain in new -tables, never a tagged body in existing messages. Activating a pre-W4b copy -disables O2 context, never converts dedicated conversations to C2 or exports -transcripts for compatibility. O2 repositories/stores remain outside copies. -A rollback probe uses recognizable secret fixture text in O2-only content objects, -then invokes old Console/CLI/Discord/raw-session renderers: none may emit it, -its title, quote or prompt. No live rollback is part of acceptance testing. - -#### Release backup, restore counting and independent revocation fence - -The existing release behavior must be explicitly accounted for: at this base -`scripts/stack-release.sh:474-493` copies bus.sqlite into -`/backups/stack//bus/`; restore_store at :498ff moves current -bus/ to `/bus.post-attempt-/`. rehearse reads backup -stores, and release never prunes them. These paths remain **O2-classified -metadata stores** even though content/quotes are outside SQLite. Directories -are 0700 owner and files (including SQLite/WAL/SHM if present) 0600 owner, -with ownership, symlink/hardlink and generic mount checks. No remote, mirror, -seat token access or generic export. rehearse may read metadata for validation -only and cannot load content objects, emit quotes or restore readiness. - -Release does not silently delete evidence. A separate explicit human/ops -retention action may prune a stopped backup/post-attempt tree only after -checking it is not the selected recovery set or needed restore evidence, -recording its IDs/digests and a prune receipt. No automatic age-based prune, -no editing of retained metadata, no pruning runs/ under this policy. Until -that separately reviewed action exists, keep these private local metadata -trees indefinitely; it grants no content access. writing-context objects -have a distinct reviewed retention process and are never backed up by release. - -W4b owns the release guard changes, not a follow-up: all eight writing_* -tables above join COUNTED in scripts/stack-release.sh:420 and the T46 table -classification in packages/cli/tests/stack-release.test.mjs:913. They are -non-event writers, not classified as ignorable tables or double-counted as -generic events. Jason's existing exact --events N confirmation remains -required when the combined post-backup row count is nonzero. A restore plan -also compares writing row identities with the proposed source store; equal -aggregate counts cannot conceal a dropped revocation replaced by another row. -A schema with any unclassified writing_* table refuses restore readiness. - -An **independent host-private fence** lives outside bus/ and every backup: -`/writing-control/restore-fence.json`, directory 0700, regular file -0600, no links/mounts/remote/source-copy/rehearse access. Its exact schema is -`{version:1,epoch,restoreOperation,droppedRowsDigest,confirmedBusinesses}`. -epoch is a host-generated opaque ID; restoreOperation is null before the -first restore, otherwise a host-generated opaque operation ID; droppedRowsDigest -is SHA-256 of the canonical sorted dropped `(table,id)` list (empty allowed); -confirmedBusinesses is a sorted unique array of authenticated business IDs. -Only the trusted release controller and existing owner-proof handler write -it by durable atomic replacement; agents/testers/request paths cannot. -It is not a human-editable readiness setting: verified release readiness is -still required, and this file is an additional independent deny fence. - -**First creation:** the compatible release controller durably creates the -fence as part of W4b's first schema migration, before committing those empty -tables or enabling any handler. It uses a fresh epoch, restoreOperation=null, -droppedRowsDigest=SHA-256 of the canonical UTF-8 empty JSON array `[]`, and -confirmedBusinesses=[]. Every initial writing row uses that epoch. A normal -never-restored store does **not** require editor.restore.confirm: the -confirmation gate applies only when restoreOperation is non-null. Initial -live grants/shares and verified artifact readiness are still mandatory. - -Initialization is allowed only when the pre-migration schema has no writing_* -tables/history and there is no existing fence. If a crash leaves a durable -initial fence but the schema transaction uncommitted, migration resumes with -that same epoch, not another initial state. If writing tables/history exist -and the fence is missing/malformed, fail closed; never repair by creating a -new initial fence. Creating an initial fence is not a way around a previous -restore or revocation. W4b acceptance exercises both migration crash orders. - -Before **any** store swap/restore (not just one with nonzero counts), the -current compatible controller durably creates a fresh epoch, records dropped -writing rows and clears confirmedBusinesses. If fencing fails, restore -refuses before changing bus/. A crash anywhere keeps O2 denied. Old snapshot -rows have old restore_epoch; they cannot authorize even if their grant, -policy or share says enabled. Automatic failure recovery and rehearse-driven -restore use the same fence. Normal code rollback without store restore -keeps the fence and leaves O2 off on incompatible code. A pre-W4b controller -is not allowed to restore an O2-enabled data root: the active controller's -capability preflight refuses it; operations must use the compatible restore -controller even when the target runtime is old. - -After restore, the verified W4b runtime remains unavailable for O2 in every -unconfirmed business. New human-only -`editor.restore.confirm({expectedEpoch})`, under the business owner's existing -trusted human proof, acknowledges that business in the independent fence -and returns `{ok:true,result:{business,epoch,confirmed:true}}`. It restores -**no old grant/share/policy/conversation**. Fresh current-epoch grants, -a fresh dedicated conversation/default policy and fresh human chips must -be created explicitly. Past rows may be inspected by an authorized recovery -operator as metadata, but never used as current authority or prompt replay. -Every read/resolve/cursor/share checks matching restore_epoch and, when -restoreOperation is non-null, that business's explicit confirmation; old object bytes remaining on disk are not capabilities. -Thus even owner confirmation cannot revive a previously revoked old share. -Missing/malformed fence state denies O2. This current-epoch file does not -claim to detect a privileged manual rollback of both fence and database; -the supported restore protocol never restores the fence from a backup and -always rotates it first. A same-uid operator bypassing that protocol is not -a boundary this file can prove. --events N approves a -store operation only and is never a substitute for this recovery protocol. - -Acceptance seeds a secret in a content object and a share, takes a backup, -revokes access/sharing, then restores the backup with explicit row-loss -approval: the old share stays refused before and after owner confirmation; -a new grant/conversation/chip is needed. Sweep bus.sqlite, WAL/SHM, every -backups/stack and bus.post-attempt-* tree, rehearse output and release logs: -no secret/title/quote/body marker may appear. Only the explicitly named -private writing-context content object may contain it. Verify COUNTED/T46 -covers each table and simulate failure before/after each fence/store step. - -The XML/ZIP parser safety ceilings and absence-of-remote checks apply to -human store ingestion too where needed to prevent path escape and remote -replication; a projection-unsupported rich feature alone does not reject a -valid human save. Parser refusal codes have a fixed human-readable reason -category, never raw XML or a misleading empty context. Fields/hyperlinks/ -text boxes may make real chapters agent-unreadable in v1; the UI explicitly -says this and never claims an empty successful projection. - -Every extractor revision referenced by retained publication history or shares -is retained as a verified immutable host artifact. An activation missing one -refuses O2 readiness (no silent citation downgrade), including rollback to a -W4b-era release that drops a revision. A pre-W4b release can run with O2 wholly -off and cannot read those records. Retiring revisions requires a separately -reviewed retention/prune operation for all dependent O2 history/shares; not -an automatic stack-copy cleanup. Artifact caches are not authorization caches. +Three recovery cases are required: (1) crash after durable DOCX staging but before archive +push, (2) crash after archive push before publication, and (3) rollback --restore from a +pre-conversion bus backup while archive commits and O2 documents remain. The source is pinned +until final publication in cases1/2; after archive push state is visibly pending, never +'original untouched'. Case3 drops conversion rows only through the counted/approved restore +path. The durable host conversion journal/format registry is not restored from that older bus +backup. A compatible controller compares journal, both git histories, remote acknowledgment +and restored metadata before lookups/writes resume; it reconstructs missing metadata through +new recovery events without reviving Markdown or any old access grant. If reconciliation +cannot prove a single current identity/version, refuse that project's lookups and surface the +pending operation to the human. Do not replay chapter text into an old index or hide event loss. +Incompatible old binaries cannot activate converted projects through the supported controller; +raw privileged rollback tampering is outside the guarantee. Never rewrite git/run history. +Hermes retirement (#423 step5) is a production-opening prerequisite, with old story-write and +store-read access removed before any conversion/new-story operation. W7 checks its retirement +receipt and host capability preflight; no design seat retires services or accesses Melanie's +host. Independent tests use fixtures only. Preserve the existing stack grant/restore behavior; +the previous unimplemented W4 private-share restore-fence/table design is withdrawn with M1, +not backfilled into legacy rows. Conversion's durable registry is not an authorization token. ## 8. Acceptance matrix and release evidence -Each row needs a named fixture/test and a mutant or bypass probe in W4b's -packet. Independent fixtures construct OOXML directly and recompute Unicode -slices/digests outside the production extractor. Security checks fail closed; -no fixture-only readiness flag may exist in production APIs. +These are required future fixture gates, not implementation results. | ID | Evidence required | Negative control / bypass | | --- | --- | --- | @@ -865,117 +593,49 @@ no fixture-only readiness flag may exist in production APIs. | A03 | XML ID absent/duplicate and ordinal behavior | missing/mismatched paraId cannot silently choose another node | | A04 | Emoji, combining characters, tabs, breaks and split runs | UTF-16 offsets, normalization and whitespace collapse fail | | A05 | Literal split-run wiki forms retained | no path/URL fetch; malformed/cross-paragraph tokens stay text | -| A06 | Final/original/markup independently verified with moves/deletions | final-only grant cannot read deletion/comment; no document rewrite | +| A06 | Final/original/markup independently verified with moves/deletions | default final-body request cannot silently include deletion/comment stories; explicit part/view is separate, no document rewrite | | A07 | Body/note/endnote/comment exact ownership | orphan/dangling/cross-document references and duplicate IDs refuse | | A08 | Package allowlist, aliases, CRC, XML/ZIP limits | external rel, macro, traversal, symlink, entity, ZIP bomb and timeout refuse | | A09 | Commit snapshot and publication ordering | next latest after Saved gets new commit; no worktree/draft fallback | | A10 | Historical resolve stale label | old quote stays old; removed grant/history refuses without text | | A11 | Pagination complete/deterministic and bounded | tampered/foreign/revoked cursor and oversized row refuse | -| A12 | Cross-user/business/project/universe denial | guessed IDs, same blob elsewhere and copied document grant nothing | -| A13 | Visible range chip exact boundaries and default off before gate | no selection/title/path metadata before readiness; draft mapping refused | -| A14 | Every lookup intersects live grant and share | pin, old send, revoked scope and range-to-whole-document escalation fail | -| A15 | Whole-document latest share explicit; save rechecked | exact share cannot reveal future edits; persistent policy visible | -| A16 | Generic file/search/git/export/index paths denied | source copy, symlink, hardlink, alternate object root and new O2 copy probes | -| A17 | Raw session, fork/resume and transcript boundaries | revoked context cannot replay via raw tool or harness history | -| A18 | Agent tools exactly read/resolve/flag after gates | native MCP, execute, save, replacement and story comment writes refuse | -| A19 | Existing C2 Markdown reads/line cites unchanged | no DOCX-as-lines conversion or redirect following adoption | -| A20 | Adoption gate before/after readiness and Q36 disposition | absent/revoked server readiness and required notice readiness refuse | +| A12 | Cross-user/business/project/universe denial | foreign project/universe IDs, same blob elsewhere and guessed unpublished objects grant nothing | +| A13 | Selection chip points only at committed text; ordinary lookup authority independent | draft mapping refuses; missing chip does not deny an authorized lookup | +| A14 | Normal project/universe/source-scope checks in every thread/room | pin, guessed ID, foreign universe and revoked holder cannot grant access | +| A15 | Latest after acknowledged save; explicit historical cite stays immutable | chip/per-send snapshot cannot force stale latest results | +| A16 | Host-only store and remote credentials; checked reader routes only | no worker store mount, arbitrary git/engine access or seat remote token | +| A17 | Existing Case 2 message/transcript policy | no O2-only/raw-session backdoor that skips existing thread/project checks; no false erasure promise | +| A18 | Reader/resolve/flag plus existing Case 2 lookups/supporting writer after gates | native MCP, execute, save, replacement and story comment writes refuse | +| A19 | Unconverted/support Markdown unchanged; converted path returns record and DOCX | no stale archive as chapter or DOCX-as-lines; historical line cite verifies by old commit/blob | +| A20 | Conversion/new story gates W4b/W7/PRD/post-10-27/Hermes/owner go | agent start, missing readiness, early release, fixture flag and missing first-real-book go refuse | | A21 | Human full-feature save remains separate | unsupported projection yields no agent context, never lossy human save | | A22 | Scope revocation during extraction | final pre-emission check prevents async stale-authority leak | | A23 | Sibling chapter save | currentCommit/stale/cursor for untouched document remain unchanged | | A24 | Full page and oversized paragraph | end before overflow; first oversized row refuses without text; no unreachable subrange claim | -| A25 | No O2 git remote or release copy | seat Gitea list/fork/clone fails; configured remote/object alternate disables O2; copies exclude stores | -| A26 | Every section 7.4 store/renderer | secret marker absent in each named legacy store, raw session, CLI/Discord/Console view and runs/ | -| A27 | Pre-W4b rollback reader | new O2 rows never rendered through legacy tables; missing retained extractor disables O2 | -| A28 | Dedicated mode vs C2 | mixed attachment/resume/fork denied; unchanged C2 supporting writes/replies fixtures pass | -| A29 | Two humans/viewer/grant revisions | viewer cannot share; second human cannot join or reuse context; all cursor authority fields checked | +| A25 | Every read/write/tool surface uses existing Case 2 isolation | same document ID across business/universe or replayed cursor refuses | +| A26 | Host-only off-host remote and per-save push | unset/local-only/unexpected remote refuses opening; push outage visible, local next lookup still fresh | +| A27 | Conversion restore accounting and durable journal reconciliation | pre-conversion --restore loses counted row but cannot revive Markdown; no lost-event concealment | +| A28 | Reopened M1 supports same-thread DOCX-read then supporting-note write | any room/project-authorized caller works; no per-document/share token; story/archive write refuses | +| A29 | Readiness is reviewed runtime/extractor plus approved PRD, not caller fields | no request/go/setting can assert release or Hermes retirement | | A30 | Canonical schemas and complete selections | unknown keys, inconsistent ranges, xmlId null mismatch and noncanonical story IDs refuse | | A31 | Closed leaf/revision table | every leaf/nested rule; mark-only deletion keeps text in final, mark-only insertion keeps text in original; markup mark spans zero-width; Word -1 separator/0 continuation-separator and older 0/1 reserved layouts validate, references to them refuse | -| A32 | Initial migration and revocation/restore | initial null-operation fence needs no restore confirmation but no grant is implicit; non-null restore fence needs confirmation and fresh authority; all tables counted/classified; old share stays refused; crash/backup-marker sweeps | +| A32 | Existing grant/restore controls and conversion metadata COUNTED | restore cannot revive grant, current Markdown or uncounted conversion event | +| A33 | Staging/archive/publish journal and operation readback | crash/sync at every boundary; pinned source until publish; post-push failure pending, not undone | +| A34 | Manifest order, typed index/links and format map | next_chapter never archive; draft scope retained; cross-universe/hybrid exclusions and R4/R5/R6 | +| A35 | Per-file fidelity, source history, human controls | all constructs/wiki/front matter preserved; no agent conversion; new DOCX has no Markdown precursor | -Implementation acceptance includes writing, bus, harness, business, WebUI, -seat mount/import closure and stack-copy/release fixtures; explicit production -adoption refusal/lift tests; independent parser/policy/tool review; G1 and -Sage's allocated schema edge. Evidence must name skips and refuse enablement -when an acceptance guard was not exercised. W4's review alone lifts nothing. +Implementation acceptance includes exact schemas/parser fixtures, live project/universe +revocation probes, same-thread supporting writes, remote denial/failure, counted-event restore +cases, Hermes gate, pinned-copy/sandbox closure and G1. All skips are named; an unexercised +guard blocks enablement. Old O2-only/private-share acceptance wording is replaced, not claimed +passed. No test, conversion or runtime experiment ran for this rewrite. -## 9. Handoff and unresolved decisions +## 9. Reopened review and handoff -Megavolt reviews this separate document and records a verdict in -`docs/reviews/2026-10-22_q195-docx-citations.md`. Revisions repeat direct -commit/blob handoff to Megavolt and Sage. Q36 remains with Jason through Mos; -no adoption, C2 reader/reply notice change or schema reinterpretation ships -on this document. W4b's brief must allocate ownership for every surface in -A16/A17 and section 7.4 before code: an unowned enforcement path is a blocker, not a deferred security -note. No live files, editor source imports, parser execution or tests were -used to write this design. - -## Round 2 changes against review 08fcb8c1c - -B1: exact selection wrapper, canonical paragraph identity, wiki/anchor schema, -chip/share and refusal records; ordinal-primary D25 refinement explicit. -B2: closed leaves and nested/paragraph-mark revision rules. B3: per-document -publication sequence and sibling-save acceptance. B4/B5: concrete append-only -authority, human proof, exact/latest share policy, revision vector and -single-human dedicated session lifetime. B6: complete-row paging; oversized -paragraph unsupported, no circular subrange API. B7: no remotes/backup push, -seat token and copy probes. B8: named native stores, renderers and immutable -run evidence, with O2-only storage/adapter readiness. B9: tables/columns, -rollback separation and extractor retention. M1: dedicated O2 conversations -only; mixed C2 context refused, no C2 requirement change. N1-N7 addressed in -canonical manifest, bound-business check, ratio/default wording, UI unavailable -reason, release-derived readiness and new A23-A31 acceptance rows. These are -proposed definitions, not passing implementation tests. Q36/adoption unchanged. - -## Round 3 changes against review 0d627a2b3 - -R2-B1: paragraph-mark revisions preserve all run text; markup has a zero-width -mark span, never a fabricated whole-paragraph deletion. Reserved note leaves -are allowed only in reserved stories; whole-part structural validation is -explicit. A31 covers both mark-only cases and reserved notes. -R2-B2: bodies/quoted share payloads move out of SQLite into private content -objects; backup/post-attempt metadata paths are named with access/retention -rules. Every writing_* table is COUNTED/T46-classified. A non-restored deny -fence changes epoch before any store swap; owner confirmation cannot revive -old-epoch grants/shares. A32 tests revocation/restore and secret-marker sweeps. -R2-N1: agent grant subject means agentInstance. R2-N2: structural leaves have -one table. This remains design only; no code, restore, parser run or test. - -## Round 4 changes against review 9fb999abf - -R3-B1: reserved-note classification is by type with any canonical signed ID, -not sign; normal notes require nonnegative IDs, and references to reserved -notes refuse. A31 covers both actual Word layouts. R3-B2: first migration -creates the durable initial epoch before schema commit; null restoreOperation -needs no recovery confirmation, a restored epoch does. Missing established -fences never reinitialize. A32 covers first enable and post-restore states. -R3-N1: business/row/private random nonce are part of each content object and -its path, so no cross-business deduplication or guessed-body digest oracle. -R3-N2: removed the unsupported claim to detect privileged manual rollback -of the fence itself. R3-N3: restore_store anchor corrected to :498. - -### Public Word fixture confirmation (not an extractor test) - -Inspected only public Microsoft-maintained test packages in memory using -Python ZIP/XML readers, not the O2 parser or a live/user document. No binary -was imported into this repository. Source: -[OfficeDev/Open-Xml-PowerTools FootNote.docx](https://github.com/OfficeDev/Open-Xml-PowerTools/blob/a9187c5ec4199106562ec91c5ffd9f355251253b/NewDocxDocuments/FootNote.docx), -14,214 bytes; DOCX SHA-256 -`40e2de78f0f70d8acf3db734df13f107c92986f1a40865cdf9772a8b55ab5e20`. -Its app properties identify Microsoft Office Word, version 15.0000. -footnotes.xml has separator=-1, continuationSeparator=0, normal note=1; -endnotes.xml has separator=-1 and continuationSeparator=0. -footnotes.xml SHA-256 -`1da08d9c0a4a1af2706c035dfb176defd179686f81418134b796d49649e850a0`; -endnotes.xml SHA-256 -`f83e7f1c9f91b44db26b147b22ca615a13488bc6a8084febb392ee00a6ca4f5e`. -This confirms the reviewer's -1/0 example in a Word-identified fixture. - -An older independent Microsoft SDK fixture confirms why IDs cannot define -the class: -[Open-XML-SDK ForTestCase/footnote.docx](https://github.com/dotnet/Open-XML-SDK/blob/431ab05cf160248cc3885a4a766026d4f8243792/test/DocumentFormat.OpenXml.Tests.Assets/assets/TestDataStorage/v2FxTestFiles/ForTestCase/footnote.docx), -69,706 bytes, SHA-256 -`26dc62a5d00e2c3c1df60e0d5bf1cac43b142a090ea595b9ad11ce73e3dab268`. -It identifies Microsoft Office Word 12.0000 and uses reserved IDs 0/1 in -both parts, with normal footnotes 2/3. No claim is made that the whole -packages pass v1's otherwise deliberately restrictive projection rules. +Fenton reviews this policy rewrite against mos-1368's A17–A41/Q1–Q16 and mos-1372 D1–D9, +including reopened M1 and A19/A20/A28, host-only remote and C5 restoration. Megavolt's old +APPROVE stays historical at the original blob; no author writes its verdict file. The +locator/projection facts remain source-backed, but the new authority/tool/runtime contract +requires its own independent approval and the Case 2 PRD approval, not a silent addendum. +Owner sends both design blobs/commit to Fenton, Mos and Sage. No code, private document, +conversion, source build/browser test, queue entry or live change is authorized here.