Filed by the PM seat from PR #9706's open question 2. Ruled A — this is the half PR #9706 could not take, because release.yml sits inside epic #9465's declared file territory.
What is missing
PR #9706 adds pnpm check:console-injection --require-stamp to ci.yml on both cache paths, so any run that consumes a restored console dist verifies that the dist actually carries this tree's@objectstack/spec rather than the published tarball. release.yml carries the same cache key and did not get the same step:
ci.yml:1439 key: ${{ runner.os }}-console-dist-${{ hashFiles('.objectui-sha', 'scripts/build-console.sh') }}
ci.yml:1485 (identical)
release.yml:491 (identical) <-- unguarded
Why this is not covered by the ci.yml side
Two facts, both measured by #9706's dev, and the combination is what makes it reachable:
release.yml uses the COMBINED cache action, whose post-step saves even when the job failed — per ci.yml's own comment, which is why ci.yml deliberately uses a split restore/save instead. That is the concrete path a poisoned entry enters the shared, repo-scoped cache.- The console job is filter-gated.
ci.yml's console paths filter is exactly .objectui-sha · scripts/build-console.sh · scripts/check-console-sha.mjs · .github/workflows/ci.yml — I verified this at ci.yml:102-106. So there is no guarantee any PR run inspects a given cache entry before release.yml restores it. A spec-only change never runs the console job at all.
⇒ "the ci.yml gate will catch it first" is not safe. It catches it first only when a PR happens to touch one of those four paths.
The change
Add, in release.yml after its check:console-sha step, the same step ci.yml now carries:
- name: Console injection stamprun: pnpm check:console-injection --require-stamp
Match ci.yml's spelling exactly rather than inventing a variant — the point is that both consumers of one cache key apply one check.
⛔ Fence
.github/workflows/release.yml is named explicitly in epic #9465's declared territory (.changeset/** · four changeset scripts · cut-rc.yml · release.yml · pr-automation.yml changeset steps · root package.json's @changesets/cli range and version script). It is not inside the scoping parenthetical, so it is fenced however the open question on that parenthetical resolves.
This card is for whoever holds the #9465 fence, or for after that epic completes. It is one step; the work is coordination, not implementation.
⚠️ Sequencing: blocked until PR #9706 lands — check:console-injection does not exist before it.
Refs: #9667 · PR #9706 · #8134 / PR #9660 · #9465
Generated by Claude Code
Filed by the PM seat from PR #9706's open question 2. Ruled A — this is the half PR #9706 could not take, because
release.ymlsits inside epic #9465's declared file territory.What is missing
PR #9706 adds
pnpm check:console-injection --require-stamptoci.ymlon both cache paths, so any run that consumes a restored console dist verifies that the dist actually carries this tree's@objectstack/specrather than the published tarball.release.ymlcarries the same cache key and did not get the same step:Why this is not covered by the ci.yml side
Two facts, both measured by #9706's dev, and the combination is what makes it reachable:
release.ymluses the COMBINED cache action, whose post-step saves even when the job failed — perci.yml's own comment, which is whyci.ymldeliberately uses a split restore/save instead. That is the concrete path a poisoned entry enters the shared, repo-scoped cache.ci.yml'sconsolepaths filter is exactly.objectui-sha·scripts/build-console.sh·scripts/check-console-sha.mjs·.github/workflows/ci.yml— I verified this atci.yml:102-106. So there is no guarantee any PR run inspects a given cache entry beforerelease.ymlrestores it. A spec-only change never runs the console job at all.⇒ "the
ci.ymlgate will catch it first" is not safe. It catches it first only when a PR happens to touch one of those four paths.The change
Add, in
release.ymlafter itscheck:console-shastep, the same stepci.ymlnow carries:Match
ci.yml's spelling exactly rather than inventing a variant — the point is that both consumers of one cache key apply one check.⛔ Fence
.github/workflows/release.ymlis named explicitly in epic #9465's declared territory (.changeset/**· four changeset scripts ·cut-rc.yml·release.yml·pr-automation.ymlchangeset steps · rootpackage.json's@changesets/clirange andversionscript). It is not inside the scoping parenthetical, so it is fenced however the open question on that parenthetical resolves.This card is for whoever holds the #9465 fence, or for after that epic completes. It is one step; the work is coordination, not implementation.
check:console-injectiondoes not exist before it.Refs: #9667 · PR #9706 · #8134 / PR #9660 · #9465
Generated by Claude Code