plans: Q168 brief, a WYSIWYG Console editor built from reviewable source (#1648)

Jason's ruling Q168 via Mos: one more library search against the row 148
bar, then an open-source WYSIWYG built from source in the repo if nothing
passes. Mos's decision 123 go on the license and candidate comes before
any code is imported.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-16 13:38:17 -05:00
co-authored by Claude Opus 5.5
parent 54aac2bd05
commit fcea7d015c
@@ -0,0 +1,110 @@
# Q168: a WYSIWYG Console editor
Status: written by Sage, lead, on Mos's directive for Jason's ruling Q168
(DECISIONS in the brain repo). It follows `docs/plans/BRIEF-TEMPLATE.md`,
one `##` heading per row.
Jason's ruling, verbatim: "If a suitable library cannot be found, we
should find an open source WYSIWYG and rewrite for our use. Ideally, we
would use a library to reduce coding overhead, but I'm willing to accept
the burden to get a functional editor."
## A WYSIWYG Console editor built from reviewable source
### Problem
Row 148 ships the Console's spec and docs editor as a Markdown textarea
with a preview built from repository code (sage-0506). That is the
interim. Jason wants a WYSIWYG editor (Q168). The row 148 library search
found no library that passed its bar: Toast UI Editor 3.2.2 bundled
DOMPurify 2.3.3, open to GHSA-gx9m-whjm-85jf, and its 534,289 B bundle
can't be rebuilt from its tag
(`agents/researcher/work/queue-148/LIBRARY.md`). Q167 D3 bans
unreviewable prebuilt bundles.
### Owner and reviewer
- Owner: Researcher.
- Reviewers: Dewey, for security until row 149's security-reviewer role
exists, and Filbert.
### Files owned
- `agents/researcher/work/queue-<row>/`: the search notes, the candidate
report and the build notes.
- After Mos's decision 123 go only: one new directory for the imported
editor source, named in the candidate report, with its license file
and a provenance file recording the origin repository, the pinned
commit and every local change.
- `packages/webui/src/public/`: the editor view, replacing row 148's
textarea view behind the same read and save routes.
- `packages/webui/package.json` and the build step, if the source needs
one, with every dependency pinned exactly.
- Tests in the webui package, the webui browser tests, READMEs and
`docs/TOOLS.md`.
The read and save routes, the bus verbs, the human writer and the
stale-base refusal stay as row 148 built them. If the editor needs a
change there, the row stops and tells Sage.
### What ships
1. One more library search against row 148's bar: a permissive license,
`script-src 'self'` with no eval and no `new Function` that can run,
nothing loaded at runtime, no CSP change, a current sanitizer, and a
bundle that rebuilds from its tagged source. Write the result in
`agents/researcher/work/queue-<row>/LIBRARY.md`: each candidate, its
version and license, and the reason it passes or fails.
2. If a library passes, it is the candidate. If none passes, pick an
open-source WYSIWYG editor with a license compatible with this
repository and plan to build it from source here. The candidate
report names:
- the project, the origin repository and the commit to pin;
- the license, with its text;
- the sanitizer it will use, its version, and the check that the
version has no open advisory;
- the source size in files and lines, and what gets removed or
rewritten so a reviewer can read all of it;
- how it builds, from which pinned tools, and how a reviewer
reproduces the build byte for byte.
3. Stop. Send the license and the candidate report to Sage, who sends
them to Mos for the decision 123 go. No editor code enters the
repository before that go.
4. After the go, import and build as the report says. From then on the
repository owns the code: it is maintained here and never updated by
replacing it with a new upstream drop. A later upstream fix comes in
as a reviewed change.
5. The editor reads and saves Markdown. A save writes Markdown through
row 148's save route, so the commit holds Markdown, not HTML. A file
opened and saved with no edits saves the same bytes, or the report
says exactly which normalisation happens and the reviewers accept it.
6. Rendering keeps row 148's rules: no raw HTML runs, links render only
for `http:`, `https:` or relative targets with
`rel="noopener noreferrer"`, and images are not loaded.
7. Tests:
- the browser test from row 148, with a `<script>`, an `onerror`
attribute and a `javascript:` link in the Markdown, runs nothing in
the WYSIWYG view;
- a test that the editor works under the Console's current CSP;
- a round-trip test over `spec/north-star.md` and a doc with every
element row 148's preview supports;
- a test that fails if the imported source's tree hash differs from
the one in the provenance file plus the recorded local changes;
- row 148's save tests still pass unchanged.
### Out of scope
Any CSP change: if the editor needs one, the row stops and tells Sage.
Vendoring any prebuilt or minified bundle, which Q167 D3 bans. Collaborative
or multi-user editing. Editing requirements or decisions. Changes to the
save route, the bus verbs or the human writer.
### Gate
- Before any code is imported: Mos's decision 123 go on the license and
the candidate report.
- At the end: Dewey and Filbert approve on the row's issue naming the
candidate manifest; Mos's decision 123 go on the `public/` diff and the
imported source; the webui, bus, cli and project suites and every
`scripts/test-*.sh` green.
- Needs row 148 done.