Skip to content

[finding] the spec-property-retirement playbook mandates a tree-scoped absence scan that check:cross-package-test-inputs structurally cannot declare — every retirement written to the playbook gets a pin turbo does not hash, and an untyped resurrection can replay a cached green #15528

Description

@os-sales

Filed by the domain:spec PM seat, session session_01G4138K1EG7kQ81FNba5Kp4, as condition 4(b) of the isolated contract-tier review of PR #15514 (card #14477). Filed unassigned, for triage. ⛔ Not folded into that PR — the verdict is explicit that "the gap is between playbook and gate, not a choice the dev made wrongly", and what that PR owes is an honesty note in its own pin header (its condition 2), not a whole-repo declaration.

Not a duplicate of #10029 (closed): that card was one test's findUp seed reaching two packages. This is the playbook mandating the shape, so every retirement written to it inherits the same undeclarable radius. #10029 is the single instance; this is the generator.

The conflict, measured

.claude/skills/spec-property-retirement/SKILL.md mandates a ⭐ tree-scoped absence scan — a test that walks the repository asserting no resurrection of a retired key. PR #15514 wrote one (packages/spec/src/system/deadline-keys-retirement.test.ts) exactly as prescribed.

scripts/check-cross-package-test-inputs.mjs is green on it, and green as designed: the pin's repo-root seed (path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..')) is a recognised spelling — it appears in --list-escapes@objectstack/spec is declared, and every literal the walk names is covered.

But the walk descends on a loop variable, and the gate's own declaration file states the trade in its own words: "the escape verdict resolves and the NAME does not".

Consequence, measured against turbo.json's @objectstack/spec#test inputs: the pin's real radius — every .ts / .tsx / .js / .mjs / .cjs / .mts / .cts / .json / .md / .mdx / .yaml / .yml outside node_modules / dist / .git / .turbo / .cache / .objectstack / coverage — is not hashed beyond spec's declared globs.

⇒ A resurrection authored in examples/**, apps/**, hand-written content/docs/**, or most packages/*/src/** does not put spec's tests into turbo ls --affected on the PR path, and can replay a cached green. That is the Layer A / Layer B failure AGENTS.md names, arriving through a document that tells authors to build it.

What still holds, so the severity is not overstated

The tsc never channel catches every typed TypeScript authoring site independently of this pin — a resurrected key in typed source fails to compile. The residue is untyped literals and prose: JSON fixtures, MDX, YAML, any-typed object literals. Full runs (merge queue, pnpm test) do execute the pin; only the affected-path shortcut can skip it.

Precedent cuts both ways, which is why this is a question and not an obvious fix

  • The two other repo-root walkers in packages/spec declare their radii honestly and narrowlypackages/**/*.object.ts and packages/lint/src/**.
  • @objectstack/core's whole-repo git ls-files pin is declared as packages/**/*.ts only — the same understatement, already in the tree.
  • The gate's declaration file repeatedly refuses radii that would put a suite on every docs PR, which is exactly what an honest whole-repo declaration here would do.

So "just declare the real radius" is not free: it would make @objectstack/spec#test affected by every content/docs/** and examples/** edit in the repo.

What this card does not decide

Whether the playbook should (a) keep the mandate and accept a full-run-only guarantee, stating it in the mandated pin's header — which is what PR #15514 does under its condition 2; (b) narrow the mandated walk to a declarable radius (packages/** plus named corpora) and say so; (c) move the guarantee to a repo-level gate that runs unconditionally rather than to a package test subject to turbo's affected-path logic; or (d) something else. Triage decides; .claude/skills/** is a governed surface, so whatever lands is draft-only with a human merge and ⛔ no agent approval.

Refs: #14477 · PR #15514 (the review that found it, and the condition-2 honesty note) · #10029 (the single-instance predecessor, closed) · #12077 (the turbo cache is shared across worktrees)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions