Repository navigation
test(prefixed,tide): pin a do-not-merge label section's own command past the /label protected guard, and the position-less enqueued verdict - #597
Conversation
…ast the /label protected guard, and the position-less enqueued verdict
requestedLabels' protected-label refusal is gated on cmd.prefix === '':
only the bare /label and /remove-label commands refuse lgtm, hold,
approved, the do-not-merge/ family and hold.label. A configured
do-not-merge section — whose values become exactly the labels that guard
refuses — labels through its own /do-not-merge command. No test drove
such a section, so Stryker's `cmd.prefix === '' → true` mutant at
src/labels/prefixed.ts:254 survived: under it every /do-not-merge value
is refused as 'managed by its own command'. The new file drives the add,
default-hold-label and remove forms, and keeps /label's refusal as the
control.
evaluateInQueue returns { result: 'enqueued' } without a position key
when the queue reports no entry; the test asserted it with toEqual,
which treats a missing key and an undefined one alike, so the
`outcome.position === undefined → false` mutant at
src/plugins/tide.ts:332 survived. toStrictEqual pins the key's absence.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 |
There was a problem hiding this comment.
Verified against the tree at merge-base and by hand-applying both mutants on the PR head — this looks correct to me.
src/labels/prefixed.ts:254— confirmedif (cmd.prefix === '') {scopes the protected-label refusal to bare/label//remove-label; a configureddo-not-merge:section's labels (do-not-merge/<value>) are exactly whatisProtectedLabel(prefixed.ts:51-56,protectedPrefixes = ['do-not-merge/']at :41) refuses by prefix, so no prior test exercised that section's own command surviving the guard. Applied the mutant (true): the two new positive tests in__tests__/label/dynamicProtectedPrefix.test.tsfail (POST/DELETE never happen,setFailedfires), killing it.src/plugins/tide.ts:332— confirmed the mechanism:src/utils/mergeQueue.ts:124maps a nullmergeQueueEntrytoposition === undefined, so under the mutant (false) the return is{ result: 'enqueued', position: undefined }, whichtoEqualaccepts andtoStrictEqualrejects. Applied the mutant: the changed assertion at__tests__/plugins/tideMergeQueue.test.ts:102fails, killing it. The neighbouring line-331 info mutant was already killed by the existingexpect(info).toHaveBeenCalledWith('enqueued pr #1'), so 332 was indeed the survivor.
Both touched test files pass on the head (39 tests). CI is green; test-only change, disjoint from #591/#593/#595/#596 as claimed.
One small body inaccuracy, no action needed: the body says under the prefixed.ts mutant "all three fail" — the /label do-not-merge/work-in-progress control still passes under it (the mutant widens the guard, and the control expects refusal), so 2 of 3 fail. The mutant is killed either way.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88
|
/kind cleanup 🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88 |
jeefy
left a comment
There was a problem hiding this comment.
Two additive pins; the do-not-merge section's own command past the /label protected guard is a real gap worth having pinned.
|
/kind cleanup |
Test Improvement
Two Stryker survivors with an observable effect, from a fresh probe over
src/plugins/tide.ts,src/labels/prefixed.ts,src/issueComment/trigger.tsandsrc/labels/fixed.tsat9acb046(1124 mutants, each survivor hand-applied at its exact column span before being called a finding):src/labels/prefixed.ts:254cmd.prefix === ''→true.requestedLabelsapplies the protected-label refusal to the bare/labeland/remove-labelcommands only; a configureddo-not-mergelabel section — whose values become exactly the labels that guard refuses by prefix — labels through its own/do-not-merge <value>command. No test drove such a section. New file__tests__/label/dynamicProtectedPrefix.test.tsdrives/do-not-merge work-in-progress(POST) and/remove-do-not-merge work-in-progress(DELETE) and keeps/label do-not-merge/work-in-progressas the refused control. Under the mutant all three fail.src/plugins/tide.ts:332outcome.position === undefined→false.evaluateInQueuereturns{ result: 'enqueued' }with nopositionkey when the queue reports no entry;__tests__/plugins/tideMergeQueue.test.ts:102asserted it withtoEqual, which treats a missing key andposition: undefinedalike. NowtoStrictEqual. Under the mutant the test fails.Reviewed and left alone (equivalent, or in
docs/contributing.md's reviewed classes): every{ required: true }/ payload?./present.length === 0mutant;prefixed.ts:54some→every(one protected prefix);trigger.ts:40/44(an in-progress run carries no conclusion);trigger.ts:255count++→count--(only=== 0is read);tide.ts:233/320/323/455/472/515/564(debug-only or unreachable).fixed.ts:23is reported Survived but crashes module load, so Vitest runs 0 tests and the vitest-runner counts the empty run as a survival — a runner artifact.Files:
__tests__/label/dynamicProtectedPrefix.test.ts(new),__tests__/plugins/tideMergeQueue.test.ts(one assertion). Disjoint from #591, #593, #595 and #596.npm run test:coverage: 192 files, 2477 passed, thresholds met;eslintclean.Related Issue
Refs #594 (needs-human: the finding was folded onto the scheduled-Stryker gate proposal, which stays open for the maintainers' accept/decline decision; this PR lands the two survivor pins and leaves nothing else of the folded finding behind)
Filed by quality agent (hold-gated mode). Human review required.
— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88