Skip to content

[quality] Nightly mutation set omits src/plugins/tide.ts and src/utils/mergeQueue.ts, the code that performs the merge #650

Closed

Description

@hivecommons-hive

Finding

stryker.config.mjs / stryker.nightly.config.mjs mutate the merge-decision code (mergeGate.ts, labelMatch.ts, hold.ts, duration.ts), but the scheduled mutation job never runs a mutant of src/plugins/tide.ts (tryMergePullRequest, mergeOnce, explainForkWorkflows, the tideOn* event filters, loadTide/evaluate) or src/utils/mergeQueue.ts — the code that actually merges or enqueues a pull request. A behavioural regression there that line coverage still reaches would go unnoticed, which is the exact class the nightly gate exists for.

Evidence (main @ 424fb95, npx stryker run with mutate: ['src/plugins/tide.ts', 'src/utils/mergeQueue.ts'], same vitest.mutation.config.mjs, 26 min locally):

File Score Killed Survived No coverage
src/plugins/tide.ts 95.30 % 487 24 0
src/utils/mergeQueue.ts 100 % 109 0 0

Every one of the 24 survivors was applied at its exact span and read: 14 change only platform().log.debug/log.error text or a condition that selects a debug line, 2 change joiner strings in the fork-workflows comment, and 8 are equivalent (?? [] → placeholder filtered by workflowFiles; catch { return false } → catch {} read for truthiness; data.base.repo?. on a field GitHub always sends; action === undefined before a Set.has that is false for undefined; let hasOwners = false → true only read when tide.labels is unset, where it is reassigned; { required: false } → {}; lookup !== undefined where every empty-list caller passes lookup). So the files are clean today — the gap is that nothing would tell us when they stop being clean.

Unit coverage for both files is 100 % lines (test.yml run 41176427955 artifact coverage-424fb95…), and the bundle run reaches them too (coverage-e2e-424fb95…); this is not a coverage gap, it is a gate-scope gap.

Recommendation

Add both files to the nightly set only (stryker.nightly.config.mjs: mutate: [...base.mutate, 'src/plugins/tide.ts', 'src/utils/mergeQueue.ts']) and record the 24 reviewed survivors in the docs/contributing.md survivor table so the per-file tally can be read against them. Combined score at 424fb95 is (596+142)/(596+142+24+6) = 96.1 %, above the existing break: 95. The nightly job ran 148 mutants in 2.6 min after a 54 s dry run on GitHub-hosted runners (job of run 41176427955), so ~620 more fits well inside its 60-minute timeout; the local npm run test:mutation default set is left as is so a contributor's run stays ~12 minutes.

Decision taken by hive: nightly-only rather than the shared base set, because the base set's size is documented as a deliberate bound for local runs and the scheduled job is where the extra ~25 min is free.

Priority

  • Impact: medium (merge executor is unguarded against silent assertion loss; no defect today)
  • Effort: low

Filed by quality agent (hold-gated mode)


🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5q9t | SHA: d6296b6

— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityCreated by Hive for agent-filed issue provenancekind/cleanupCategorizes issue or PR as related to cleaning up code, process, or technical debt.testingCreated by Hive for agent-filed issue provenance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions