Skip to content

test: kill batch-2 surviving mutants → 96% mutation score#43

Merged
williamdewitt merged 1 commit into
mainfrom
test/mutants-batch-2
Jun 26, 2026
Merged

test: kill batch-2 surviving mutants → 96% mutation score#43
williamdewitt merged 1 commit into
mainfrom
test/mutants-batch-2

Conversation

@williamdewitt

Copy link
Copy Markdown
Owner

Closes #41 — the batch-2 mutation survivors (the set the @claude agent stalled on, being too large for one autonomous run). Done by hand with local Stryker verification.

Result

  • Mutation score 59.92% → 96.26% (batch 1 took it to 65%; this is the rest).
  • 98 → 153 tests, all green on net8.0 + net10.0.
  • Exactly 1 survivor remains, by design (see below).

New / strengthened coverage

Area What was missing Added
AddCaliberWebhooks validation boundaries + message text untested min-valid-accepted tests (kill the < 1/>= flips) + message-fragment assertions
Constructor guards null-collaborator guards untested ConstructorGuardTests across every internal component
HttpDeliveryChannel no dedicated tests at all new suite: 2xx success, non-2xx → "HTTP {n}", null guards
DeliveryManager no-due path, claim token, throttle no-due returns 0; owner-is-the-claim-token (spy store); a batch > MaxConcurrency drains fully (proves the semaphore is released)
Ingestion / Subscription / MessageStore publish/claim guards, lease boundary guard tests + an exact-lease-expiry boundary test

Equivalent mutants

  • ConfigureAwait is added to Stryker's ignore-methods — its boolean mutant (falsetrue) is not observable in a unit test, so it was 31 mutants of pure noise.
  • The rest are annotated in source with // Stryker disable once … : equivalent — … (fast-path returns; lease release on already-terminal messages; the defensive key-wipe finally; guards the downstream already enforces).
  • One survivor left on purpose: the format string ("n") of the random fallback claim token, used only when no owner is configured — purely cosmetic, no observable behaviour.

Note

Touches src/ (the // Stryker disable annotations, incl. SigningEngine), so this classifies risk:critical and is human-gated. No behaviour changes — comments only on the source side.

🤖 Generated with Claude Code

Closes the batch-2 Stryker survivors (the batch the agent stalled on, #41):
options validation, the manager/host/store guards and branches, and the HTTP
delivery channel. Mutation score 59.92% → 96.26%; 98 → 153 tests.

New / strengthened tests:
- ConstructorGuardTests: null-collaborator guards across every internal component.
- ServiceCollectionExtensions: boundary-accepted minimums (kills the `< 1`/`>=`
  equality flips) + message-fragment assertions (kills the validation strings).
- HttpDeliveryChannelTests (new): 2xx success, non-2xx → "HTTP {n}", null guards.
- DeliveryManager: no-due path, owner-is-the-claim-token (spy store), and a
  batch larger than MaxConcurrency drains fully (proves the throttle is released).
- Ingestion/Subscription/MessageStore: publish + claim guards, lease-expiry boundary.

Stryker config: ignore `ConfigureAwait` (its boolean mutant is equivalent — not
observable in unit tests; removed 31 mutants of pure noise).

The remaining equivalents are annotated in source with `// Stryker disable once`
justifications (fast-path returns; lease release on already-terminal messages;
the defensive key wipe in a finally; guards the downstream also enforces). One
cosmetic survivor is left by design: the format string of the random fallback
claim token, used only when no owner is configured.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013NxkrufMdQ9cy21T4ZnUNY
@github-actions github-actions Bot added the risk:critical SSRF/signing/secret/public-API/migrations; review + design (Opus, max) label Jun 26, 2026
@williamdewitt williamdewitt merged commit 445dc07 into main Jun 26, 2026
9 checks passed
@williamdewitt williamdewitt deleted the test/mutants-batch-2 branch June 26, 2026 11:29
williamdewitt added a commit that referenced this pull request Jun 26, 2026
The full-project mutation score is now 96.26% (after #42/#43), so the gate can be
ratcheted up from its initial floor. Thresholds become high:90 / low:80 / break:80
— coherent (break == low, the red zone) and meaningful: changed code must clear
80% mutation-kill to merge, while config-touching PRs (which force a full run) pass
comfortably against the 96% baseline.


Claude-Session: https://claude.ai/code/session_013NxkrufMdQ9cy21T4ZnUNY

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:critical SSRF/signing/secret/public-API/migrations; review + design (Opus, max)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: kill surviving mutants — managers, hosting, delivery & message store (batch 2)

1 participant