8.3 KiB
Row 53, console tokens and shell restyle, round 3 review (Darkwing)
Issue #1542, request comment 27168, packet comment 27169, queue revs
367-369. Base ea080fd8. Candidate manifest sha256
2562c05d4a92f90096c0fe68ef8c2adfa7244fa547f3390155f5bee5cce64cba, the
same 16 files under packages/webui. The packet manifest and my snapshot
of the checkout both check 16 OK. round3.patch applied to my round 2
snapshot gives the round 3 files byte for byte, so the delta is README,
app.js and shell.test.mjs and nothing else (r3/out/r2-to-r3.diff).
Verdict: approve. Both of my round 2 items are fixed, and the tests pin them. Every suite is green, all 14 new mutants die, and my probes on the real control-board show nothing from before a refusal. I have three notes, none blocking. The worst is a stale session picker that this row didn't introduce.
Method
- Detached worktrees at
ea080fd8,cand,mutwtandpwt, each with the 16 candidate files staged and checking 16 OK.mutwtstill checks 16 OK after the mutant runs (r3/mut/manifest-after.txt). r3/gate.sh: thepackages/webuisuite,build-tokens.mjs --check, then everyscripts/test-*.shwithDOCKER_HOST=unix:///nonexistent.sock, 19:23:02Z to 19:26:06Z.- 14 mutants aimed at the round 3 code (
r3/mut/mutate.py,r3/mut/run.sh), each against the full webui suite, 19:26:06Z to 19:38:50Z. test-releasewith Docker, finished 19:39:38Z.- Probes in Chromium through the candidate's
tests/browser.mjs(r3/probes/probe3.test.mjs, outputr3/probes/probes-cand.txt). Test one is round 2's fake board and bus set (P1 to P9). Test two runs the real control-board fromtests/history-fixture.mjsbehind a proxy that can answer 403, fail the catalogue with a 500, or hold history pages (P10, P11, P13). Test three is a board whose first read is a 500 (P12). No tracker request. - Read the three changed files against my round 2 required list and Filbert's C4 (comment 27163).
Node v26.8.1, TMPDIR=~/darkwing-scratch/r53c/tmp.
Suites
| Suite | Result |
|---|---|
| packages/webui (node) | 27/0 |
| build-tokens --check | rc 0, "tokens.css is current" |
| test-auth | 15/0 |
| test-conductor | 17/0 |
| test-config | 24/0 |
| test-discord | 66/0 |
| test-extension-package | 18/0 |
| test-foundation | 44/0 |
| test-queue | 27/0 |
| test-release | 4/0 without Docker, 14/0 with it |
| test-task, Docker unreachable | 26/0 |
As before, I didn't run test-task with real Docker because it makes live model calls.
Round 2 items
| Item | Result |
|---|---|
| Required 1, P9 and Filbert's C4 | Fixed. With no scan held, error() empties #sessions, #waiting and #seen, puts "–" in the three counts, and says "the read failed" in the tree, the footer and #status. P9 (403 then 500) and P12 (first read 500) both show an empty board. The test runs a 403, then a 503, and asserts no rows, no cards, no History buttons and the dashes |
| Required 2, P10 | Fixed. A 403 with a conversation open empties #conv-log and calls closeConversation(). P10 on the real control-board: #conversation hidden, no has-conversation, #conv-log empty, the form hidden |
| README wording | Fixed. The refusal line now names the cards, the project filter, the empty board after a failed read and the closed conversation. Each claim matches what the probes show |
| M30 (counts kept on refusal) | Now tested. R09 below drops the dashes and dies on #waiting-count |
Dewey's test doesn't run a 500, only a 503. Both go through the same non-403 branch, and my P9 and P12 run the 500. That's enough.
Probes
Fixtures as in round 2. P10, P11 and P13 use the control-board fixture's session, whose history holds "Secret question from before the refusal" and "Secret answer from before the refusal".
| Probe | Candidate |
|---|---|
| P1 board 403 with the inspector open | #board-view display:none, inspector hidden |
| P2 board 403 | tree, footer, #status and #fresh-board say not read |
| P3, P4, P4b bus refusal | the palette and section list show the four views only |
| P6, P7 | banner ref then banner err, no task rows |
| P8 the toast before any copy | 1×1, empty, in the tree |
| P9 good read, board 403, then a 500 | #board-view shown but empty, 0 rows, #waiting and #sessions empty, tree, footer, #status and #fresh-board say "the read failed". Was the refused rows. Fixed |
| P9b then a good read | 2 rows, footer "waiting 1 · working 1" |
| P10 History open, then every board request 403 | #conversation hidden, #conv-log empty, form hidden, #board-refused shown. Was the full history on screen. Fixed |
| P11 refusal, recovery, History again with the catalogue failing | #conv-pick shown with the earlier conversation's title. See note 1 |
| P12 first read 500, no scan ever | empty board, "the read failed" everywhere, banner "No board data loaded" |
| P13 a 403 while a history page is in flight, then the page answers | #conv-log stays empty, #conversation stays hidden. The convGen bump in closeConversation() drops the late page |
Mutants
14 of 14 killed (r3/mut/summary.txt). Every kill is an assertion or a
wait timeout in the shell browser test, not a load error.
| Mutant | Change | Killed at |
|---|---|---|
| R01 | no close block on a refusal | #conversation hidden, line 200 |
| R02 | close without clearing #conv-log |
#conv-log empty, line 202 |
| R03 | showConversation(false) instead of closeConversation() |
the keyboard focus wait, line 215 |
| R04 | if (!data) becomes if (refused) |
footer "the read failed", line 180 |
| R05 | no replaceChildren() loop |
no rows or cards, line 178 |
| R06 | the loop skips seen |
line 178 |
| R07 | the loop skips waiting |
line 178 |
| R08 | the loop skips sessions |
line 178 |
| R09 | no count dashes | #waiting-count, line 170 |
| R10 | footer always "refused" | line 180 |
| R11 | why always "refused" |
#status, line 182 |
| R12 | no inspect() in the no-data block |
inspector hidden, line 164 |
| R13 | a refusal keeps project |
"All projects" pressed after recovery, line 187 |
| R14 | a refusal keeps selected |
inspector hidden, line 164 |
R03 passes the conversation assertions, because they check only that the
panel is hidden and the log empty. It dies at the keyboard step because
conv stays set. The next Enter on a row runs closeConversation()
first (line 347), which moves focus to the old History button before
focusSnapshot(). Escape then returns focus to History, not to the row.
A direct check that the conversation is closed would catch it sooner, but
the kill is real.
Notes (not blocking)
- Stale session picker (P11), not from this row.
openConversation()clears the title, the meta line and the log, but replaces the#conv-pickoptions only after a good catalogue read. When the catalogue fails, the picker keeps the previous conversation's titles, shown under "History unavailable". That can be a conversation from before a refusal or from another seat. Choosing one doesn't open the wrong session: the next catalogue read doesn't find it under this row and falls back. Base03969219has the same code. The fix is one line,$('conv-pick').replaceChildren()next to theconv-metaclear. It fits in row 54 or a later shell row. - Focus after a refusal closes a conversation. In
error(),closeConversation()runs before the no-data block.restore()puts focus back on the History button, which is still in the DOM at that point. The next lines empty#sessions, the button goes, and focus falls to<body>(P10active: "BODY"). The$('main').focus()fallback incloseConversation()has already run by then. A keyboard user ends up at the top of the document after a refusal. Repeating the fallback at the end oferror()fixes it. - Round 2's note 2 (the hidden inspector keeps its text in the DOM) and Filbert's N4 to N7 still stand. M07 stays accepted. Round 2's note 3, the refresh timer race, is now in row 54 with Dewey's test, and I'll check it there.
Files
r3/candidate-manifest.sha256: copy of Dewey's.r3/gate.sh,r3/out/: suite runs,summary.txt,test-release-docker.txtandr2-to-r3.diff.r3/mut/: mutant definitions, runner, diffs, outputs,summary.txtand the manifest check after the runs.r3/probes/: the probe test and its output.