Filed by the domain:devx dev working #8024 (PR #8109). Out of scope there — that card's file surface is scripts/check-skill-frame-freshness.mjs, and this is a workflow change. #8024 remains open until its own PR lands.
The observation
check:skill-frame-freshness is deliberately not wired into lint.yml, and the script's header gives the reason, which is correct as far as it goes: on a fresh CI merge ref the scan is a tautological green, and on any PR that legitimately edits the decision frame it would be a false red, since "differs from main" is that PR's whole purpose.
But package.json runs the gate in two halves:
"check:skill-frame-freshness": "node scripts/check-skill-frame-freshness.mjs --self-test && node scripts/check-skill-frame-freshness.mjs"
The reasoning above applies only to the second half. The --self-test half is a pure self-consistency check: it manufactures a specimen from the repo's own files, drives it through temp git repos, and touches neither the network nor origin/main. Nothing about it is tautological on a merge ref, and nothing about it goes red on a PR that edits the frame on purpose (it re-derives from whatever the frame currently is).
So the half that CANNOT run in CI is keeping the half that CAN out of it.
Why it is worth a card
Measured while fixing #8024: the fixture had stranded twice, not once.
| documents |
old hand-copied fixture |
pre-rewrite (ab19075^) |
RED — its mention rule spelled 沿三条固定评估轴, missing the bare 三条评估轴 mention in the same file, so the specimen was incoherent and the independence case failed |
today (HEAD) |
RED — the axis-line rule matched nothing after the 2026-08-12 rewrite; this is what #8024 reports |
The first stranding was never noticed by anyone. Both would have been caught the day they landed by running the self-test half in CI. The failure mode is the expensive kind: the gate stays in the gate list reading as coverage while protecting nothing.
Suggested shape
Add a step to lint.yml running node scripts/check-skill-frame-freshness.mjs --self-test on its own — not pnpm check:skill-frame-freshness, which would drag the scan in with it. Worth checking whether other gates in the repo have the same split shape (a CI-hostile scan hiding a CI-safe self-test behind &&); if so this is a family, not a single step.
Establishment
Measured in a clean worktree at d91c558; the pre-rewrite half by reconstructing the three framework documents and both scripts at ab19075^ into a temp tree and running the self-test there. The exact dating of the first stranding could not be established — this clone's history is grafted at f7dceed, so git log -S on the mention attributes it to the graft boundary rather than to a real introducing commit.
Generated by Claude Code
Blocked-by: #8024
Filed by the
domain:devxdev working #8024 (PR #8109). Out of scope there — that card's file surface isscripts/check-skill-frame-freshness.mjs, and this is a workflow change. #8024 remains open until its own PR lands.The observation
check:skill-frame-freshnessis deliberately not wired intolint.yml, and the script's header gives the reason, which is correct as far as it goes: on a fresh CI merge ref the scan is a tautological green, and on any PR that legitimately edits the decision frame it would be a false red, since "differs frommain" is that PR's whole purpose.But
package.jsonruns the gate in two halves:The reasoning above applies only to the second half. The
--self-testhalf is a pure self-consistency check: it manufactures a specimen from the repo's own files, drives it through temp git repos, and touches neither the network nororigin/main. Nothing about it is tautological on a merge ref, and nothing about it goes red on a PR that edits the frame on purpose (it re-derives from whatever the frame currently is).So the half that CANNOT run in CI is keeping the half that CAN out of it.
Why it is worth a card
Measured while fixing #8024: the fixture had stranded twice, not once.
ab19075^)沿三条固定评估轴, missing the bare三条评估轴mention in the same file, so the specimen was incoherent and the independence case failedHEAD)The first stranding was never noticed by anyone. Both would have been caught the day they landed by running the self-test half in CI. The failure mode is the expensive kind: the gate stays in the gate list reading as coverage while protecting nothing.
Suggested shape
Add a step to
lint.ymlrunningnode scripts/check-skill-frame-freshness.mjs --self-teston its own — notpnpm check:skill-frame-freshness, which would drag the scan in with it. Worth checking whether other gates in the repo have the same split shape (a CI-hostile scan hiding a CI-safe self-test behind&&); if so this is a family, not a single step.Establishment
Measured in a clean worktree at
d91c558; the pre-rewrite half by reconstructing the three framework documents and both scripts atab19075^into a temp tree and running the self-test there. The exact dating of the first stranding could not be established — this clone's history is grafted atf7dceed, sogit log -Son the mention attributes it to the graft boundary rather than to a real introducing commit.Generated by Claude Code
Blocked-by: #8024