Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
6.0 KiB
Filbert review, row 129 round 1: changes
Candidate manifest cfbadbd49902f5f3740392fec9218279adc2a661cfb28341fba02790f327232b (15 paths), base 70504d23a. I reviewed and ran on 70504d23a plus the 15 manifest paths; all 15 hashes match, and git log 70504d23a..806ab89df on the 15 paths is empty. The packages/webui/src/public/ diff (bus.js, chat.css, chat.js, index.html) needs Mos's decision 123 go on this candidate before landing.
Brief: docs/plans/2026-10-14_prd-1.2-build.md:552-567, "The WebUI chat area".
(a) Edits to existing WebUI tests (sage-0747)
Each count increase also names the chat item:
packages/webui/tests/browser.test.mjs:21-22: scripts 4 to 5, andscript[src="/chat.js"]is counted exactly once.packages/webui/tests/shell.test.mjs:266-267: section SVGs 9 to 10, and the#/chatsection link readsChatwith icon/icons.svg#i-inbox.packages/webui/tests/shell.test.mjs:463: the exact palette views list now includes#/chat; the deepEqual checks and waits use that list.packages/webui/tests/views.test.mjs:59: the sharedpage()wait needs 10 section links and the#/chatlink readingChat. Two tests use this helper, which is why BUILD lists it twice.
No other assertion was weakened. Chat reuses the inbox icon, as BUILD says.
(b) Mutant 16, read-array
mutants-first.txt:16 records 16-read-array SURVIVED. The cause is the one BUILD gives. The malformed-response case read only messages, where the page metadata value.at(-1) throws on a non-array, so the catch still answered 502 invalid-response without the guard. packages/webui/tests/chat.test.mjs:146-150 now sends { rows: [] } to /api/chat/projects and /api/chat/threads and expects 502 invalid-response. Without the guard at chat-http.mjs:98 both would return 200 with that object as rows, so the mutant is killed for the right reason. The source is unchanged; only the test was added.
Brief acceptance
- List, create, send and the per-thread view: chat.test.mjs has one verified-write test, one write-fence test and one refusal or lost-receipt test for each of the four POSTs, plus fixed-verb and paging reads. chat-browser.test.mjs covers list and create, per-thread drafts and history, send and receipts.
- A thread the user doesn't own: the real-broker test (
chat.test.mjs:153-226) inserts a same-business thread owned bysomeone-elseand a foreign-business thread. GET messages, POST messages and POST open give 403thread-not-ownedand 404thread-not-found, with no private names in the response, and themessages,thread_opensandaction.allowedcounts are unchanged. - Mutants for each: Rocko's 64 (BUILD, final table) include mutants for each of these.
Checked and correct
chat-http.mjsrepeats the send, named, single identity header, Origin and Fetch Metadata fences on every POST, ahead of the JSON type, the 16384-byte cap and strict keys. Methods other than GET and POST get 405. Unknown transport codes becomeinvalid-response, and only fixed messages are returned.chat.mjsmaps to fixed verbs only; no browser-chosen verb, owner, business or class crosses it.chat.jsrenders every label and body throughesc(inert(...)), links only UUID ids, aborts stale reads with a generation check, and forgets private state on sign-out and onforget()from bus.js.- The bus.js diff only adds the section, the palette entry, the
MosaicChat.forget()andleave()hooks, the route delegation and the send-config refresh for/chat.
Changes requested (tests only; the source is correct)
My own mutants left four shipped guards that no test pins. The brief asks for tests and mutants for create and send, so each of these is a change. Each fix is a test addition; no source change is needed.
- chat.js send target. Changing the send POST in
packages/webui/src/public/chat.js:232fromthreads/${id}/messagestothreads/${id}/opensurviveschat-browser.test.mjs. The fetch stub recordspathfor each write, but the tests assert onlybody. Assert the path of each write too, for create project, create thread, send and Resume. - createThread receipt instance check. Replacing the
instancecheck atpackages/webui/src/chat-http.mjs:105withfalsesurviveschat.test.mjs. The malformed-receipt cases use only{}, which fails theidcheck first. Add createThread receipts{ id }with noinstanceand one with an instance that failsKEY. Both should give 503outcome-unknownwithsent: 'unknown'. - Receipt fields. Replacing
chat-http.mjs:111withconst receipt = { ...value };survives. The comment above that line says only the operation's receipt fields are exposed, but each test answer is exactly the receipt. Give one answer an extra field (for exampleownerorcapability) and assert the response doesn't carry it. - Bidi controls. Dropping
\u202a-\u202e\u2066-\u2069from theinertclass atchat.js:6surviveschat-browser.test.mjs.HOSTILEalready contains U+202E, but the test only checks the ESC escape. Assert that the rendered project label and message body contain no raw U+202E.
Ran by me
Slot from sage-0761, on 70504d23a plus the 15 manifest paths. Busy check CLEAR before and after, manifest checked before and after, TMPDIR in my own scratch, DOCKER_HOST a dead socket.
- Singles, 16:42:28Z to 16:43:03Z: chat.test 20/20, chat-browser.test 11/11, browser.test 1/1, shell.test 5/5, views.test 3/3. Total 40/40, 0 skipped.
- Mutants, 16:43:03Z to 16:44:02Z: 6 of my own, none of them in Rocko's 64. The controls for chat.test and chat-browser.test pass first. Killed: the repo
KEYcheck (chat.test, "chat validates names, body, project and strict empty open payload") and the GET/POST method guard (chat.test, "chat assets, GET purity..."). The four that survived are listed above.
Not mine
Rocko's receipts (agents/rocko/work/queue-129/r1/): final gate 16:24:07Z, WebUI 177, bus threads 14, CLI thread parity 11, total 202; 64 of 64 mutants killed after the read-array test change; chat-final-shape.log 20/20; named-browser, named-shell and named-views logs 1/1, 5/5 and 3/3.