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