One cumulative control-board, webui and seat state. The four rows edit the
same files (scan.mjs, page.html, README.md, app.js), so they land together,
each on its own receipt:
- Row 18, Discord connector rows on the board (#1509): R3 approved by
Darkwing and Dewey, Gitea comment 26257, manifest 254403b8. Jason
accepted the visual test.
- Row 22, board attention status (#1503): Filbert approved R1, comment
26248, manifest e40b58ec; restart receipt 26249.
- #1511, task attribution (row 6 code phase): R2 approved by Filbert and
Dewey, manifest d4c96395. docs/TOOLS.md carries the approved --by usage
line (tools-usage.patch 86bcba3c).
- #1512, relaunch activity (row 6 pilot): R1 approved by Darkwing and
Dewey, candidate manifest 47769fad. All seven source files match it.
Row 16, internal development bootstrap (#1510): the seven files outside
shared records match Filbert's R1 pins, receipt 26204 (agents/researcher/*,
scripts/test-darkwing-launch.mjs, the bootstrap plan).
packages/webui/src/public/app.js is committed at its #1512 R1 pin ce7d79a4.
The working copy holds Dewey's unreviewed return-flow candidate on top of
that, and it stays uncommitted.
Also: the four row briefs and Darkwing's evidence records under
agents/darkwing/work, including the 2026-09-26 tree manifest and the #1512
re-run against 21e3e908. Serial acceptance command: 397/397, three runs.
The failures that only show when tests run concurrently are in #1509 engine
tests, and they reproduce on clean HEAD.
Suites on the exact staged tree: config 24, task 90, foundation 43,
conductor 17, release 14, auth 15, discord 63; package union 397/397
(serial); test-darkwing-launch 5/5.
Shared records (BUILD-LOG, QUEUE, CURRENT, DEFERRED, SESSIONS, AGENTS.md,
agents/README.md) follow in Sage's records commit.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
96 lines
5.3 KiB
Markdown
96 lines
5.3 KiB
Markdown
# #1512 R1 candidate re-run against HEAD, 2026-09-26
|
|
|
|
Requested by Sage over T3 on 2026-09-26. Integration was held because of the
|
|
row 21 engine test race, and `1685deb4` fixed that race. This record is new
|
|
evidence. The R1 files next to it are unchanged.
|
|
|
|
## Snapshot
|
|
|
|
- `/tmp/relaunch-activity-r1-rerun-oupRiqIC`: `git archive 21e3e908`, plus the
|
|
working `packages/control-board`, `packages/webui` and `packages/seat`
|
|
(node_modules excluded), plus a symlink to the root `node_modules`.
|
|
- `CANDIDATE.sha256` in the snapshot hashes to `47769fad…`, which is the R1
|
|
candidate manifest. All 7 candidate pins match.
|
|
- 71 of the 89 R1 dependency pins are unchanged. The other 18 are
|
|
`packages/discord/**` and `scripts/test-discord.sh`, and they equal HEAD.
|
|
`engine-pi.mjs`, `engine.test.mjs`, `fake-pi.mjs` and `helpers.mjs` in the
|
|
snapshot are byte-identical to HEAD.
|
|
- Node v26.8.1. Test union: control-board, webui, seat, mosaic, ledger and
|
|
discord tests. The count rose from 351 at R1 to 397 because rows 23 to 25
|
|
added Discord tests.
|
|
|
|
## Results
|
|
|
|
| Run | Flags | Result | Log (`/tmp/`) | sha256 prefix |
|
|
|---|---|---|---|---|
|
|
| A1 | `--test-concurrency=1 --test-timeout=15000` (R1 form) | 397/397, rc 0, 19.9 s | darkwing-1512-rerun-A1-bounded.txt | 8b34a64a660d5948 |
|
|
| A2 | same | 397/397, rc 0, 19.7 s | darkwing-1512-rerun-A2-bounded.txt | 5c8b96209f5b8b2c |
|
|
| A3 | same | 397/397, rc 0, 19.4 s | darkwing-1512-rerun-A3-bounded.txt | e9829f454bf2b63f |
|
|
| B1 | `--test-concurrency=1` | 397/397, rc 0, 19.0 s | darkwing-1512-rerun-B1-serial-notimeout.txt | bb6eaedf6250c410 |
|
|
| C1 | default concurrency | 395/397, rc 1, hung until I ended a leaked child | darkwing-1512-rerun-C1-default-concurrency.txt | 5200188e1bcd8b15 |
|
|
| C2 | default concurrency | 395/397, rc 1, hung until I ended a leaked child | darkwing-1512-rerun-C2-default-concurrency.txt | 1f244a4835000e31 |
|
|
|
|
In C1 and C2, the same two tests failed, both in `packages/discord/tests/engine.test.mjs`:
|
|
|
|
- Test 205 (line 100), "a prompt while streaming is held…": ENOENT on
|
|
`commands.jsonl`.
|
|
- Test 208 (line 146), "tool events from a run that outlived its timeout…":
|
|
`engine refused prompt: agent is streaming; specify streamingBehavior`.
|
|
|
|
Both runs stopped making progress after every test had finished and the
|
|
`after()` hook had removed the temp root. The only thing left was a `fake-pi.mjs`
|
|
child. I sent that child SIGTERM (C1 pid 3636242, C2 pid 3668771). The file
|
|
then exited and the runner printed its summary. Apart from that, I didn't
|
|
touch either run.
|
|
|
|
## Control: clean HEAD, no #1512 files
|
|
|
|
Snapshot `/tmp/darkwing-head-21e3e908-zinKkQ` (`git archive 21e3e908` only).
|
|
Same union, default concurrency:
|
|
|
|
| Run | Result | Log (`/tmp/`) | sha256 prefix |
|
|
|---|---|---|---|
|
|
| 1 | rc 124 at the 240 s cap, 178 ok, interrupted in seat and webui files | darkwing-head-default-1.txt | 799acad299d0b20e |
|
|
| 2 | rc 124 at the 240 s cap, same shape | darkwing-head-default-2.txt | e9028b28c02ffc86 |
|
|
| 3 | 369/370, rc 1, test 187 = the line 146 engine failure | darkwing-head-default-3.txt | fcd85bd474f2c210 |
|
|
| discord only | 162/162, rc 0 | darkwing-head-discord-only.txt | 5f068557caee7fc7 |
|
|
| seat + webui only | 21/21, rc 0 | darkwing-head-seat-webui.txt | 9952b57707577a92 |
|
|
|
|
`engine.test.mjs` alone in the candidate snapshot passed 5 of 5 times, 11/11
|
|
each run (`darkwing-engine-alone-{1..5}.txt`).
|
|
|
|
Dewey was running `packages/webui/tests/` from the canonical checkout during
|
|
part of this window. That added load. It doesn't explain the HEAD control, and
|
|
the two engine failures reproduce without it.
|
|
|
|
## Reading
|
|
|
|
The #1512 candidate passes its R1 acceptance command 3 of 3 times at 397/397,
|
|
and it passes the serial run with no timeout. Every default-concurrency failure
|
|
is in committed `#1509` Discord engine code, and clean HEAD fails the same way.
|
|
I found nothing that implicates the seven candidate files.
|
|
|
|
Two engine defects are exposed under load. They belong to `#1509`, not to #1512:
|
|
|
|
1. **Test race plus leak, `engine.test.mjs:100`.** The test reads the fake's
|
|
command log 20 ms after the second prompt. Under load the fake hasn't written
|
|
the file yet, so the read fails with ENOENT. The test has no `try/finally`,
|
|
so `engine.stop()` never runs, the fake-pi child stays alive, and the test
|
|
file never exits. That is the hang. The fix is the pattern `1685deb4`
|
|
already uses elsewhere: wait with `until()` and stop in `finally`. Six other
|
|
tests in the file also stop without `finally`.
|
|
2. **Engine race, `engine-pi.mjs`, seen through `engine.test.mjs:146`.**
|
|
`busy` is `state.busy || pending.some((t) => !t.done)`. Suppose a turn times
|
|
out before the engine has read pi's `agent_start`. `failTurn` marks it done,
|
|
`state.busy` is still false, and `busy` reads false. The next prompt then goes
|
|
straight to pi, and pi refuses it because it's still streaming. This fails
|
|
closed: the prompt errors and nothing is misattributed. Production timeouts
|
|
are long, so this should be rare there. It's still a real race. One option is
|
|
to count a sent turn toward `busy` until pi's own end or settle event arrives,
|
|
not only until the client gives up on it.
|
|
|
|
Rocko's finding C, a follow-up sent after a timeout, looks superseded. Since
|
|
`1685deb4`, the engine never sends a follow-up (held prompts), and the line 100
|
|
test asserts that `streamingBehavior` is absent. Defect 2 is the timeout race
|
|
that remains.
|