Problem Statement
packages/hex-schema/stryker.config.json still carries !src/**/*.kernel.ts in its mutate list, so one real file — src/prefixed-hex.kernel.ts — is excluded from mutation testing purely because of how it is named. The repo retired the cell-role suffix taxonomy on 2026-08-16 and CONCEPTS.md now states that a file's name grants it nothing. Renaming that one file makes the exclusion stop matching and silently changes what mutation measures, with nothing reporting the change. Every other package mutating a src/ tree has already moved to src/**/*.ts plus test and declaration exclusions.
Goal
packages/hex-schema/stryker.config.json selects its mutation population without keying on any cell-role filename suffix, and the survivors that widening exposes are either killed or recorded as accepted on this issue.
Evidence: the live suffix key, and the shape everyone else already uses
packages/hex-schema/stryker.config.json (at dae6f86)
"mutate": ["src/**/*.ts", "!src/**/*.test.ts", "!src/**/*.d.ts", "!src/mod.ts",
"!src/**/*.kernel.ts"]
packages/effect-daemon-spec/stryker.config.json (already migrated, same commit)
"mutate": ["src/**/*.ts", "!src/**/*.test.ts", "!src/**/*.property.test.ts",
"!src/**/*.d.ts", "!src/**/__tests__/**"]
packages/hex-schema/src/prefixed-hex.kernel.ts exists — it is the single file the exclusion currently removes, so the entry is live rather than inert.
Orientation
docs/solutions/architecture-patterns/label-routed-rules-are-unfalsifiable.md is the ruling this config predates: it records that a narrow glob is a label-routed check in different clothes, and that widening effect-daemon-spec from a suffix glob to the package moved that package from "score 100, 12 killed, 0 survived" to "score 74.2, 67 killed, 42 survived". Expect the same direction here.
The per-package mutation gate is that package's stryker.config.json and nothing above it. requireTestContribution is configured in the same file.
Related: #47 (effect-daemon-spec mutation settings), #73 (test-contribution unmeasurable under bail).
Boundaries
- Never start a local mutation run. REPO-D3 forbids it, and
.claude/hooks/guard-local-mutation.ts refuses it. The score and survivor list come from the Mutation workflow's merged report, which a human reads.
- Ask first before setting
requireTestContribution: null or changing a threshold.
Non-Counting Outcomes
- Renaming
prefixed-hex.kernel.ts so the exclusion stops matching. That satisfies the letter while leaving the forgeable key in the glob for the next file.
- Widening
mutate and then restoring the score by setting requireTestContribution: null, lowering a threshold, or excluding the newly-exposed files individually.
- Deleting or weakening the kernel's property test to remove survivors.
- Reporting a number without naming the survivors, when the survivors are the point of widening.
- Asserting the exclusion is harmless because the file is "just a kernel"; the retirement's whole finding is that the name carries no such license.
Acceptance Criteria
Problem Statement
packages/hex-schema/stryker.config.jsonstill carries!src/**/*.kernel.tsin itsmutatelist, so one real file —src/prefixed-hex.kernel.ts— is excluded from mutation testing purely because of how it is named. The repo retired the cell-role suffix taxonomy on 2026-08-16 andCONCEPTS.mdnow states that a file's name grants it nothing. Renaming that one file makes the exclusion stop matching and silently changes what mutation measures, with nothing reporting the change. Every other package mutating asrc/tree has already moved tosrc/**/*.tsplus test and declaration exclusions.Goal
packages/hex-schema/stryker.config.jsonselects its mutation population without keying on any cell-role filename suffix, and the survivors that widening exposes are either killed or recorded as accepted on this issue.Evidence: the live suffix key, and the shape everyone else already uses
packages/hex-schema/src/prefixed-hex.kernel.tsexists — it is the single file the exclusion currently removes, so the entry is live rather than inert.Orientation
docs/solutions/architecture-patterns/label-routed-rules-are-unfalsifiable.mdis the ruling this config predates: it records that a narrow glob is a label-routed check in different clothes, and that wideningeffect-daemon-specfrom a suffix glob to the package moved that package from "score 100, 12 killed, 0 survived" to "score 74.2, 67 killed, 42 survived". Expect the same direction here.The per-package mutation gate is that package's
stryker.config.jsonand nothing above it.requireTestContributionis configured in the same file.Related: #47 (
effect-daemon-specmutation settings), #73 (test-contribution unmeasurable under bail).Boundaries
.claude/hooks/guard-local-mutation.tsrefuses it. The score and survivor list come from the Mutation workflow's merged report, which a human reads.requireTestContribution: nullor changing a threshold.Non-Counting Outcomes
prefixed-hex.kernel.tsso the exclusion stops matching. That satisfies the letter while leaving the forgeable key in the glob for the next file.mutateand then restoring the score by settingrequireTestContribution: null, lowering a threshold, or excluding the newly-exposed files individually.Acceptance Criteria
grep -E '\.(kernel|workflow|executor|acl|store|handler|middleware|policy|observer|adapter|shape|state)\.ts' packages/hex-schema/stryker.config.jsonreturns zero lines. (gatekeeper)pnpm check:localexits 0.src/prefixed-hex.kernel.tsis inside the package's mutation population at the merge commit.requireTestContributionwas not set tonullin this change.