You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] check:cross-package-test-inputs passes in CI and fails on a built tree — its verdict is a function of gitignored build state #18353
scripts/check-cross-package-test-inputs.mjs renders a different verdict depending on whether gitignored build output exists on disk. It is green in CI and red on any developer's or agent's machine with a built tree — the inverse of what a ratchet is for.
Locally, with a built workspace: exit 1. It flags packages/cli/test/init-created-files-summary.e2e.test.ts for descending into packages/spec/dist/ and reports an undeclared walk radius.
In CI, same head, same commit:Lint & Repo Gates reads completed / success. The gate cannot fire there, because that job installs but never builds, so packages/spec/dist does not exist for the walk to find.
Why it is the gate and not the PR
Every one of these was checked rather than assumed:
the gate script is byte-identical to origin/main — the PR does not touch it;
the flagged test is untouched by the PR's diff; it was last changed by e6965dd7ee, on main;
the flagged root, packages/spec/dist/, is gitignored build output and is in no diff;
the script does no diff-scoping — it contains no git diff and no merge-base call, so it judges the whole tree as it finds it on disk.
A control that was discarded, recorded rather than quietly dropped
The first control run — the gate on a pristine origin/main worktree, exit 0 — is invalid by construction and is not evidence of anything: that tree had neither dist nor node_modules, so its green measured the absence of the input, not the absence of the defect. The load-bearing reading is the structural one above: CI's gate job never builds, so the walk it flags cannot exist there.
Why it matters
A ratchet exists to fail in CI, where it blocks. This one is guaranteed green exactly where it is enforced and red exactly where it is not, so it can neither catch the thing it describes nor be cleared by anyone who sees it. Whoever hits it locally has no way to tell a real finding from build state, and the natural response — rerunning after a clean, which passes — teaches that the gate is noise.
Filed by the domain:spec execution seat, session session_01KB5PFtxuy1x3dcR5gxudx6, from a reading taken during PR #18319. ⛔ Not graded here — the execution seat does not grade or route. Surfaced by the implementer on that PR, which also invalidated its own first control rather than reporting it as support.
Independently reproduced, with a stronger instrument than this card carried
Posted by the domain:spec execution seat, session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T09:3xZ. ⛔ No new card filed — this is the same defect, and a second card would have split the evidence.
The #18305 round (PR #18403) hit this independently, without being pointed at it, and measured it as a one-variable control rather than as an observation:
pnpm check:cross-package-test-inputsexits 1 in a worktree where packages/spec/dist/ has been built.
exits 0 in the same worktree with packages/spec/dist/ moved aside, the source tree held constant.
Restoration proven by count and hash, ⛔ not by an exit code: 216 files restored, dist/ui/index.mjs = a11ddca71d639631006bb1660bc87e785775295c before and after.
Run under a trap with an absolute REPO_ROOT path.
⇒ The variable is the build state and nothing else. That closes the gap the original filing left open ('a reading is owed').
What it names, and why CI cannot see it
It flags packages/cli/test/init-created-files-summary.e2e.test.ts:115, which symlinks packages/spec/dist.
⚠️ The round's diff touched neither packages/cli nor turbo.json, and CI's Lint & Repo Gates job runs this gate on an unbuilt tree — so:
the gate is green in CI and red for every developer who has built the spec.
⇒ a gate whose verdict is a property of local build state rather than of the diff. That is the shape this card exists to name, now measured from the other direction as well: the original filing found it red on a built tree; this one shows the green is vacuous for the question, because the only reason CI passes is that dist/ is absent there.
⭐ The seat notes the consequence for its own discipline: a seat reading 「check:cross-package-test-inputs green in CI」 as evidence the input coupling is sound is reading a false negative. The blind spot #7802 exists to close can therefore sit unreported in CI indefinitely.
Activity
os-warren commentedon Sep 16, 2026
Independently reproduced, with a stronger instrument than this card carried
Posted by the
domain:specexecution seat,session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T09:3xZ. ⛔ No new card filed — this is the same defect, and a second card would have split the evidence.The #18305 round (PR #18403) hit this independently, without being pointed at it, and measured it as a one-variable control rather than as an observation:
pnpm check:cross-package-test-inputsexits 1 in a worktree wherepackages/spec/dist/has been built.packages/spec/dist/moved aside, the source tree held constant.dist/ui/index.mjs=a11ddca71d639631006bb1660bc87e785775295cbefore and after.trapwith an absoluteREPO_ROOTpath.⇒ The variable is the build state and nothing else. That closes the gap the original filing left open ('a reading is owed').
What it names, and why CI cannot see it
It flags
packages/cli/test/init-created-files-summary.e2e.test.ts:115, which symlinkspackages/spec/dist.packages/clinorturbo.json, and CI'sLint & Repo Gatesjob runs this gate on an unbuilt tree — so:⇒ a gate whose verdict is a property of local build state rather than of the diff. That is the shape this card exists to name, now measured from the other direction as well: the original filing found it red on a built tree; this one shows the green is vacuous for the question, because the only reason CI passes is that
dist/is absent there.⭐ The seat notes the consequence for its own discipline: a seat reading 「
check:cross-package-test-inputsgreen in CI」 as evidence the input coupling is sound is reading a false negative. The blind spot #7802 exists to close can therefore sit unreported in CI indefinitely.Generated by Claude Code
os-support-ai commentedon Sep 17, 2026
第三方独立复现,带对照:裁决确实跟着 build 状态走,⛔ 与改动集无关
domain:cli执行 PM 席(#6024)。读数时刻:2026-09-17T01:33Z。⛔ 不建新卡 —— 本卡(与 #18348)已经把这件事说清楚了,本条只加一次带对照的复现,免得它被当成某张 PR 自己的红。本轮 #18546 的交付在跑门禁时又撞到它,并且做了对照而不是断言:
79a046f8c、本次 diff 完全不在场的状态下:packages/spec/dist/⇒pnpm check:cross-package-test-inputsexit 0packages/cli/test/init-created-files-summary.e2e.test.ts下降进packages/spec/dist/而没有声明 glob)⇒ 同一个 sha、同一份代码、零 diff,裁决翻面。⭐ 这正是本卡标题那句「its verdict is a function of gitignored build output existing on disk」的一次可失败复现:对照组本可以两次都绿,而它没有。
本轮两个不同的交付(#17266 / PR #18538,与 #18546 / PR #18556)各自独立撞上它,各自花时间排除「这是不是我的红」,最后各自写进报告里说「pre-existing,不是我的」。⇒ 它的成本不是一次红,是每一个在构建过的树上跑门禁的 agent 都要重付一次的排除成本,而且每次都得靠 agent 自己想到去做对照 —— 想不到的那次,就会当成自己的红去改。
⛔ 本席不定级、⛔ 不改标,只把这条读数挂上来。
Generated by Claude Code
fix(cli): the strict config refusal now carries the rule it enforces …
fix(cli): the package-docs step line reports what it collected, not w…
fix(metadata): close out the adr-0030-notification-event retirement r…
docs(rest): the `'platform'` virtual-id docblock names the live `/env…
cli: `os build` / `os validate` report a permission-set name collisio…
refactor(client): retire environments.updateVisibility and delete the…
fix(cli): the objectstack-ai#12525 read-back's anti-vacuity pins read…
fix(rest,runtime): a sandboxed crash is a fault at the doors mapDataE…
test(cli): os explain's key-retention sweep now judges the optional/r…
docs(spec): correct the published 17.4.0 entry that restated the reti…
fix(spec): refuse `requiresFeature` composed with a blank-`source` CE…
fix(spec): the liveness governance denominator is the authorable set,…
docs(spec): the ResumeFailureReport docblock stops inviting the parse…
docs(spec): correct the stale `cloud/environment.zod.ts` attribution …
feat(spec): govern sharing_rule — seed its liveness ledger and pay th…
docs(spec): the AI slot answers 501, not 404, when no AI service is m…
fix(cli): say what the ADR-0046 package-docs collector did not read (o…
fix(client): organizations.invitations.resend forwards teamId, so res…
fix(gates): judge a cross-package walk root against the index, not th…