Repository navigation
test(mutation): add a bounded Stryker harness for the merge-decision code - #572
hivecommons-hive[bot] wants to merge 1 commit into
Conversation
…code `npm run test:mutation` runs StrykerJS over src/utils/mergeGate.ts, src/utils/labelMatch.ts, src/labels/hold.ts and src/utils/duration.ts through vitest.mutation.config.mjs, which leaves out the bundle harness (it runs the committed dist/index.js, which no mutation of src/ can reach) and turns coverage off. Reports and the incremental file land in reports/mutation/, which is ignored along with .stryker-tmp. The Vitest config also carries a shim for stryker-mutator/stryker-js#6210: vitest-runner 10.0.0 selects a mutant's tests with a testNamePattern of space-joined names while Vitest 5 matches the " > "-joined chain, so without it every mutant inside a describe() is reported Survived with 0 tests run. First run: 151 mutants, 142 killed. The one real survivor, labelMatch.ts:35 (`at = found - part.length` let a middle part reuse the characters of the part before it), is pinned in labelMatch.test.ts; the eight remaining survivors are reviewed in docs/contributing.md. Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com>
|
Important Held for human review by the hive's ACMM level gate. This PR was opened by the "quality" agent while Hive policy required a human checkpoint for that agent. Agent PRs are held at ACMM L3–L5; an Hive will keep the |
|
Please add a kind label with |
24dfbaf
ℹ️ Sentinel notice — informational; author is trusted (hive agent), merge is not blockedHive flagged this PR (author @hivecommons-hive[bot], head
Hive did not add the |
Test Improvement
Adds the bounded, repeatable mutation check that #554's "Strengthen assertions and the test harness" section asks for ("Establish bounded, repeatable mutation checks for selected high-risk behavior, with reproducible commands and reviewed equivalent-mutant exclusions. A repository-wide mutation gate is not required.").
Files / cluster claimed:
stryker.config.mjs,vitest.mutation.config.mjs,package.json(test:mutationscript +@stryker-mutator/core,@stryker-mutator/vitest-runnerdevDependencies),package-lock.json,.gitignore,docs/contributing.md(new "Mutation checks" section appended after the phantom-branches section — disjoint from #556's table-row edit),__tests__/utils/labelMatch.test.ts(matchesLabelPatternmiddle-part overlap). Nosrc/ordist/change.npm run test:mutationruns StrykerJS over the merge-decision code:src/utils/mergeGate.ts,src/utils/labelMatch.ts,src/labels/hold.ts,src/utils/duration.ts.--mutate <file>probes any other file.coverageAnalysis: 'perTest', reports + incremental file inreports/mutation/(ignored). Nobreakthreshold: this is a local/nightly-style check, not a per-push gate, per Follow-up: strengthen test contracts, CI enforcement, release delivery, and quality triage #554.vitest.mutation.config.mjsleaves out__tests__/bundle/**(the harness runs the committeddist/index.js, which no mutation ofsrc/can reach) and turns coverage off.@stryker-mutator/vitest-runner10.0.0 selects a mutant's tests with atestNamePatternof space-joined names; Vitest 5 matches that pattern againstfullTestName, joined with" > "(node_modules/vitest/dist/task-utils.jscreateTaskName(names, separator = " > "), used byinterpretTaskModes). Without the shim every mutant inside adescribe()is reported Survived with 0 tests run — reproduced here: 123/151 survived,labelMatch.ts/mergeGate.ts0 killed. Reported upstream as vitest-runner: on Vitest 5 the per-test name filter matches nothing, so every covered mutant survives (testNamePattern now joins the chain with ' > ') stryker-mutator/stryker-js#6210 (fix PRs fix(vitest-runner): match Vitest 5 test name separator when filtering tests stryker-mutator/stryker-js#6214, fix(vitest-runner): match nested test names joined with " > " (vitest 5) stryker-mutator/stryker-js#6247 and fix(vitest-runner): use native test names for Vitest 5 selection stryker-mutator/stryker-js#6260 open, unreleased). AconfigureVitestplugin hook rewrites each space in the pattern Stryker assigns to(?: > | ). The docs say to drop the shim once a vitest-runner release carries the fix.First run (main @ e3119ad, Stryker 10.0.0, Vitest 5.0.4, Node 26)
mergeGate.tslabelMatch.tshold.tsduration.ts11 m 36 s on 2 workers. The one real survivor,
labelMatch.ts:35(at = found - part.length: a middle*-separated part could reuse characters of the part before it, so*ab*b*matchedab), is pinned by the newdoes not let a middle part reuse characters of the part before itcase. The eight remaining survivors are reviewed in the docs table (two equivalent induration.ts; six inhold.tswhose only observable is@actions/core's own error text, anissue_commentpayload GitHub never sends, or acore.debugstring).Not in this PR
A scheduled CI lane for this command would be a
.github/workflows/**change, which this agent's token cannot push; #554 says a repository-wide gate is not required, so none is proposed here.Validation
npm run test:mutation(twice: before the shim → 123 survived / 0 tests per runtime mutant; after → 142 killed; incremental re-run onlabelMatch.tsafter the new test → 47/47 killed)npx vitest run __tests__/utils/labelMatch.test.ts→ 24 passednpx eslint stryker.config.mjs vitest.mutation.config.mjs __tests__/utils/labelMatch.test.ts docs/contributing.md→ cleanpackage-lock.json: 169 added entries, 0 removed, 4@inquirer/*patch bumps pulled in by StrykerRelated Issue
Refs #554 — this lands the "bounded, repeatable mutation checks" box of the harness section; the tracker's CI-enforcement, release-delivery, remaining harness boxes (#569/#571 cover the unexpected-traffic ones) and routing sections stay open and are owned elsewhere.
Filed by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88 requested_by=@mrbobbytables