plans: re-pin rows 135, 137, 139, 143, 148 and 149 for PRD 1.5 round 3 (Filbert 28765, Dewey 0503); row 148 drops Toast UI for a textarea and preview

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-16 13:03:52 -05:00
co-authored by Claude Opus 5.5
parent c74511fe90
commit 1d0386dd08
+73 -22
View File
@@ -37,7 +37,9 @@ Row 148.
Jason wants to read and change a project's north-star spec and docs
without an agent, in a WYSIWYG markdown editor, with git history. Row 147
gives each project a local git repository, but the only ways to change it
are an editor on the host and `git commit` by hand.
are an editor on the host and `git commit` by hand. No WYSIWYG library
passed the bar below, so this row ships a source editor with a preview,
and a WYSIWYG editor waits for a library that passes.
### Owner and reviewer
@@ -47,8 +49,7 @@ are an editor on the host and `git commit` by hand.
### Files owned
- `packages/webui/src/public/`: the editor view, and the vendored library
under `public/vendor/<library>-<version>/` with its LICENSE file
- `packages/webui/src/public/`: the editor view and the preview renderer
- `packages/webui/src/serve.mjs`: one read route and one save route
- `packages/webui/src/bus.mjs` and `packages/webui/src/reads.mjs`: the
calls to the human transport
@@ -61,16 +62,36 @@ are an editor on the host and `git commit` by hand.
### What ships
- Library choice first. Before any `public/` change, Researcher picks one
library and sends Sage its name, version, license, size in bytes and
the sha256 of each vendored file. Sage puts them in this section and
re-pins the row, and Mos gives the decision 123 go on them. The library
must run under `script-src 'self'` with no eval and no `new Function`,
load nothing at runtime, and need no CSP change. If no library meets
that, the editor is a textarea with a rendered preview, built from code
in the repository, and the brief says so.
- `vendor.sha256` in the vendor directory lists each vendored file. A test
checks the files against it, so a changed vendored file fails the suite.
- Library choice first, done. The bar was a permissive license,
`script-src 'self'` with no eval and no `new Function` that can run,
nothing loaded at runtime, and no CSP change. If no library met it, the
editor would be a textarea with a rendered preview built from code in
the repository.
- Library ruling (sage-0506): no library. Researcher's step 1 proposed
Toast UI Editor 3.2.2. Step 1b, in
`agents/researcher/work/queue-148/LIBRARY.md`, found its bundled
DOMPurify 2.3.3 open to GHSA-gx9m-whjm-85jf, a critical nesting mXSS
reachable with the options Toast passes, and found that the 534,289 B
bundle has no second source: the editor@3.2.2 tag has no dist, so it
can't be checked or rebuilt. The CSP stops scripts but not off-site
links, meta refresh after a bypass, style overlays or same-origin form
posts. Patching means splicing DOMPurify into a minified bundle nobody
can rebuild, for a library unmaintained since 2023-02. The editor is the
textarea with a rendered preview:
- A textarea edits the file's Markdown source, so a save writes what
the human typed, byte for byte.
- The preview renders headings, paragraphs, lists, block quotes, code
blocks, inline code, emphasis and links from code in this repository.
It builds nodes with `createElement` and `textContent` only, never
`innerHTML`, `outerHTML`, `insertAdjacentHTML` or
`document.write`, so it needs no sanitizer. Anything else, raw HTML
included, shows as source text.
- A link renders only for an `http:`, `https:` or relative target, with
`rel="noopener noreferrer"`, and the preview shows the target beside
the link text. An image renders as its alt text and URL and is never
loaded.
- Nothing is vendored, so `vendor.sha256` and the vendor routes drop
out. Decision 123 still covers the `public/` diff.
- Reading. The Console lists `spec/north-star.md` and the files under
`docs/` for a project, and opens one with its current commit. The read
goes through the human transport like the Console's other reads.
@@ -93,7 +114,10 @@ are an editor on the host and `git commit` by hand.
and writes nothing; a path outside the two allowed refuses; each
boundary check refuses as the Settings tests do; a browser test that a
`<script>`, an `onerror` attribute and a `javascript:` link in the
markdown run nothing; the vendor hash test.
markdown run nothing; a test that the preview module's source has no
`innerHTML`, `outerHTML`, `insertAdjacentHTML` or `document.write`;
a preview test that each allowed element renders and a link with any
other scheme renders as text.
### Out of scope
@@ -104,7 +128,7 @@ row stops and tells Sage.
### Gate
Filbert and Dewey approve on the row's issue naming the candidate manifest;
Mos's decision 123 go on the `public/` diff and the vendored files; the
Mos's decision 123 go on the `public/` diff; the
webui, bus, cli and project suites and every `scripts/test-*.sh` green.
Needs row 147 done.
@@ -141,9 +165,17 @@ agents are proactive, and no role contract says so.
what a verdict needs. If the bus requires message.send to deliver a
verdict, it gets that too, and BUILD.md says why. Its contract: review a
candidate for security only, and approve or block with the reason.
- merge-gate: holds only row 137's land op, with no other grant and no
write tools. Its contract: land an approved merge when the decision,
the verdicts and the gate all pass, and otherwise report the refusal.
- merge-gate: its one grant is git.merge.protected as a cross-role
action, which is what row 137's land op checks. Raising a decision needs
no grant. It has no write tools. Its contract: take a candidate the
reviewers approved, raise the merge decision with domain `technical`,
and land it once the decision is resolved, the verdicts approve and the
gate passes; otherwise report the refusal. merge-gate raises what it
lands because only the raising instance and thread can consume an
approval (PRD 1.5 REQ-DEC-5, REQ-ROLE-5).
- The organization that row 149's tests use allows cto to message
merge-gate, because row 133 refuses a raise whose route can't message
the raiser.
- Every role contract gets one line: within your grants, act on what you
see without waiting to be asked, and raise a decision or send a message
for anything outside them.
@@ -152,7 +184,10 @@ agents are proactive, and no role contract says so.
them to the mosaic-stack business is a live step after the re-pin, with
Mos's go. It is not part of the row.
- Tests: both role files load and validate; security-reviewer's tool list
has no write or shell tool; merge-gate's only grant is the land op; a
has no write or shell tool; merge-gate's only grant is
git.merge.protected cross-role; a merge-gate raise with domain
`technical` routes to `arbiters.technical` and is accepted; a business
whose arbiter is merge-gate is refused, or a test pins what happens; a
contract test that finds the proactive line in every `roles/*.md`.
### Out of scope
@@ -192,6 +227,10 @@ four workflow roles, or for agents reviewing Jason's spec changes.
quoting Jason's Q167 text and his added text. It is never edited in
place.
- `docs/acceptance/314.md`, the acceptance script Jason runs.
- `packages/tasks/requirements.json`,
`packages/tasks/tests/requirements.test.mjs` and
`packages/bus/tests/requirements.test.mjs`: the new requirement ids in
PRD order, the version and the counts, as earlier PRD versions did.
### What ships
@@ -277,6 +316,10 @@ survive a reseed.
the landed commit, and consumes the decision.
- The sandbox binds the op only for a role that holds a resolved merge
decision, the same way push and fetch are bound today.
- PRD 1.5 REQ-LAND-1: only a role granted git.merge.protected cross-role
lands, so the land op refuses a merge decision of class `gated`. Row 139
carries the refusal and its test. If row 139 has landed before 137
does, 137 carries them instead.
- `read.mjs` keeps its cli-resolved check. Row 139 relaxes it.
- Canonical `refactor` is never a target. land-work.sh keeps working for
Sage's landings.
@@ -400,9 +443,14 @@ Jason on 2026-10-15.
- The grant to set instance names (row 141). chief-of-staff gets it
within-role. Whichever of 139 and 141 lands second adds the grant, and
until then names are set only by the human through the CLI.
- Tests for each hard wait, for a spec-covered merge going to the arbiter,
for an uncited decision still going to the human, and for a stale spec
citation.
- PRD 1.5 REQ-LAND-1: the land op refuses a git.merge.protected decision
of class `gated`, which is any merge decision raised by a role without
the cross-role grant. Row 139 carries the refusal if row 137 has landed
when 139 is built; otherwise 137 carries it.
- Tests for each hard wait, for a cited merge raised by merge-gate going
to the arbiter, for an uncited decision still going to the human, for a
stale spec citation, and for the land refusal: a coder raises a cited
merge decision, the arbiter approves it, and the land refuses.
### Out of scope
@@ -496,6 +544,9 @@ from the assistant, mostly repeats.
goes to the assistant.
- The assistant tells Jason the result in its own words, and its contract
says to summarize chief's text and not repeat it.
- Only saves through row 148's verb send the notice. A commit Jason makes
with git outside the Console sends none; PRD 1.5 REQ-PROJ-4 says so, and
covering those commits is a later row.
- Tests: one notice per spec commit; no notice for an agent's record
commit; a BLOCK reaches the assistant; a contract text test.