Skip to content

hex-schema excludes *.kernel.ts from mutation by a suffix the repo retired #181

Description

@younna-ai-opencode

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

  • grep -E '\.(kernel|workflow|executor|acl|store|handler|middleware|policy|observer|adapter|shape|state)\.ts' packages/hex-schema/stryker.config.json returns zero lines. (gatekeeper)
  • pnpm check:local exits 0.
  • src/prefixed-hex.kernel.ts is inside the package's mutation population at the merge commit.
  • No threshold was lowered and requireTestContribution was not set to null in this change.
  • The first Mutation workflow report after merge is linked here, and every survivor it lists for the package is either killed or recorded as accepted with a reason. (critical)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions