Skip to content

test(adapters/app): pin receiveWebhook's refusal texts and header guard, dedupe's capacity boundary and settings' unset-input omission (webhook.ts:35-56, dedupe.ts:15, settings.ts:37) - #612

Merged
jeefy merged 1 commit into
mainfrom
quality/test-app-adapter-guards
Oct 29, 2026
Merged

jeefy merged 1 commit into
mainfrom
quality/test-app-adapter-guards

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Test Improvement

One new file, __tests__/adapters/app/webhookGuards.test.ts (11 cases), for the GitHub App adapter #608 added. Nothing under src/, dist/, config or docs is touched.

Why. The adapter landed at 100 % unit lines, but a Stryker pass over src/adapters/app/{dedupe,scope,settings,webhook}.ts at main@282b8e0 (npx stryker run with a config that only widens mutate; perTest, vitest.mutation.config.mjs) scored 81.08 % — 21 of 111 mutants survived. Four of them change behaviour:

  • webhook.ts:35 — !id || !eventName → &&: a delivery carrying only one of the two headers went on to signature verification instead of being refused. The existing case removes both headers, where || and && agree.
  • webhook.ts:48 — the JSON-parse catch body removed: the 400 body is not json is lost and the request falls through to appPlatform, which happens to throw a different 400.
  • dedupe.ts:15 — ids.size > capacity → >=: the store forgets an id at exactly capacity. The existing case fills past capacity, where both comparisons evict.
  • settings.ts:37 — value !== undefined guard → true: unset inputs become explicit undefined keys; toEqual({}) cannot see them, toStrictEqual can.

The other 17 are response bodies and log lines nobody read (missing delivery headers, bad signature, body is not json, pong, already handled, accepted; the warning/info sink lines for a bad signature and a duplicate). The new file reads each of them once, checks that the header and signature refusals neither read the body (Request.bodyUsed) nor touch the delivery store, and that a malformed body leaves its delivery id unconsumed so a corrected redelivery is still handled.

Re-run: 95.50 %, dedupe.ts / scope.ts / settings.ts at 100 %. The five that remain are two equivalent mutants (new Response(…, {}) defaults to 200) and the three on webhook.ts:65-66, which #611 claims — left alone.

Files / cluster claimed — __tests__/adapters/app/webhookGuards.test.ts; src/adapters/app/dedupe.ts:15, settings.ts:37, webhook.ts:35-56,79. Disjoint from every held PR: #609 (src/platform/index.ts), #611 (src/server/**, webhook.ts:65, its own webhookNonErrorThrow.test.ts), #591/#593/#595/#597/#598/#599/#601/#603/#605 (plugins, dispatcher, labels, config, harness, typecheck, coverage hints, runtime). The bad-signature log line this file asserts in-process is the same text #611's dist-server bundle test looks for on stdout — different level, different file, and the unit assertion is what makes the Stryker mutant on line 40 die.

No issue is filed for this: the repository's mutation-gate proposal (#594) is still awaiting a decision, and this is another instance of the class it covers.

Testing


Filed by quality agent (hold-gated mode). Human review required.

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

…rd, dedupe's capacity boundary and settings' unset-input omission

Stryker over src/adapters/app/{dedupe,scope,settings,webhook}.ts at 282b8e0
scored 81.08% with 21 survivors; this file kills 16 of them. The behavioural
ones: the header guard's || (a delivery with one of the two headers reached
signature verification under &&), the JSON-parse catch body, the capacity
comparison in memoryDeliveryStore (>= would forget an id at exactly
capacity) and settingsFromEnv's value !== undefined guard (toEqual treats an
explicit undefined key as absent). The rest are the response bodies and the
duplicate/bad-signature log lines that no test read.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com>
@hivecommons-hive hivecommons-hive Bot added the hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 29, 2026
@hivecommons-hive
hivecommons-hive Bot requested a review from jpmcb as a code owner October 29, 2026 06:38
@hivecommons-hive

Copy link
Copy Markdown
Contributor Author

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 outreach PR that targets a repository this hive does not manage is held at every level because it publishes project-facing communication into someone else's project.

Hive will keep the hold label until a human removes it. Operators can make a deliberate one-off release during an ACMM level change with release_level_holds=true, but level changes never release this hold automatically.

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the diff against the tree at pr612 (0dcaa75), not just the patch. Test-only change — one new file, nothing under src/ — and the claimed mutant kills hold up:

  • Header guard (src/adapters/app/webhook.ts:35): I applied the ||→&& mutant locally and ran the new file — the two it.each cases fail (a one-header delivery passes a valid signature and returns 202, not the asserted 400). Verified kill.
  • Dedupe boundary (src/adapters/app/dedupe.ts:15, eviction at webhook.ts-adjacent ids.size > capacity): memoryDeliveryStore(2) with exactly 2 ids distinguishes > from >= — under the mutant, a is evicted and seen('a') returns false. Verified by reading dedupe.ts:91-99.
  • JSON-parse catch (webhook.ts:48-49): the redelivery case is the sharp part — with the catch body removed, the malformed delivery's id would be consumed by deliveries.seen at line 54, so asserting the corrected redelivery is dispatched (not already handled) kills it. Correct by trace.
  • settings guard (src/adapters/app/settings.ts:139): toStrictEqual + Object.keys does distinguish explicit-undefined keys that toEqual cannot; the empty-string case pins the !== undefined (vs truthy) choice.

Helpers (__tests__/adapters/app/testApp.ts) are reused, not duplicated; the file set is disjoint from the held PRs it names (#611's new file is webhookNonErrorThrow.test.ts, different file, and webhook.ts:65-66 mutants are deliberately left to it). Full adapter suite: 4 files, 42 passed locally; CI green including e2e-coverage and DCO.

This looks correct to me. (I don't approve — a maintainer's signature is theirs — but I found nothing to change.)

— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88

@jeefy jeefy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eleven guard cases for the App adapter from #608. Reviewed the four behavioural mutants described; the || vs && header guard and the JSON-parse catch are exactly the arms I'd want pinned.

@jeefy jeefy removed the hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 29, 2026
@jeefy

jeefy commented Oct 29, 2026

Copy link
Copy Markdown
Member

/kind cleanup

@jeefy
jeefy merged commit a558ff2 into main Oct 29, 2026
18 checks passed
@jeefy
jeefy deleted the quality/test-app-adapter-guards branch October 29, 2026 15:36
@github-actions github-actions Bot added kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. and removed needs-kind labels Oct 29, 2026
jeefy added a commit that referenced this pull request Oct 29, 2026
…ty dry-run (#616)

#612 was written against 282b8e0, before settingsFromEnv defaulted jobs to
lgtm (#614); merged as-is it fails main's build-test.

Signed-off-by: Jeffrey Sica <me@jeefy.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant