Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f4fa4f939 | ||
|
|
691235ad57 | ||
|
|
8d209016b6 | ||
|
|
1ac76a4177 | ||
|
|
e36bce3526 | ||
|
|
17a48a7782 | ||
|
|
e012bab0be |
No files matched your search
@@ -5344,3 +5344,27 @@ Gander: after Duckworth-0100 design approval with C1-C5, prepared the two host-s
|
||||
2026-10-22T18:11:57Z | Sage | Row 275 (#1780, Morgana, Duckworth) LANDED 3410df7c3. Before: refactor at 48e450ce8; viewers had no verb list of their own and board reads were not refused to users. After: a fast-forward of 3 commits; manifest 39847b15 (4 paths) blobs match; gate 17:52:12Z-18:05:00Z green (whole files 7/22/6, bus 834, cli 861, harness 151, business 231, seat 167, 10 scripts with 3 named skips), M6 and M10 killed; Duckworth APPROVE rev 3260 (comment 30717); note and done by sage-2897; #1780 comment 30728 and closed. N1 (board refusal test as a loop over BOARD_VERBS) is non-blocking.
|
||||
|
||||
2026-10-22 18:11:58 UTC | Gander row276 #1781 prepared, gate pending | Before: row253 left5legacy Case1 AS_USER calls unsupervised across sudo pty sessions. After: candidate uses its unchanged supervisor with per-call inner/outer budgets, separate streams, strict display-only failure trailer, fake-only paired process-model cases and15unique mutants. Duckworth0182 B1 corrected the plan before product code;0183 cleared build. Parse-only Bash checks pass; no Node, behavioral test, host, unit or config action. Runtime gate and publication await Sage.
|
||||
|
||||
2026-10-22T23:03:39Z | Gyro Q195 O2 rewrite, #1752 / Vikunja #448, mos-1356 | Before: landed O3 design 95e3f7166/blob 4cb59999. After: Q231/Q233 full WordCraft O2 design on gyro/editor-o2 from refactor c4f77373f; canonical git DOCX, original Markdown/wiki preservation, human cadence default 0 with instant accepted-save commits, full rich-feature first slice. Ten briefs include independent source/dependency security clearance before any build queue entry, exact editor-only CSP approval gate, restricted source/build/bridge, separate reviewed DOCX citation gate and flags-only agent access. Existing Case 2 semantics unchanged; any integration requirement change goes through Mos to Jason. Static checks: ten briefs/seven fields, independent reviewers, unique anchors, current source/base/blob pins, docs scope and append-only logs pass. No builds, browser/worker runs, code, queue or live changes. Fenton review pending; CSP and implementation gates remain closed.
|
||||
|
||||
2026-10-22T23:03:53Z | Gyro Q195 O2 push guard | CI queue guard identity gyro / purpose push returned exit 0, documented degraded-pass: CANNOT_ASSERT credential-unresolvable. Audit: /mnt/storage/scratch/gyro-q195-ci-queue-audit.jsonl. No credential fallback or CI-green claim.
|
||||
|
||||
2026-10-22T23:09:38Z | Gyro Q195 O2 fenton-0006 fixes | Before: e012bab0b left stale-source ambiguity, incomplete migration/shipping ownership, undefined typing transactions and an unmeasured CSP gate. After: D12 explicitly routes superseded-source/C2 reply notices to Mos/Jason and refuses adoption before W4b/notice path; Q2 remains open. F2-F6 add schema-edge placeholders and restore-accounting files, shipped runtime data/writing closure with no sandbox store mount, per-chapter DOCX and 2s-pause/15s-span save groups, volume/latency/growth gates, split-run clickable wikilinks and historical Obsidian graph warning, and S0 isolated existing-artifact CSP measurement before exact-header approval. Static ten-brief/ownership/settings/checklist checks pass. No build/browser run, product/queue/live change. Independent re-check pending.
|
||||
|
||||
2026-10-22T23:09:50Z | Gyro fenton-0006 push guard | identity gyro, purpose push, exit 0 documented degraded-pass CANNOT_ASSERT credential-unresolvable; audit gyro-q195-ci-queue-audit.jsonl. No fallback credentials or CI-green claim.
|
||||
|
||||
2026-10-22T23:10:14Z | Gyro mos-1358 ruling recorded | Q36 / Vikunja 562 keeps C2 superseded notices OPEN with Jason. Markdown adoption refusal until W4b PASS is now a separate settled Mos build-order ruling, not a Jason question. D12 and Q2 distinguish them; no notice build authorized.
|
||||
|
||||
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.
|
||||
|
||||
2026-10-23T01:41:59Z | Gyro sage-3121 A1-A3 PRD alignment | Before: 8d209016b adds a current Connections graph, excludes new Markdown stories in converted books and defaults archiveFolder. After: parent/W4 align with PRD1.17 d6 sha256 886b93c571f87bfbb2f27ee3113b6800a32d8f89196d95ace33566031bee380a: clickable editor links only; graph/tests later pending J-b; new different-path Markdown in a converted book remains canon until import, only recreated converted old paths are unmapped; archive folder is human-set in library mapping with no default, missing folder refuses conversion. Static A1-A3/11-brief checks pass; W4 locator/extractor/access/remote/recovery blocks unchanged. Local commit only, push held for Sage's named gap while Gizmoduck holds 270+271 run5. No product/build/browser/worker/queue/live action. Fenton gets local SHA through shared object store.
|
||||
|
||||
2026-10-23T01:49:08Z | Gyro fenton-0012 B1/B2 and N1-N6, mos-1379 | B1: off-host remote must deny the real shared jason.woltje seat-helper credential as well as seat identities until #431; private visibility/dummy-token denial is insufficient; W3b/A16/A26 require that future fixture proof. B2 follows mos-1379: human-only editor.agentReadComments and editor.agentReadTrackedDeletions both default false, comment/original/markup reads/resolves/index/context refuse when off; final access remains D9 and no role allowlist/per-document grant. N1 staging-ref allowlist and retained private refused/published audit refs; N2 URLs literal with fidelity-report loss and confirmation; N3 future paths marked new or predecessor row; N4 rename/sharing wording fixed; N5 historical thread text not refreshed; N6 protected VM1012 backup cited in P5. Static checks pass, locator JSON/package/projection mechanics retained. Local commit only; HTTPS push still held for Sage's named gap. No credentials tested/read/printed, no product/build/browser/worker/queue/live action. Fenton gets exact local SHA/blobs.
|
||||
@@ -1549,3 +1549,10 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-22 | Della | Row258 E01 3094e3bfa focused manifest review | APPROVED 11-path manifest/static F1/F2/N1 corrections; file and full-blob digest recipes verified. M1-M11 fixed; all execution/landing evidence still required in CLEAR. No shared-log edit, Node, tests, HTTPS Git or live action.
|
||||
2026-10-22T17:55:40Z | Sage (Opus 5.5, 1ef1e4f8) | Row 253 landing; post-253 doc sweep | 253 LANDED 48e450ce8. Sweep on sage/sweep-253: Gosalyn Case 2 design and rows, 229 design, Gyro 0acbdb0d8, Della 179391055, 268 docs, seat dirs for Della, Scrooge, Huey, Louie and Ludwig, human-users-build:70 under Q173, DEFERRED 253 N1, 198 N2, row 203 text, 224 residual and 206 sharee list, and seat log lines.
|
||||
2026-10-22 14:48 UTC | Researcher (Sonnet 5.5, 9bac0794) | Rows 220 and 216 resumed (sage-2708, sage-2716, sage-2719); local commits only | 220 e4a204836 on researcher/row220-r2 (on ea6dc9eff): C1 run tests, C2 default-reader M7 test, configDirectory fixture scope, BUILD.md round 2b. 216 4f3fbc25a on researcher/row216-r2 (on aca16404c): index cache, find/get/search/manuscript/universeInfo, PRD 1.14 levels. Nothing pushed, claimed or run; node --check not run. Waits for Sage's CLEAR and go; rebase onto 253 on a new branch before any gate.
|
||||
2026-10-22T23:03:39Z | Gyro (Codex gpt-6.1-sol, mos-1356) | Q195/Q231/Q233 O2 design rewrite, gyro/editor-o2 from c4f77373f | Canonical queue next gyro: nothing. Ten docs-only briefs; full-feature WordCraft, independent 15-crate/199-package security review, editor-only CSP candidate, instant git DOCX saves and retained Markdown/wiki sources, committed-only DOCX citation gate, no agent story prose. Static structure/source-anchor/scope checks only; no code, build/run, queue or live change. Fenton review requested after push.
|
||||
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.
|
||||
2026-10-23T01:41:59Z | Gyro (Codex gpt-6.1-sol, sage-3121) | 571 PRD d6 A1-A3 alignment | Both designs corrected and statically checked; local commit for Fenton in shared repo object store. HTTPS push held for Sage gap, independent review pending. No product, test-slot, queue or live change.
|
||||
2026-10-23T01:49:08Z | Gyro (Codex gpt-6.1-sol, fenton-0012/mos-1379) | 571 B1/B2 and N1-N6 docs corrections | Real-helper denial gate and two off-by-default human review settings; static acceptance/brief/immutable-mechanics checks pass. Local candidate for Fenton via shared Git objects; no HTTPS push before Sage gap, no runtime or credential experiment.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,671 @@
|
||||
# Q195 O2 W4: committed DOCX citations and Case 2 access
|
||||
|
||||
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. Confirmed format policy and approval gates
|
||||
|
||||
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.
|
||||
|
||||
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 and mos-1374's protected manual VM1012 backup before the
|
||||
first real import, handled by its authorized human operator, not this design seat. 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.
|
||||
|
||||
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. Final accepted text follows that access. Under mos-1379,
|
||||
editor.agentReadComments and editor.agentReadTrackedDeletions are human-only booleans,
|
||||
both false by default. The former gates comment stories; the latter gates original/markup
|
||||
views. This is two settings, not a role-level allowlist or per-document grant. 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.
|
||||
|
||||
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 archive is in the source-repository folder set by a human in the library mapping.
|
||||
There is no default; missing/invalid folder keeps conversion closed. It is recorded 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.
|
||||
Pre-conversion text already in thread history is not rewritten/refreshed; its cites verify
|
||||
against their original commit/blob and show historical/converted state, not the current DOCX.
|
||||
A Markdown file recreated at a converted old path is unmapped, neither canon nor playground,
|
||||
excluded from lookups and flagged to the human. A new Markdown story at a different path in
|
||||
a converted book stays canon until import, flagged and offered for human import; no automatic
|
||||
conversion. Existing playground scope rules remain. Clickable DOCX editor links stay; no
|
||||
DOCX graph exists yet. A Connections graph and its tests wait for Jason's J-b answer.
|
||||
|
||||
Every conversion runs the pinned extractor before archiving and refuses unsupported output.
|
||||
An independently reviewed importer preserves every wiki token and front-matter key.
|
||||
The v1 extractor does not accept OOXML hyperlinks: emit Markdown label/URL as literal text
|
||||
with a fidelity-report entry for lost clickable behavior, never w:hyperlink/r:id. Bare URLs
|
||||
stay literal; wiki links stay exact and host-clickable. Unsafe/unrepresentable URLs refuse.
|
||||
This handled literal mode is explicitly confirmed before archive push; 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.
|
||||
|
||||
## 2. Document identity, order and freshness
|
||||
|
||||
Host code alone opens `<dataRoot>/writing/<business>/<project>/`. 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
|
||||
|
||||
All objects reject unknown keys. IDs are nonempty ASCII `[A-Za-z0-9_-]{1,128}`;
|
||||
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 DOCX records for the Case 2 lookup/citation union.
|
||||
|
||||
A locator is exactly:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "docx-range", "version": 1,
|
||||
"business": "acme", "project": "book", "document": "chapter_1",
|
||||
"commit": "<40 lowercase hex>", "blob": "<40 lowercase hex>",
|
||||
"extractor": {"id": "mosaic-docx-text-v1", "revision": "<64 lowercase hex>"},
|
||||
"part": {"class": "body", "name": "word/document.xml", "story": "main"},
|
||||
"paragraph": {"ordinal": 0, "xmlId": null},
|
||||
"start": 0, "end": 5, "textView": "final", "quote": "Hello",
|
||||
"quoteDigest": "<sha256 of UTF-8 quote>"
|
||||
}
|
||||
```
|
||||
|
||||
Part triples are exact: body/main uses the body part; footnote/endnote/comment
|
||||
uses its class-matching part and a canonical nonnegative decimal story ID
|
||||
(`0` or `[1-9][0-9]*`), never a user path. Paragraph `xmlId` is JSON null
|
||||
when absent. A textView is always recorded in every locator; there is no
|
||||
resolver default. quote is a nonempty valid Unicode string bounded to 16,384
|
||||
code points and 64 KiB UTF-8. Unknown enum values or unexpected types refuse.
|
||||
|
||||
The ordinal-primary rule below deliberately refines D25's wording ("IDs
|
||||
when present, otherwise ordinal"): a possibly duplicated paraId is a required
|
||||
cross-check, never the lookup key. This is an O2-only design choice for Sage's
|
||||
implementation brief, not an amendment to Case 2.
|
||||
|
||||
`paragraph.ordinal` is the zero-based paragraph index within the selected
|
||||
story, in deterministic XML document order, including empty paragraphs and
|
||||
table-cell paragraphs. `xmlId` is null exactly when the selected node has no w14:paraId, otherwise the literal eight-hex `w14:paraId`,
|
||||
canonicalized uppercase. Ordinal is always present: paraId alone is not
|
||||
unique or stable enough. The key is mandatory: passing null for a node that has the attribute refuses.
|
||||
The non-null value must equal that node's attribute; duplicated IDs do not
|
||||
trigger a search, since ordinal selects the node. Mismatches refuse.
|
||||
Thus identical paragraphs remain distinct. `start < end <= codePointLength`
|
||||
selects one paragraph, end exclusive. A multi-paragraph selection has the exact wrapper below, not a bare array:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind":"docx-selection", "version":1,
|
||||
"business":"acme", "project":"book", "document":"chapter_1",
|
||||
"commit":"<40 lowercase hex>", "blob":"<40 lowercase hex>",
|
||||
"extractor":{"id":"mosaic-docx-text-v1","revision":"<64 lowercase hex>"},
|
||||
"part":{"class":"body","name":"word/document.xml","story":"main"},
|
||||
"textView":"final",
|
||||
"ranges":[
|
||||
{"paragraph":{"ordinal":0,"xmlId":null},"start":1,"end":5,"quote":"ello","quoteDigest":"<64 lowercase hex>"},
|
||||
{"paragraph":{"ordinal":1,"xmlId":null},"start":0,"end":5,"quote":"World","quoteDigest":"<64 lowercase hex>"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
It has 2..32 ranges, all sharing the wrapper's exact document, publication,
|
||||
blob, extractor, view and part. Ordinals are consecutive and increasing.
|
||||
First range ends at its paragraph length, last starts at zero; intermediate
|
||||
ranges cover whole paragraphs. Each range verifies its own quote/digest;
|
||||
no inserted newline is included in any digest. Empty intermediate paragraphs
|
||||
are represented by start=end=0, quote="" and SHA-256 of empty UTF-8; the first
|
||||
and last are nonempty. Total quote budget is 16,384 code points and 64 KiB
|
||||
UTF-8 for the entire selection. A one-paragraph selection uses docx-range
|
||||
only: there is one canonical representation. No auto-merging, cross-story
|
||||
selection or clipping. Resolver's locator union and a range chip accept
|
||||
either exact kind. An atomic selection fails entirely if any range fails;
|
||||
a response never returns only the valid fragments.
|
||||
|
||||
`extractor.revision` is the digest of a canonical build manifest containing
|
||||
extractor source blob IDs, projection rules revision and locked parser/ZIP
|
||||
library versions. The release pins that manifest and independently verifies
|
||||
its digest. It is not caller-supplied executable code or a mutable version
|
||||
label. Its canonical manifest is exactly `{manifestVersion:1,id,rulesRevision,
|
||||
sources,dependencies,formattingProperties}`. id is mosaic-docx-text-v1,
|
||||
rulesRevision is integer 1; sources is a path-sorted array of `{path,blob}`
|
||||
for every extractor/transitive source input; dependencies is a name-sorted
|
||||
array of `{name,version,integrity}` from the lock, including ZIP/XML parsers;
|
||||
formattingProperties is a sorted unique array of expanded XML names.
|
||||
Duplicate keys/entries refuse. Canonical bytes are compact JSON, UTF-8,
|
||||
no BOM/newline, recursively lexicographic ASCII object-key order; strings
|
||||
escape only quote/backslash and U+0000..001F (lowercase four-hex \u escapes),
|
||||
with other scalar values literal. Arrays preserve the specified sorted order,
|
||||
integers are decimal without leading zeroes. revision is SHA-256 of those
|
||||
bytes. Independent tooling must reproduce it. Server readiness is derived
|
||||
from the verified release artifact containing that manifest and its reviewed
|
||||
formatting list, not any human-authored config field.
|
||||
Resolver requires that exact available revision; changed extraction
|
||||
rules create a new revision, never silently reinterpret an old locator.
|
||||
|
||||
A paragraph extraction record is exactly:
|
||||
|
||||
```json
|
||||
{
|
||||
"part": {"class": "footnote", "name": "word/footnotes.xml", "story": "7"},
|
||||
"paragraph": {"ordinal": 0, "xmlId": null},
|
||||
"textView": "final", "text": "Note text", "length": 9,
|
||||
"textDigest": "<sha256 UTF-8 text>",
|
||||
"anchors": [], "wikiTokens": []
|
||||
}
|
||||
```
|
||||
|
||||
Anchors have the exact shape `{kind,story,offset}`; allowed
|
||||
kinds are `footnote-reference`, `endnote-reference`, `comment-start`,
|
||||
`comment-end`, `comment-reference`; story is a canonical decimal nonnegative XML
|
||||
ID string (`0` or `[1-9][0-9]*`, the same as note/comment locator stories),
|
||||
offset a code-point boundary in this record. They never grant
|
||||
access to their target. wikiTokens have exactly `{start,end,literal,form,target,label,heading}`.
|
||||
form is link/label/heading/embed; label and heading are null except in their
|
||||
corresponding form. target is 1..256 code points without `[`, `]`, `|`, `#`,
|
||||
control characters or newline; a label/heading is 1..256 code points without
|
||||
brackets, `|`, `#`, controls or newline. literal is respectively `[[target]]`,
|
||||
`[[target|label]]`, `[[target#heading]]` or `![[target]]`. start/end are exact
|
||||
paragraph code-point bounds, including the exclamation for embed. No nested
|
||||
forms or combined label+heading/embed variants are interpreted in v1; they
|
||||
remain text. Tokens are maximal nonoverlapping complete forms in left-to-right
|
||||
order, with their literal equal to the text slice. They are not instructions
|
||||
or external links. All text
|
||||
and metadata are untrusted document data. Part/story IDs, excerpts and
|
||||
comment content never enter system prompts as instructions.
|
||||
|
||||
## 4. Story classes and package validation
|
||||
|
||||
Version 1 accepts transitional WordprocessingML namespace
|
||||
`http://schemas.openxmlformats.org/wordprocessingml/2006/main`, relationships
|
||||
`http://schemas.openxmlformats.org/package/2006/relationships`, office
|
||||
relationship types rooted at
|
||||
`http://schemas.openxmlformats.org/officeDocument/2006/relationships/`, and
|
||||
`w14:paraId` from `http://schemas.microsoft.com/office/word/2010/wordml`.
|
||||
Prefixes are irrelevant; expanded namespace/local names decide. Strict OOXML
|
||||
and unknown alternate-content choices refuse until a separately pinned
|
||||
extractor supports them; never guess equivalent namespaces.
|
||||
|
||||
| Class | Exact part names | Story selector | Agent exposure |
|
||||
| --- | --- | --- | --- |
|
||||
| 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 plus human comments setting; 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 |
|
||||
|
||||
Body/note/comment ownership comes solely from relationships in that committed
|
||||
package, not filenames supplied by a request. A note/comment belongs to one
|
||||
DOCX, never the book or an adjacent chapter. Classify reserved notes by
|
||||
w:type in {separator, continuationSeparator, continuationNotice}, with any
|
||||
canonical signed integer ID (`0` or `-?[1-9][0-9]*`, no plus/leading zeroes),
|
||||
not by sign. A normal note has absent type or type normal and a canonical
|
||||
nonnegative ID; unknown types refuse. Reserved notes are structural and never
|
||||
readable stories. Any document reference to a reserved note refuses, including
|
||||
an id-0 continuation separator; the reference must resolve to a normal note. Duplicate story IDs, dangling references or overlapping
|
||||
ambiguous comment ownership refuse extraction. Unreferenced comment/note
|
||||
stories are not agent-readable. Cross-paragraph comment anchors may be
|
||||
recorded, but never concatenate their text with body text.
|
||||
|
||||
The root `_rels/.rels` must contain exactly one internal officeDocument
|
||||
relationship to `word/document.xml`. Its matching content type is
|
||||
`application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml`.
|
||||
Optional footnotes/endnotes/comments each have at most one matching internal
|
||||
relationship and their matching `...wordprocessingml.{footnotes,endnotes,comments}+xml`
|
||||
content type. Their relationship targets must be the exact part names above.
|
||||
Reject normalized-path aliases, absolute paths, traversal, encoded separators,
|
||||
backslashes, duplicate ZIP names, symlink entries, encryption and overlapping
|
||||
ZIP data. Never extract ZIP entries onto the filesystem.
|
||||
|
||||
Only internal relationships of types officeDocument, styles, numbering,
|
||||
settings, webSettings, fontTable, theme, image, header, footer, footnotes,
|
||||
endnotes and comments are accepted. Resolve internal targets relative to the
|
||||
owning part within the package, reject escape and validate existence/type.
|
||||
Reject every external relationship, hyperlink relationship, altChunk,
|
||||
attachedTemplate, OLE, package embedding, VBA/macro content type or executable
|
||||
part. Textual literal wiki links need no relationship. Unsupported rich
|
||||
constructs refuse the agent projection, not the human save: the human can
|
||||
retain a full document without it becoming readable to agents.
|
||||
|
||||
Parse XML without DTDs, external entities, XInclude or network/file resolution.
|
||||
Reject DOCTYPE/entity declarations. Bound before allocation: compressed blob
|
||||
32 MiB, total expanded bytes 128 MiB, each entry 16 MiB, 2048 entries,
|
||||
expansion ratio 100:1 both per entry and for the total (nonempty expanded data with zero compressed bytes refuses), XML depth 128, 1,000,000 nodes, 100,000 paragraphs,
|
||||
1,000,000 code points per paragraph and 10,000,000 per document. Extraction
|
||||
has a 5 s host deadline and bounded worker memory of 256 MiB. Exceeding any
|
||||
bound yields `editor-document-unsupported`, no truncated success. These are
|
||||
initial server safety ceilings, not grants or business quota settings;
|
||||
changing them requires reviewed parser evidence. CRC/size mismatches refuse.
|
||||
|
||||
## 5. Deterministic reading views
|
||||
|
||||
`textView` enum is `final`, `original`, `markup`. Default requests use final.
|
||||
Final is the accepted-reading projection, not an accept-changes operation.
|
||||
A text run is visible in final iff no ancestor is w:del or w:moveFrom; in
|
||||
original iff no ancestor is w:ins or w:moveTo. This ancestor veto applies to
|
||||
nested revisions, so an insertion inside a deletion is absent in both final
|
||||
and original. Markup includes both in source order with revision spans for
|
||||
every revision container (nested spans may overlap). w:t and w:delText use
|
||||
the same ancestor rule, never special substring searches. Revision IDs are
|
||||
canonical nonnegative decimals; malformed or unmatched move ranges refuse.
|
||||
|
||||
Paragraph-mark revisions under pPr/rPr mark only the paragraph boundary,
|
||||
not the runs' text. A mark-only w:ins or w:del changes **no projected text**
|
||||
in final or original: run content follows the ancestor rule alone. Although
|
||||
accepting a mark deletion in Word joins paragraphs, this locator projection
|
||||
never merges, splits or renumbers XML paragraphs in any view. It preserves
|
||||
the text on both sides as separate ordinal records. In markup a paragraph
|
||||
mark contributes a zero-width span at that paragraph's code-point length,
|
||||
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 require editor.agentReadTrackedDeletions=true; comment stories require
|
||||
editor.agentReadComments=true. Both are human-only and false by default (mos-1379); a comment
|
||||
in original/markup needs both. Check them in addition to ordinary project/universe access,
|
||||
refusing with editor-access-refused and no text when off. No role-level allowlist or
|
||||
per-document grant is added. A final-body read stays available and never silently includes
|
||||
deleted revisions/comments. Human editor review/save remains full-featured and unaffected. Revision author/date metadata
|
||||
is omitted from agent responses in v1.
|
||||
|
||||
Closed story/run leaf table (all names in w namespace unless stated):
|
||||
|
||||
| Leaves | Text/anchor contribution |
|
||||
| --- | --- |
|
||||
| t, delText | decoded text subject to view/ancestor rule |
|
||||
| tab | U+0009 |
|
||||
| br, cr | U+000A, regardless of page/column type; layout kind does not affect offsets |
|
||||
| noBreakHyphen | U+2011 |
|
||||
| softHyphen | U+00AD |
|
||||
| annotationRef | zero text; only allowed in comment story |
|
||||
| separator, continuationSeparator, continuationNotice | structural only, allowed only inside reserved footnote/endnote stories; never projected |
|
||||
| footnoteRef, endnoteRef | zero text; only in matching note story |
|
||||
| footnoteReference, endnoteReference | zero text; matching anchor at current offset with canonical story ID |
|
||||
| commentRangeStart, commentRangeEnd, commentReference | zero text; matching comment-start/end/reference anchor |
|
||||
| moveFromRangeStart, moveFromRangeEnd, moveToRangeStart, moveToRangeEnd | zero text; validate paired IDs, do not duplicate revision text |
|
||||
| bookmarkStart, bookmarkEnd, permStart, permEnd, proofErr, lastRenderedPageBreak | zero text; structural only, never access grants |
|
||||
| sym, ptab | refuse requested story (font/position dependent) |
|
||||
| fldChar, instrText, delInstrText, fldSimple | refuse requested story, including field results |
|
||||
| drawing, pict, object, txbxContent, subDoc, altChunk | refuse requested story |
|
||||
|
||||
Leaf validation covers **the entire selected XML part**, including all its
|
||||
normal and reserved stories, before any requested story is projected. Reserved
|
||||
separator/continuation notes are structurally validated against this same
|
||||
closed vocabulary, with separator/continuationSeparator/continuationNotice
|
||||
permitted only there, never a readable locator story. Each reserved ID/type
|
||||
must be internally consistent; duplicate IDs within a part refuse. A separator
|
||||
leaf in a normal note/body/comment refuses. A valid separator in a reserved
|
||||
note does not make readable footnotes/endnotes unsupported.
|
||||
|
||||
The table is exhaustive for story/run leaves; unknown leaves refuse, including
|
||||
nontext leaves not explicitly named. Formatting properties belong only to
|
||||
the separately closed manifest list. Anchors/range marks under invisible
|
||||
revision ancestors are omitted in that view but still structurally validated.
|
||||
Comment author data and ACL-like Word permission markers never supply Mosaic
|
||||
authority. Unknown extension/AlternateContent text is unsupported, not ignored.
|
||||
|
||||
Walk direct story paragraphs and table cells in XML order, including nested
|
||||
tables in their containing cell order. Paragraph ordinals do not change with
|
||||
view. Concatenate visible text across adjacent runs with no invented spaces.
|
||||
Preserve decoded Unicode as stored: no NFC, case folding or whitespace
|
||||
collapse. xml:space text remains
|
||||
literal. Offsets count Unicode scalar values, not UTF-16 units or graphemes;
|
||||
unpaired surrogates/invalid XML characters refuse. Field instructions,
|
||||
hidden/vanished text and text boxes are not silently omitted: their presence
|
||||
in a requested story makes v1 projection unsupported. Field results and
|
||||
unknown semantic text-bearing elements likewise refuse until specified.
|
||||
The projection traverses only these containers in the w namespace:
|
||||
body, footnote, endnote, comment, tbl, tr, tc, p, r, ins, del, moveFrom,
|
||||
moveTo, smartTag and sdtContent. A document root wraps body; note/comment
|
||||
part roots wrap their corresponding stories. sdt may contain sdtPr (ignored
|
||||
properties) and sdtContent only. Hyperlink containers are unsupported even
|
||||
without a relationship. Unknown text-bearing containers refuse. Nontext
|
||||
subtrees pPr, rPr, tblPr, tblGrid, trPr, tcPr and sdtPr may be ignored only
|
||||
if they contain no story text elements, field codes, external references,
|
||||
objects or unknown namespaces. Structural-leaf behavior is defined only by
|
||||
the closed table above. w:sectPr is layout-only, with relationship targets
|
||||
validated normally.
|
||||
Formatting-property descendants are a closed W4b release artifact: its full
|
||||
expanded-name list is included in the extractor manifest and independently
|
||||
reviewed before enablement; any name absent from that list refuses. This
|
||||
artifact can narrow the allowed property subtrees, never add a text-bearing
|
||||
container to this v1 contract. Missing artifact is no readiness, not a
|
||||
permissive descendant-text scraper.
|
||||
|
||||
Reference marks contribute anchors at the current text boundary, not invented
|
||||
note numbers or inline comment bodies. Each note/comment is separately paged.
|
||||
A single range cannot straddle a view, paragraph or story; the selection wrapper
|
||||
may cover contiguous paragraphs only under section 3. Extract literal
|
||||
`[[target]]`, `[[target|label]]`, `[[target#heading]]` and `![[target]]`
|
||||
after concatenating visible runs within one paragraph, so split-run tokens
|
||||
survive formatting changes. Preserve complete literal bytes as UTF-8 after
|
||||
XML decoding and code-point start/end; never follow OS paths or external URLs.
|
||||
Targets resolve only via the host's owned-document resolver, with independent
|
||||
authorization; unresolved targets stay literal and marked unresolved in human
|
||||
UI. No link parsing grants reads. Nested/unclosed bracket sequences remain
|
||||
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. 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})`:
|
||||
project, document, version and part are required; only textView, cursor and
|
||||
limit may be omitted. version is exactly `{mode:"latest"}` or
|
||||
`{mode:"commit",commit}`; part is
|
||||
one class/name/story triple above; textView defaults final; cursor is null
|
||||
on first page, limit 1..100 (default 20). No path, blob or draft argument.
|
||||
- `editor_resolve_citation({locator})`: verify the exact immutable range;
|
||||
it does not search for a nearby quote. Return exact quote and locator plus
|
||||
`currentCommit` and `stale` after current authorization.
|
||||
- `editor_flag` is W5's metadata-only write; W5 must validate the same
|
||||
locator before storing a flag and may not write into the document.
|
||||
|
||||
Read response is exactly `{version:1, business,project,document,commit,blob,
|
||||
extractor,textView,part,rows,nextCursor,currentCommit,stale}`. Each row has the
|
||||
extraction record above. The public envelope contains no absolute paths or
|
||||
raw package attributes. `nextCursor` is null at end; `currentCommit` is the
|
||||
current published document commit; stale is exactly commit != currentCommit.
|
||||
A resolver response is exactly `{version:1,locator,currentCommit,stale}`:
|
||||
the verified quote is the locator's quote, with no separate unverified text.
|
||||
There is no default "first part" or automatic descent into notes/comments. The broker-bound business must equal
|
||||
locator.business; a mismatch is editor-access-refused before object lookup.
|
||||
Markup additionally requires `revisionSpans` on each
|
||||
row: array of `{kind,id,start,end}`, kind insert/delete/move-from/move-to/
|
||||
paragraph-mark-insert/paragraph-mark-delete (mark spans have start=end),
|
||||
with null-free canonical decimal IDs and valid boundaries; other views omit
|
||||
that key. Limits cap output at 64 KiB UTF-8 JSON per response, including envelope and cursor. End a page before the first complete
|
||||
row that would overflow, and return a cursor for that row. This is normal
|
||||
paging, not partial-row success. If that first row cannot fit even on an
|
||||
otherwise empty page, return editor-range-too-large with no text. Such a
|
||||
paragraph is unsupported for agent reading in v1; no subrange read exists.
|
||||
A human-visible "paragraph exceeds agent reading limit" reason appears only
|
||||
after authorization. The human editor/save is unaffected. All empty paragraphs
|
||||
still produce rows and advance the cursor. No page can return the same cursor
|
||||
without progress.
|
||||
|
||||
Cursor is a host-authenticated opaque token binding principal, session,
|
||||
project/document, commit/blob, extractor, view, part, next ordinal, the complete
|
||||
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, 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
|
||||
blob and commit membership, not digest alone. Any mismatch refuses
|
||||
`editor-citation-invalid` without guessed text. After newer publication the
|
||||
old valid locator returns `stale:true` with old text; it never auto-relocates
|
||||
to identical paragraphs or another note. Jump opens that committed view with
|
||||
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 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 (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,
|
||||
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.
|
||||
|
||||
|
||||
### 6.1 Case 2 query and citation adapters
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## 7. Existing Case 2 authority, remote durability and restore
|
||||
|
||||
### 7.1 Access and supporting writes (reopened M1)
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
The cursor authority revision is the server's current project grant, universe/mapping/scope
|
||||
revision, the two human review-settings revisions and format-publication generation for
|
||||
the bound caller/session. It contains no
|
||||
sharing human or writing_access_events/writing_shares sequence. Check the review settings before every part/view/citation/search/index/context attachment,
|
||||
not only on first open. No request boolean can enable them. 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.
|
||||
|
||||
### 7.2 Selection convenience and ordinary messages
|
||||
|
||||
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.
|
||||
|
||||
### 7.3 Host-only off-host remote (replaces the ban)
|
||||
|
||||
`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.
|
||||
Until #431 corrects the real seat helper's shared jason.woltje credential route, the remote
|
||||
must be on a host/account that principal and all seat credentials cannot reach; private
|
||||
visibility alone proves nothing. Prefer a separate off-host instance. An existing-instance
|
||||
owner/org qualifies only after denial through the actual helper credential path proves no
|
||||
jason.woltje access. W3b tests that real helper route and seat identities against an authorized
|
||||
empty fixture remote, without printing/logging credential values; no dummy-token substitute.
|
||||
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. Allow host pushes only to refs/heads/writing-published and
|
||||
refs/heads/import-staging/<operation-id>. A refused candidate retains a private non-reader
|
||||
staging ref and journal status; after publication the staging ref stays as an audit link.
|
||||
No automatic deletion or force-update of staging refs. No silent fallback or force push.
|
||||
|
||||
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.
|
||||
|
||||
### 7.4 Conversion events, rollback --restore and irreversible recovery
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
These are required future fixture gates, not implementation results.
|
||||
|
||||
| ID | Evidence required | Negative control / bypass |
|
||||
| --- | --- | --- |
|
||||
| A01 | Exact body quote independently recomputed from commit/blob/revision | change quote, digest, blob, commit or extractor; each refuses |
|
||||
| A02 | Two identical paragraphs and notes have different locators | no content-search relocation; swapped ordinal/story refuses |
|
||||
| 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; review settings off by default | final read succeeds; original/markup or comment request/resolve refuses until matching human setting, both needed for original comment; 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 | 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; actual seat helper credential denied, not just a dummy 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 | 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/helper-readable/unexpected remote refuses opening; real helper denial tested; 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 | 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 and missing-folder refusal | all constructs/wiki/front matter preserved; no agent conversion; new DOCX has no Markdown precursor |
|
||||
|
||||
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. Reopened review and handoff
|
||||
|
||||
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.
|
||||
Reference in new issue
Block a user