Skip to content

Commit 7cb2f9f

Browse files
os-zhuangclaude
andauthored
ci(lint): run scripts/pm/ci-failure.mjs --self-test in Lint & Repo Gates (#10195)
`scripts/pm/ci-failure.mjs` shipped a `--self-test` that no job ran, unlike the four sibling PM tools (dispatch-gates, the part-of guard, the single-claim guard, the half-state sweeper) which all run theirs as unconditional steps in this same job. It was the odd one out, so it could rot until the next agent reached for it mid-round and found it broken. The rot this prevents is the exact defect the tool's own card was about: the file was found near-complete but never run live, because node 22's `fetch` ignores HTTPS_PROXY, so every read answered 401 and the tool's own transport probe reported PREREQUISITE NOT MET (exit 3) — and looked right doing it. A retrieval tool that has stopped working presents as a tool correctly declining to work. One step in the existing `lint:` job, whose `name:` (`Lint & Repo Gates`) is the required-status-check context and is unchanged — a required context is matched by check-run name, so a step adds no context. No new job, no new check name. Unconditional and un-`if:`-ed, like every self-test beside it. Measured, not assumed: under `strace -f` with full egress available the self-test makes zero socket() and zero connect() calls (the live walk, traced identically, makes 3 and 3), and it exits 0 inside an empty network namespace where the live walk exits 3. Runtime ~0.07-0.17 s. Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt Co-authored-by: Claude <noreply@anthropic.com>
1 parent ce300c8 commit 7cb2f9f

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

.github/workflows/lint.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,53 @@ jobs:
388388
- name: Verify-lock entry-point self-test
389389
run: bash scripts/pm/os-verify-lock.sh --self-test
390390

391+
# ci-failure self-test (#9898). Fifth member of the PM self-test family
392+
# above, and until now the odd one out: `scripts/pm/ci-failure.mjs` — the
393+
# one command from "a check is red" to "here is the failing assertion" —
394+
# shipped a `--self-test` that NO job ran, so it executed only when a
395+
# human or an agent typed it.
396+
#
397+
# This tool is worth the second because the rot it would hide is the exact
398+
# defect its own card was about. The file was found near-complete but
399+
# NEVER RUN LIVE: node 22's `fetch` ignores HTTPS_PROXY, so behind an agent
400+
# container's proxy every read answered 401 and the tool's own transport
401+
# probe reported PREREQUISITE NOT MET (exit 3) — and looked right doing it.
402+
# ⇒ A retrieval tool that has stopped working presents as a tool correctly
403+
# declining to work. Nothing about that shape reads as broken, which is
404+
# what makes an unrun self-test the wrong economy here specifically.
405+
#
406+
# The self-test is also materially larger than when the card was filed:
407+
# #9966/PR #10157 corrected the transport probe (a healthy `/rate_limit`
408+
# was greening containers whose repo-scoped reads are refused — the fourth
409+
# measured container class) and added nine cases, which is why this step
410+
# was deliberately ordered AFTER that fix. Wiring a false green into a
411+
# required job would have pinned it as CI-enforced truth.
412+
#
413+
# Beyond the pure predicates it pins the LIVE WIRING: `resolveStep` is run
414+
# against the real `.github/workflows/` tree, so reshaping the workflows
415+
# until no step name resolves to a `run:` block reddens here rather than
416+
# silently degrading every gate failure from "here is the command" into
417+
# "no substitute available".
418+
#
419+
# Unconditional and un-`if:`-ed, like every self-test above it — an
420+
# exemption is precisely what a self-test must not have, or the gap moves.
421+
#
422+
# NO NETWORK, measured rather than assumed (#9898), because a self-test
423+
# that reached GitHub would put this required context at the mercy of API
424+
# availability — a far worse trade than the rot it prevents. Under
425+
# `strace -f` with full egress available the run makes ZERO `socket()` and
426+
# ZERO `connect()` calls (the live walk, traced identically, makes 3 and
427+
# 3), and it exits 0 inside an empty network namespace where the live walk
428+
# exits 3. The `--self-test` branch is chosen before the transport probe
429+
# and never re-execs, and its two readers are injected. ~0.14 s.
430+
#
431+
# Invoked as `node` rather than through a `pnpm check:*` alias, same as
432+
# the release-rehearsal step above: this card's declared file surface is
433+
# this workflow alone, and dispatch-gates.mjs derives gate families from
434+
# either spelling.
435+
- name: PM ci-failure self-test
436+
run: node scripts/pm/ci-failure.mjs --self-test
437+
391438
# Docs/skills authoring guard (#2035 / ADR-0059): TS code blocks in
392439
# Markdown/MDX are not type-checked or ESLinted, so skills/ and
393440
# content/docs/ can drift back to teaching the bare `: Page = {}` literal

0 commit comments

Comments
 (0)