Skip to content

finding: check:skill-frame-freshness (#5866) is invoked by nothing — not CI, not a git hook, not another script #6990

Description

@os-project-manager

Observation-class. Found while enumerating root check:* wiring for #6865 (PR #6983); not carried in that PR.

Fact

check:skill-frame-freshness exists in the root package.json and its script is real and working, but no in-repo entry point runs it. Measured on origin/main at 55011af — every reference to it anywhere in the tree, excluding the script's own file:

scripts/check-skill-frame-sync.mjs:103:   * EXPORTED for scripts/check-skill-frame-freshness.mjs (#5866), which asks the
package.json:42:    "check:skill-frame-freshness": "node scripts/check-skill-frame-freshness.mjs --self-test && ..."

That is one prose mention in a sibling's comment, plus the alias itself. Nothing in .github/workflows/**, nothing in .githooks/**, and no other package.json script chains it. Its sibling gate is wired — .github/workflows/lint.yml:964 runs pnpm check:skill-frame-sync — so the asymmetry is visible side by side.

The script runs clean today (EXIT=0), so this is not a latent red; it is a gate with no path on which it can ever go red for anyone.

Why it is worth recording

#5866 wrote this gate against a measured, still-live channel: dispatch prompts are assembled from a working tree on disk, and on 2026-08-06 a shared PM checkout 173 commits behind handed every dispatched dev agent the pre-#5130 two-axis decision frame — the axis #5130 ruled changes verdicts (#5021 vs #4936). The script's own header calls that "a lying green light". A gate written against a live channel and then reachable from no entry point is the #4690 phantom-check shape one level over: it reads as coverage in the ledger and in the script list, and covers nothing.

⚠️ Wiring it into CI is probably the WRONG fix — do not treat that as the obvious answer

The question this gate asks is "is this working tree current with origin/main". A CI runner checks out fresh, so on CI the answer is trivially yes and the gate is green by construction — the #4177/#4232 dormant-gate class. The channel #5866 is about is a seat's local checkout at dispatch time, which CI never observes.

So the real dispositions look like:

  1. a documented, enforced invocation at the point that matters (a pm-dispatch preflight step), so the gate runs where its input actually varies;
  2. retirement, if the drift is now covered another way — with the reason recorded, since the channel is measured and was live as recently as the gate's own authoring;
  3. keep as an on-demand tool, but say so in the script header and in the dispatch playbook, so "runnable, deliberately not run by CI" is a stated classification rather than something the next reader has to infer from absence. packages/spec's check:generated ledger already draws exactly this distinction (NO_GENERATOR = "runnable, deliberately not run here" vs EXTERNAL_INPUT_REQUIRED = "cannot run here"), and its header records that conflating the two is what check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690 cost.

No recommendation between these — the choice depends on whether the dispatch preflight is a place the maintainer wants a gate.

Adjacent, recorded so it is not re-derived

Root check:* scripts have no coverage ledger. packages/spec has one (check:generated --reconcile-only, wired into lint.yml, which reconciles in both directions and fails when a gate drops out of coverage), but it reads packages/spec/package.json only — the 56 root-level check:* scripts are outside its program entirely. That is why this orphan could exist silently. Whether root gates deserve the same reconciliation is a separate question from this one card.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions