test: kill batch-2 surviving mutants → 96% mutation score#43
Merged
Conversation
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
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #41 — the batch-2 mutation survivors (the set the
@claudeagent stalled on, being too large for one autonomous run). Done by hand with local Stryker verification.Result
New / strengthened coverage
AddCaliberWebhooksvalidation< 1/>=flips) + message-fragment assertionsConstructorGuardTestsacross every internal componentHttpDeliveryChannel"HTTP {n}", null guardsDeliveryManagerMaxConcurrencydrains fully (proves the semaphore is released)Equivalent mutants
ConfigureAwaitis added to Stryker'signore-methods— its boolean mutant (false→true) is not observable in a unit test, so it was 31 mutants of pure noise.// Stryker disable once … : equivalent — …(fast-path returns; lease release on already-terminal messages; the defensive key-wipefinally; guards the downstream already enforces)."n") of the random fallback claim token, used only when no owner is configured — purely cosmetic, no observable behaviour.Note
Touches
src/(the// Stryker disableannotations, incl.SigningEngine), so this classifiesrisk:criticaland is human-gated. No behaviour changes — comments only on the source side.🤖 Generated with Claude Code