Filed unassigned by the #9966 dev seat (session session_01DdCnBGcHeufjrq7drTD3wt), out of that card's scope: #9966 is scoped to the transport probe, and this is the walk one layer down. Duplicate search first: keyword sweep over all 231 open issues for the ci-failure / uncaught / walk / transport shapes, plus a semantic search — no hit. Adjacent but distinct: #9966 itself (the probe's false green, being fixed now), #10141 (this file's reachability claim about raw logs), #9898 (this file's --self-test runs nowhere in CI).
Measured, 2026-08-20, in an agent container
Against scripts/pm/ci-failure.mjs as it stands on origin/main (2d3860df9), pointed at a repo this session's egress proxy refuses repo-scoped:
$ PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/ci-failure.mjs --sha 2d3860df9aad...
Error: GET /repos/objectstack-ai/objectui/commits/2d3860df9aad.../check-runs?per_page=100&page=1 -> HTTP 403
at rest (.../ci-failure.mjs:608:19)
at async checkRunsFor (.../ci-failure.mjs:619:18)
at async walk (.../ci-failure.mjs:690:15)
EXIT=1
Why the exit code is the defect, not the stack trace
rest() throws a plain Error on any non-ok status, and nothing between it and the top level catches. Node exits 1 on an uncaught exception — and this file's own exit table assigns:
* 1 RED failing checks, and the assertion text was retrieved for
* EVERY one of them. The output is the answer.
So a container that could not read one byte about the tree hands its caller the code that means "the tree is red and here is the proof". Any script branching on $? — the reading the header explicitly instructs (Piping hides all of it. Read $?) — reads a transport refusal as a confident verdict about the tree. That is the #4690 inversion this file is built to refuse, arriving through the one path the file does not guard.
Note the shape is strictly worse than a missing verdict: exit 2 (UNDETERMINED) would be honest, and the walk never reaches it.
Scope note — #9966 does not close this
#9966 adds a repo-scoped probe stage, so the class-4 container now exits 3 before the walk starts, and the repro above stops reproducing. What remains uncovered is any transport failure arriving mid-walk, after the probe passed: quota exhausted between the probe and the last annotations call, a repo whose access changes under the run, a transient 5xx, a 404 on an annotations URL. The probe cannot cover those by construction — it fires once, at the start.
The decision this needs (which is why it is not a rider on #9966)
What should a mid-walk transport failure exit as? The two candidates are already both in the file's vocabulary and mean different things:
A related sub-question: a mid-walk failure after some checks were read must not print a partial result that reads complete — the same invariant swept keeps true one file over.
Generated by Claude Code
Filed unassigned by the #9966 dev seat (session
session_01DdCnBGcHeufjrq7drTD3wt), out of that card's scope: #9966 is scoped to the transport probe, and this is the walk one layer down. Duplicate search first: keyword sweep over all 231 open issues for the ci-failure / uncaught / walk / transport shapes, plus a semantic search — no hit. Adjacent but distinct: #9966 itself (the probe's false green, being fixed now), #10141 (this file's reachability claim about raw logs), #9898 (this file's--self-testruns nowhere in CI).Measured, 2026-08-20, in an agent container
Against
scripts/pm/ci-failure.mjsas it stands onorigin/main(2d3860df9), pointed at a repo this session's egress proxy refuses repo-scoped:Why the exit code is the defect, not the stack trace
rest()throws a plainErroron any non-ok status, and nothing between it and the top level catches. Node exits 1 on an uncaught exception — and this file's own exit table assigns:So a container that could not read one byte about the tree hands its caller the code that means "the tree is red and here is the proof". Any script branching on
$?— the reading the header explicitly instructs (Piping hides all of it. Read $?) — reads a transport refusal as a confident verdict about the tree. That is the #4690 inversion this file is built to refuse, arriving through the one path the file does not guard.Note the shape is strictly worse than a missing verdict: exit 2 (UNDETERMINED) would be honest, and the walk never reaches it.
Scope note — #9966 does not close this
#9966 adds a repo-scoped probe stage, so the class-4 container now exits 3 before the walk starts, and the repro above stops reproducing. What remains uncovered is any transport failure arriving mid-walk, after the probe passed: quota exhausted between the probe and the last annotations call, a repo whose access changes under the run, a transient 5xx, a 404 on an annotations URL. The probe cannot cover those by construction — it fires once, at the start.
The decision this needs (which is why it is not a rider on #9966)
What should a mid-walk transport failure exit as? The two candidates are already both in the file's vocabulary and mean different things:
verdictOfalready distinguishes retrieved from unretrievable assertions; a partial walk is that same shortfall.check-half-states.mjsfaced the same fork for its in-loop net (see thesweptparameter and the check-i18n-bundles reports a stale-dist prerequisite failure as a content verdict ("1 bundle problem(s)") #7681/check-i18n-coverage:example 自身依赖未构建时仍抛裸异常 + node 栈(诊断准确,但不是结论) #6033 partial-round wording it cites).A related sub-question: a mid-walk failure after some checks were read must not print a partial result that reads complete — the same invariant
sweptkeeps true one file over.Generated by Claude Code