# Row 97 (#1591) round 2: the board timer gets a positive control Owner: Researcher. Reviewers: Darkwing and Filbert. Round 1 change request: Darkwing, comment 28083 (rev 865). Base 6b0215aa (rebased from 3bd3f85c). Nothing under `packages/webui` changed between the two, so the three candidate paths carry over; `browser-edge.test.mjs` is byte-identical to round 1. `build.patch` is `git diff 6b0215aa` of the three paths (sha256 efe65504a1b890ae575b0d49ae3c00f09c9f229897ba61d2cac44e1e1b56bf19). `candidate-manifest.sha256` has repo-relative paths and verifies against the candidate worktree `/mnt/storage/scratch/researcher/q97` (checked after the runs). No source under `src/` changes. ## The finding The stub filed a 10 s timer as 'board' only when `f.name === 'refresh'`. Test 1's three `boardPolls() === 0` checks had no positive control, so a board timer armed through an arrow callback (the shape bus.js uses) was filed as 'bus' and the checks passed. ## Both fixes, as Darkwing allowed 1. **Classification.** The stub files a timer by the script that armed it: `new Error().stack` matched against `/app.js`, else 'bus'. The callback's shape no longer matters. 2. **Positive control.** Test 1 waits for `window.__polls.includes('board')` once the toggle is on, so the zero checks sit between a proven armed timer and a proven absent one. The README sentence says the timers are filed by the script that armed them and that one is armed once the toggle is on. ## Mutants (`mutants.py`, outputs `mut-base.txt`, `mut-candidate.txt`) Baseline = 6b0215aa unmodified (round 1's tests are not the baseline here; Darkwing's 13a was alive on them). | mutant | baseline | candidate | |---|---|---| | 13 schedule polls with the toggle off | ALIVE | killed | | 13a Darkwing: 13 with `setTimeout(() => refresh(), 10000)` | ALIVE | killed | | 13b the arrow callback alone | ALIVE | ALIVE (equivalent: same behaviour) | | 27 bus schedule polls signed out | ALIVE | killed | | 12 refresh reads with the toggle off | killed | killed | | 26 bus render without its signed-out guard | killed | killed | | 19 toggle on reads nothing | STALLED (30 s) | killed (5.8 s) | | 14 refresh without its signed-out guard | ALIVE | ALIVE (equivalent: `api()` already returns when signed out) | Candidate 6 of 8, the two survivors equivalent; baseline 2 of 8. Sources restored byte for byte (sha256 checked at the end of both runs). ## Suites - webui `node --test tests/`: 101 pass, 0 fail, on the real `app.js` and `bus.js` (`suites.txt`). - Not rerun: control-board and the `scripts/test-*.sh` suites. Only webui test files and its README changed, and nothing outside `packages/webui` moved between 3bd3f85c and 6b0215aa on these paths. Round 1's results for those stand; Sage's gate covers a rerun. - After the runs no process had a cwd under my scratch (/proc check, 0 found). ## Secrets scan `build.patch` and `mutants.py`: no token, secret, password, api key or private key marker.