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
AGENTS.md:75 states the hidden-tests rule exclude-only, but the gate enforces it spelling-agnostically — the prose declares a narrower rule than the tree enforces #14942
Split out of #14835 by the domain:devx execution seat (session session_012zGPuVVX3deAx9LdjK8jCk) after its measurement showed the gap is prose, not enforcement. Filed into the skills/instruction-surface lane because AGENTS.md is that lane's file and a governed surface.
The defect
AGENTS.md:75 reads, verbatim on origin/main:
Never exclude*.test.ts / *.spec.ts from a package's tsconfig.json —
That rule is exclude-shaped. The invariant it summarises is not: check:type-check-coverage enforces the rule per file and spelling-agnostically, and its own failure text says so — scripts/check-type-check-coverage.mjs:1998:
accounts for this package -- named by an `exclude`, or never reached by any `include` -- so
The gate's header at :1138 names the mismatch out loud: the AGENTS.md rule "is written about a file glob, so it does not reach a whole directory that no include ever named."
⇒ The prose declares a narrower rule than the tree enforces. An author who obeys AGENTS.md to the letter can still hide a whole test directory by never include-ing it, and will be stopped by a gate whose rule they were never told.
Why this is worth fixing rather than leaving
This is the declared ≠ enforced shape pointed the documentation way: the enforcement is right and the description is short. Measured, not hypothetical — the include spelling is the one an author naturally reaches for:
11 packages in this repo keep their tests in a sibling tree outside src today (the include spelling's natural habitat).
5 of them (cli, client, metadata-core, metadata-fs, spec) stay covered ONLY because a second config is named in the typecheck script. Drop that name and they silently re-hide — the gate catches it; AGENTS.md's sentence does not describe it.
The split measured on #14835 is 10 exclude / 0 include. That is an accident of timing, not licence to keep the rule exclude-shaped: the population was mixed until PR #14833 landed hours earlier. An exclude-shaped rule passes the include spelling — it would have passed packages/cli yesterday. Write the sentence about the invariant (a package's tsc program must reach its own tests, however the config fails to reach them), with the gate as the enforcement pointer, so the prose cannot drift narrower than the check again.
Executable acceptance criterion
AGENTS.md:75's rule describes both spellings — a test file removed by an excludeand a test tree no include ever names — and points at check:type-check-coverage as the enforcing instrument. ⛔ No new gate: the enforcement already exists and is already spelling-agnostic; a second copy is the duplicate-predicate drift this repo has already written down about itself.
Provenance
Measurement and full verification: #14835 (comment by the devx seat, 2026-09-03T11:2xZ). Related: #14710 (the triage ruling that asked for the split), PR #14785 (runtime, exclude shape), PR #14833 (cli, include shape + the rootDir: "../.." precedent).
domain:* deliberately unset — triage's field, not this seat's. Governed surface ⇒ human merge.
Split out of #14835 by the
domain:devxexecution seat (sessionsession_012zGPuVVX3deAx9LdjK8jCk) after its measurement showed the gap is prose, not enforcement. Filed into theskills/instruction-surface lane becauseAGENTS.mdis that lane's file and a governed surface.The defect
AGENTS.md:75reads, verbatim onorigin/main:That rule is exclude-shaped. The invariant it summarises is not:
check:type-check-coverageenforces the rule per file and spelling-agnostically, and its own failure text says so —scripts/check-type-check-coverage.mjs:1998:The gate's header at
:1138names the mismatch out loud: the AGENTS.md rule "is written about a file glob, so it does not reach a whole directory that noincludeever named."⇒ The prose declares a narrower rule than the tree enforces. An author who obeys AGENTS.md to the letter can still hide a whole test directory by never
include-ing it, and will be stopped by a gate whose rule they were never told.Why this is worth fixing rather than leaving
This is the declared ≠ enforced shape pointed the documentation way: the enforcement is right and the description is short. Measured, not hypothetical — the include spelling is the one an author naturally reaches for:
srctoday (the include spelling's natural habitat).cli,client,metadata-core,metadata-fs,spec) stay covered ONLY because a second config is named in thetypecheckscript. Drop that name and they silently re-hide — the gate catches it; AGENTS.md's sentence does not describe it.packages/cliwas an include-narrower until PR fix(cli): wire the test layer into check:test-typecheck — 115 test files no tsc program read #14833 fixed it the same day. The spelling is one PR away from recurring.⛔ The trap to avoid while fixing this
The split measured on #14835 is 10 exclude / 0 include. That is an accident of timing, not licence to keep the rule exclude-shaped: the population was mixed until PR #14833 landed hours earlier. An exclude-shaped rule passes the include spelling — it would have passed
packages/cliyesterday. Write the sentence about the invariant (a package's tsc program must reach its own tests, however the config fails to reach them), with the gate as the enforcement pointer, so the prose cannot drift narrower than the check again.Executable acceptance criterion
AGENTS.md:75's rule describes both spellings — a test file removed by anexcludeand a test tree noincludeever names — and points atcheck:type-check-coverageas the enforcing instrument. ⛔ No new gate: the enforcement already exists and is already spelling-agnostic; a second copy is the duplicate-predicate drift this repo has already written down about itself.Provenance
Measurement and full verification: #14835 (comment by the devx seat, 2026-09-03T11:2xZ). Related: #14710 (the triage ruling that asked for the split), PR #14785 (
runtime, exclude shape), PR #14833 (cli, include shape + therootDir: "../.."precedent).domain:*deliberately unset — triage's field, not this seat's. Governed surface ⇒ human merge.Generated by Claude Code