Skip to content

Commit 447eee7

Browse files
claude[bot]claude
andauthored
fix(pm): stream dispatch-gates self-test verdicts, document detached run (#14520)
selfTest()'s t() collector now prints each case's ✓/✗ line the moment the case is decided, instead of buffering all cases into an array and printing them only after the last one in the tail loop. The tail is reduced to the failed/length summary, unchanged in wording and exit codes. On an agent container the battery cannot finish in the foreground (the container's ~10-minute cap SIGTERMs it), and a killed run used to leave zero diagnostic lines. Streaming means a killed run now leaves every case decided before the kill readable in the log. Both files' headers gain a "run this detached on an agent container" section with the exact command. The triage's "record it in package.json's script comment" instruction lands in check-dispatch-gates.mjs's header instead — package.json is JSON and holds no comments, and that file is what check:pm-dispatch-gates actually runs. Option 2 from the triage (share one derivation across the end-to-end cases) is deferred per the ruling — no case is merged, no spawn removed, no case's name, condition or order moved. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9acddde commit 447eee7

2 files changed

Lines changed: 62 additions & 3 deletions

File tree

scripts/pm/check-dispatch-gates.mjs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@
66
*
77
* node scripts/pm/check-dispatch-gates.mjs # runs the tool's --self-test
88
*
9+
* ## On an agent container, run this DETACHED (#14281)
10+
*
11+
* `package.json`'s `check:pm-dispatch-gates` script is exactly this file —
12+
* `node scripts/pm/check-dispatch-gates.mjs` — and JSON holds no comments, so
13+
* the instruction a script comment would carry lands here instead, in the
14+
* header of the file that script runs. The battery this file spawns re-runs
15+
* `dispatch-gates.mjs`'s own CLI as a child process many times (see the "Why
16+
* the self-test ONLY" section below), and on an agent container that makes a
17+
* full run longer than the container's foreground command cap, which SIGTERMs
18+
* a run past it — this file's `result.signal` branch further down reports
19+
* exactly that kill, but only once the process has already been cut off. Do
20+
* not run `pnpm check:pm-dispatch-gates` (or `dispatch-gates.mjs --self-test`
21+
* directly) in the foreground there. Detach it and poll the log instead:
22+
*
23+
* nohup pnpm check:pm-dispatch-gates > /tmp/pm-dispatch-gates.log 2>&1 &
24+
*
25+
* then tail the log file until it stops growing. `dispatch-gates.mjs`'s
26+
* `selfTest()` streams each case's `✓`/`✗` line as that case is decided, so a
27+
* run killed mid-battery — by this cap, or by anything else — leaves every
28+
* case decided before the kill in the log, readable as a partial result. The
29+
* measured runtime and case count are not repeated here — a reading belongs
30+
* to a named commit, not to a header (the convention the next section states
31+
* for this same file) — see #14281 for the reading that motivated this
32+
* section.
33+
*
934
* ## Why the gate exists
1035
*
1136
* scripts/pm/dispatch-gates.mjs derives the "local gates for this card" line of

scripts/pm/dispatch-gates.mjs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@
1717
* node scripts/pm/dispatch-gates.mjs --repo <owner>/<name> ... # refuse unless this checkout IS that repo
1818
* node scripts/pm/dispatch-gates.mjs --self-test
1919
*
20+
* ## Run --self-test DETACHED on an agent container (#14281)
21+
*
22+
* The battery re-spawns this tool's own CLI as a child process many times —
23+
* deliberate (see `check-dispatch-gates.mjs`'s header for why a self-test this
24+
* size is not fixture-only) — and on an agent container that makes the full
25+
* run longer than the container's foreground command cap, which SIGTERMs a
26+
* run past it. Do not run `--self-test` (or `pnpm check:pm-dispatch-gates`,
27+
* which is exactly that flag) in the foreground there. Detach it and poll the
28+
* log instead:
29+
*
30+
* nohup pnpm check:pm-dispatch-gates > /tmp/pm-dispatch-gates.log 2>&1 &
31+
*
32+
* then tail the log file until it stops growing. Each case's `✓`/`✗` line
33+
* prints the moment that case is decided, so a run killed mid-battery — by
34+
* this cap, or by anything else — still leaves every case decided before the
35+
* kill in the log, readable as a partial result rather than a silent zero. The
36+
* measured runtime and case count are not repeated here — they move with the
37+
* tree and belong to a named commit, not to this header (see #14281 for the
38+
* reading that motivated this section).
39+
*
2040
* ## Harvest the machine-readable modes, never this prose (#13462)
2141
*
2242
* The matched block renders in TWO spellings — `pnpm check:NAME` and
@@ -10032,7 +10052,19 @@ export function bannerLines({ identity, paths = [], drift = null }) {
1003210052

1003310053
function selfTest() {
1003410054
const cases = [];
10035-
const t = (name, cond) => cases.push([name, cond]);
10055+
// Stream the verdict the moment it is decided (#14281) rather than only at
10056+
// the tail: every `t()` call evaluates `cond` eagerly at the call site, so
10057+
// the line below is not a preview of the tail loop's output — it prints the
10058+
// SAME verdict, just however many calls earlier than a buffered run did. A
10059+
// run that dies mid-battery (the container's foreground cap SIGTERMs a run
10060+
// past ~10 minutes; see check-dispatch-gates.mjs's header for the detached
10061+
// workaround) used to leave zero case lines; now the log already carries
10062+
// every case decided before the kill. `cases` still collects every entry —
10063+
// the tail's `failed`/`length` summary reads it unchanged.
10064+
const t = (name, cond) => {
10065+
cases.push([name, cond]);
10066+
console.log(` ${cond ? '✓' : '✗'} ${name}`);
10067+
};
1003610068

1003710069
const wf = [
1003810070
'jobs:',
@@ -16829,10 +16861,12 @@ function selfTest() {
1682916861
}
1683016862
}
1683116863

16864+
// The per-case line already printed inside `t()`, streamed as each verdict
16865+
// was decided (#14281) — this tail is the summary only, unchanged in shape
16866+
// and wording from the pre-streaming version.
1683216867
let failed = 0;
16833-
for (const [name, cond] of cases) {
16868+
for (const [, cond] of cases) {
1683416869
if (!cond) failed++;
16835-
console.log(` ${cond ? '✓' : '✗'} ${name}`);
1683616870
}
1683716871
if (failed) {
1683816872
console.error(`✗ dispatch-gates self-test: ${failed} of ${cases.length} case(s) failed.`);

0 commit comments

Comments
 (0)