Skip to content

[quality] coverage-e2e names tide.ts:99 uncovered; the zero is the never-reached options.initial ?? await getPull fallback on line 98 #466

Description

@hivecommons-hive

Finding

npm run test:coverage:e2e (main @ 7f01721, local run) reports src/plugins/tide.ts as 99.56% Stmts / 93.98% Branch, with line 99 (for (const delay of unknownRetryDelaysMs)) listed as uncovered. That line is not uncovered: in the same coverage-e2e/lcov.info the loop body executes (DA:100,65).

What the zero really is: the ?? await getPull(...) fallback on line 98

let pr = options.initial ?? await getPull(octokit, context, number)

Both fetchMergeability call sites (evaluateMerge, tide.ts:198-201, and evaluateInQueue, tide.ts:307-310) pass initial: first, so the right-hand side never runs from dist/index.js:

coverage-e2e/lcov.info  SF:src/plugins/tide.ts
DA:98,60   BRDA:98,0,0,60   BRDA:98,0,1,0   DA:99,0   DA:100,65

V8/istanbul attributes that zero-count ?? range to the following line, which is why the report names 99. The unit run shows the same attribution (coverage/lcov.info: BRDA:98,0,1,7 and DA:99,7 while DA:100,135); it just is not visible there because the unit suite does call fetchMergeability without initial. Of the 52 for … of headers in src/, this is the only one the e2e report zeroes.

Only the unit tests exercise the fallback. It is the same shape as the arms #462 removed for #458 (retryIf default in this very function), and was not in that list.

Recommendation

Follow #462: make initial required in FetchMergeabilityOptions and drop the ?? await getPull(...) fallback (plus the unit cases that only reach it); rebuild dist/. After that, tide.ts no longer appears in the e2e "Uncovered Line #s" column for this reason, and the report stops pointing at a line that does run.

  • FetchMergeabilityOptions.initial required; line-98 fallback removed; dist/ repacked
  • npm run test:coverage:e2e no longer lists tide.ts:99

This is a production-code change, so no PR accompanies this issue. The related e2e-only behaviour gap in the same function (the !retryIf(pr) short-circuit never reached end-to-end) is covered by #465.

Priority

  • Impact: low
  • Effort: low

Filed by quality agent (hold-gated mode)


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

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

Activity

  1. added
    qualityCreated by Hive for agent-filed issue provenance
    testingCreated by Hive for agent-filed issue provenance
    agent/qualityCreated by Hive for agent-filed issue provenance
    on Oct 13, 2026
  2. github-actions commented on Oct 13, 2026

    @github-actions
    Contributor

    Please add a kind label with /kind failing-test or /kind cleanup.

  3. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: isOwnReview's user-token arm (approveReview.ts:63, login === identity.login) never reached from dist/index.js

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run) leaves one arm of isOwnReview in src/plugins/approveReview.ts unreached end-to-end:

    return identity.login === undefined ? isBotUser(review.user) : login === identity.login   // :63

    coverage-e2e/lcov.info for SF:src/plugins/approveReview.ts: BRDA:63,5,0,9 BRDA:63,5,1,0 — the installation-token fallback (isBotUser) is taken 9×, the user-token comparison 0×. DA:35,1 shows GET /user succeeds in exactly one bundle run (approveReview.test.ts → "does not even try when the token is a user who opened the pull request"), and that run routes no reviews, so isOwnReview is never called with a marker review under an identified token. The unit suite does reach the arm (coverage/lcov.info: BRDA:63,5,1,4).

    The docstring of syncApprovalReview promises "Reviews without the marker, or by anyone else, are never touched"; for a PAT/user token "anyone else" is decided by this login comparison, and nothing exercises that through dist/index.js: whether an existing marker review by the token's own login suppresses resubmission, whether a bot's marker review is (correctly) not treated as own once the token has a login, and whether /approve cancel dismisses only the login-matching review.

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines, approveReview.ts 100% branch. E2E evidence: npm run test:coverage:e2e on the same revision — approveReview.ts 90.38% branch, arm above at 0. Both from a local run on the same checkout; lcov raw data read directly (not the table summary).

    Recommendation

    Add a bundle scenario file routing GET /user → 200 { login } with marker-bearing APPROVED reviews present, asserting:

    • own review (author = token login, different case) on the head sha → no POST /pulls/1/reviews, already carries the approval review debug
    • marker review by github-actions[bot] under the user token → not own; a fresh review is submitted
    • /approve cancel with both present → PUT …/reviews/<own>/dismissals only

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  4. added
    🐝 covered by PRHive verified that an open PR references or claims this issue; still actionable until confirmed
    on Oct 13, 2026
  5. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: approve.ignore_review_state is never set in any bundle scenario (approve.ts:380-381 arms at 0 from dist/index.js)

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run) shows that no bundle scenario ever sets approve.ignore_review_state: true. In coverage-e2e/lcov.info for SF:src/plugins/approve.ts:

    BRDA:380,55,0,0   BRDA:380,55,1,45   # settings.ignore_review_state && identity === undefined ? [] : await listReviews(...)
    BRDA:381,57,0,0   BRDA:381,57,1,44   # approvalEvents(comments, settings.ignore_review_state ? [] : reviews, ...)
    

    The true arms of both ternaries are taken 0× end-to-end; grep -rn ignore_review_state __tests__/bundle finds nothing. The unit suite reaches them (coverage/lcov.info: BRDA:380,55,0,2, BRDA:381,57,0,3).

    docs/configuration.md:343 and docs/commands.md:214-215 document the option: with it set, APPROVED reviews add nobody and CHANGES_REQUESTED reviews remove nobody, and docs/commands.md:298 promises that without github_review the reviews are not read at all. None of those three promises is exercised through dist/index.js.

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines, approve.ts 100% branch. E2E evidence: npm run test:coverage:e2e on the same revision — approve.ts 93.25% branch, the two arms above at 0. Both from a local run on the same checkout; lcov raw data read directly.

    Recommendation

    Add a bundle scenario file with approve:\n ignore_review_state: true in prow.yaml, asserting through dist/index.js:

    • an APPROVED review by a listed approver → #1 is not approved, no approved label, and no GET /pulls/1/reviews at all
    • /approve followed by a CHANGES_REQUESTED review → #1 is approved by bob, approved added, no DELETE
    • with github_review: true as well (GET /user → 403) → reviews are read for the mirror, still count for nobody, no POST /pulls/1/reviews

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  6. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Two more findings folded here by the dist/index.js consolidation, both from npm run test:coverage:e2e on main@7f01721:

    1. approve.ignore_review_state never set in any bundle scenario — src/plugins/approve.ts BRDA:380,55,0,0 / BRDA:381,57,0,0. The documented behaviour (docs/commands.md:214-215,298) is unit-tested only. A hold-gated PR adding __tests__/bundle/approveIgnoreReviewState.test.ts (3 scenarios) is open; see the linked PR.

    2. effectiveKind's 'ignore' arms at approve.ts:228,230 are unreachable from dist/index.js — same shape as the arms #462 dropped for #458. With the setting on, line 381 already passes [] as the review list to approvalEvents, so no review-approved / review-changes event can ever exist when settings.ignore_review_state is true. computeApproval has one production caller (approve.ts:382). Even with the new scenario file both arms stay at BRDA:228,33,0,0 / BRDA:230,34,0,0. Production-code cleanup (drop the ternaries to plain 'add' / 'remove', repack dist/), so no PR from this lane:

    • effectiveKind review-approved → 'add', review-changes → 'remove' unconditionally; the unit cases reaching only the 'ignore' arms removed; dist/ repacked

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

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

  7. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: approvalEvents' non-APPROVED/CHANGES_REQUESTED review arm (approve.ts:125) never reached from dist/index.js

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run) leaves the fall-through arm of approvalEvents' review-state switch in src/plugins/approve.ts unreached end-to-end:

    if (review.state === 'APPROVED') {            // :122
      events.push({ user: login, kind: 'review-approved', at })
    }
    else if (review.state === 'CHANGES_REQUESTED') { // :125
      events.push({ user: login, kind: 'review-changes', at })
    }

    coverage-e2e/lcov.info for SF:src/plugins/approve.ts: BRDA:125,15,0,1 BRDA:125,15,1,0 — CHANGES_REQUESTED is taken once, the else-arm (any other state: COMMENTED, DISMISSED, PENDING) never. The bundle suite does list COMMENTED/DISMISSED reviews (bundle.test.ts:718, approveMembershipArms.test.ts:83-84, approveReviewShortCircuits.test.ts:91, sweepArms.test.ts:142), but each is either the bot's review or has no submitted_at, so it is dropped by the guard on line 118 before the switch. The unit suite reaches the arm (coverage/lcov.info: BRDA:125,15,1,>0; approve.ts 100% lines, 98.87% branch there).

    docs/automatic-merging.md:398 documents the contract: "GitHub reviews | APPROVED adds an approver, CHANGES_REQUESTED removes one". That a human's COMMENTED review adds nobody, and that a DISMISSED review (a dismissed approval or a dismissed changes-request) neither adds nor withdraws, is exercised only by unit tests.

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines / 99.69% branch overall. E2E evidence: npm run test:coverage:e2e on the same revision — approve.ts 93.25% branch, arm above at 0. Both from a local run on the same checkout; lcov raw data read directly (not the table summary).

    Recommendation

    Add a bundle scenario file on a pull_request_review event with human reviews carrying submitted_at, asserting through dist/index.js:

    • a COMMENTED review by the covering approver → #1 is not approved; nobody approves sdk/x.go, no approved label, notifier NOT APPROVED
    • a DISMISSED review by the covering approver → same: a dismissed approval is no approval
    • /approve followed by COMMENTED and DISMISSED reviews → #1 is approved by bob, approved kept, no DELETE (contrast with the existing CHANGES_REQUESTED scenario in bundle.test.ts:1748)

    Disjoint from #465 (tide.ts retryIf), #467 (approveReview.ts:63) and #468 (approve.ts:380-381, ignore_review_state, which passes [] to approvalEvents and so cannot reach this arm).

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  8. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: canonicalCommand's dynamic remove-form arm (handleIssueComment.ts:91, e.g. /remove-triage) never reached from dist/index.js

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run) leaves the dynamic arm of canonicalCommand in src/issueComment/handleIssueComment.ts unreached end-to-end:

    const base = name.replace(/^\/remove-/, '/')
    return base !== name && isDynamicLabelCommand(base) ? base : name   // :91

    coverage-e2e/lcov.info for SF:src/issueComment/handleIssueComment.ts: BRDA:91,3,0,0 BRDA:91,4,1,0 — the base consequent is taken 0×, and isDynamicLabelCommand(base) is never even evaluated, so no bundle run ever lists a dynamic section's remove form (such as /remove-triage) in prow-commands. The only canonicalization scenario (commandCanonicalization.test.ts) uses /remove-help, which resolves through the alias table on line 84 before reaching line 90. The unit suite does reach the arm (coverage/lcov.info: BRDA:91,3,0,>0).

    docs/commands.md:14-15 and :75 document the contract: listing an alias enables the whole family, any other lower-case slash-key is a label command backed by the matching config section, and its remove form is enabled together with its base. Through dist/index.js nothing checks that configuring only /remove-triage enables /triage, that /remove-triage and /triage listed together collapse to one run, or what a remove form with no matching section does.

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines, handleIssueComment.ts 100% branch. E2E evidence: npm run test:coverage:e2e on the same revision — handleIssueComment.ts 94.54% branch, the two arms above at 0. Both from a local run on the same checkout; lcov raw data read directly (not the table summary).

    Recommendation

    Add a bundle scenario file with a labels: triage: values: [accepted] section in .github/prow.yaml, asserting through dist/index.js:

    • prow-commands: /remove-triage + comment /triage accepted → POST /issues/1/labels { labels: ['triage/accepted'] }
    • prow-commands: /remove-triage + comment /remove-triage accepted → DELETE /issues/1/labels/triage%2Faccepted, no POST
    • prow-commands: /remove-triage /triage → duplicates collapse: exactly one label write
    • prow-commands: /remove-nosuch with no nosuch section → canonicalized to /nosuch, fails with nosuch: yaml malformed, expected 'nosuch' top level key

    Disjoint from #465 (tide.ts retryIf), #466 (tide.ts:98), #467 (approveReview.ts:63), #468 (approve.ts:380-381) and #469 (approve.ts:125): none touch handleIssueComment.ts.

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  9. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: merge-queue answers without an entry, enqueuer or error message (tide.ts:329-330,361; mergeQueue.ts:105,123,184) never driven from dist/index.js

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run, coverage-e2e/lcov.info read directly — re-run with the heads of held PRs #465/#467/#468/#469/#470 merged in, so none of these arms is already claimed) leaves the merge-queue answers the shared fixture never gives unreached from dist/index.js:

    SF:src/utils/mergeQueue.ts
    BRDA:105,3,0,0   # entry.enqueuer === null  → no `enqueuer` on the queue state
    BRDA:123,4,0,0   # enqueuePullRequest answered with mergeQueueEntry: null → { ok: true } without position
    BRDA:184,12,1,0  # GraphQL `errors: []` → falls through to the client's own message
    SF:src/plugins/tide.ts
    BRDA:329,44,0,0  # `enqueued pr #n` logged without ` (position P)`
    BRDA:330,45,0,0  # { result: 'enqueued' } without position
    BRDA:361,52,1,0  # `was enqueued by an unknown actor; leaving it in the queue`
    

    The cause is in the fixture, not the scenarios: __tests__/bundle/fakeGithub.ts mergeQueueRoute always answers the enqueue mutation with { state: 'QUEUED', position: 1 } and always wraps entry.enqueuer in { login }, so every bundle run sees a position and a named enqueuer. The unit suite reaches all six arms (coverage/lcov.info: BRDA:105,3,0,2, BRDA:123,4,0,3, BRDA:184,12,1,1, tide BRDA:329,44,0,>0).

    docs/automatic-merging.md:240 documents enqueued pr #<n> (position P) and :268 the rule "only the bot's own entry (enqueuer is github-actions or ends with [bot])" is ever dequeued. What happens when GitHub answers without an entry or without an enqueuer — the position is omitted rather than printed as undefined, and an entry with no enqueuer is treated as not-ours and left alone — is exercised only by unit tests.

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines / 99.69% branch, all six arms >0. E2E evidence: npm run test:coverage:e2e on the same revision plus the five held heads — mergeQueue.ts 86.66% branch, tide.ts 93.98% branch, the six arms above at 0. Both local runs on the same checkout.

    Not claimed: mergeQueue.ts:188 arm 1 (a non-Error thrown by octokit.graphql) — @octokit/graphql only throws Error subclasses, so it is defensive and stays at 0.

    Recommendation

    Add a bundle scenario file routing POST /graphql by operation (as mergeQueueArms.test.ts already does for its HTTP-500 case), asserting through dist/index.js:

    • enqueue answered with mergeQueueEntry: null → exit 0, stdout enqueued pr #1 with no (position, no PUT …/merge
    • pull_request unlabeled lgtm with isInMergeQueue: true and mergeQueueEntry.enqueuer: null → ::debug::pr #1 was enqueued by an unknown actor; leaving it in the queue, no dequeuePullRequest
    • enqueue answered with data: null, errors: [] → exit 1, could not enqueue pr #1: Request failed due to following response errors:

    Disjoint from #465 (tideVerdictArms.test.ts, retryIf), #467, #468, #469 (approve*) and #470 (handleIssueComment.ts): none touch the GraphQL merge-queue path.

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  10. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: suggestApprovers' second greedy round (approve.ts:260) never reached from dist/index.js — the notifier never suggests two approvers end-to-end

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run, with the heads of held PRs #465/#467/#468/#469/#470/#471 merged in so none of their ground is counted) leaves the greedy set cover in suggestApprovers (src/plugins/approve.ts) one-round-only end-to-end.

    coverage-e2e/lcov.info for SF:src/plugins/approve.ts:

    DA:256,24                 # 24 greedy rounds across 53 notifier evaluations
    BRDA:260,42,0,30  BRDA:260,42,1,0   # owners.perFile.get(file)?.approvers.has(best): true 30×, false 0×
    

    In every round the chosen best covered every remaining file, so the remaining set always emptied after round one. No bundle scenario ever produces state.suggested with more than one login: every please assign assertion in __tests__/bundle/ names exactly one (**alice**, **bob**, **carol**), and nothing asserts the /assign @x @y form.

    The notifier's contract (renderNotifier, approve.ts:296-300) is that a pull request spanning directories with disjoint approvers gets all of them listed — please assign **bob**, **carol** and /assign @bob @carol — with the most-covering approver first and ties broken alphabetically. That is unit-tested (__tests__/plugins/approve.test.ts:160 "suggests approvers greedily…") but never observed through dist/index.js.

    Unit evidence: npx vitest run --coverage on main@7f01721 — approve.ts 100% lines / 100% branch. E2E evidence: npm run test:coverage:e2e on the same revision (+ held heads above) — arm above at 0. Both local runs on the same checkout; lcov raw data read directly (not the table summary, which ncc's column-less source map can misreport — #424).

    Recommendation

    Add a bundle scenario file __tests__/bundle/approveSuggestionArms.test.ts asserting through dist/index.js on a pull_request_review event:

    • root OWNERS with reviewers only, sdk/OWNERS: [bob], olm/OWNERS: [carol], files in both → please assign **bob**, **carol**, /assign @bob @carol, both OWNERS files bold in the details list
    • a/[x,y], b/[y,z], c/[z] (all no_parent_owners) → please assign **y**, **z**, /assign @y @z, x never suggested

    Disjoint from #465 (tide.ts retryIf), #466 (tide.ts:98), #467 (approveReview.ts:63), #468 (approve.ts:380-381, ignore_review_state), #469 (approve.ts:125, review-state arm), #470 (handleIssueComment.ts:91) and #471 (merge-queue nulls): none touch suggestApprovers or assert a multi-login suggestion.

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  11. hivecommons-hive commented on Oct 13, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 63 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-e2e: tide.labels is never configured in any bundle scenario (tide.ts:542 probe-skip arm at 0 from dist/index.js)

    Finding

    npm run test:coverage:e2e (main @ 7f01721, local run) shows that no bundle scenario ever configures a valid tide.labels list. In coverage-e2e/lcov.info for SF:src/plugins/tide.ts:

    BRDA:542,83,0,367   BRDA:542,83,1,0    # if (config.tide.labels === undefined) { hasOwners = … probe … }
    

    loadTide takes the "labels undefined → probe the base branch for OWNERS" arm 367× and the "labels configured → skip the probe" arm 0×. grep -rn 'labels:' __tests__/bundle under a tide: key finds only configSchemaArms.test.ts:57, which is the schema-error case ([lgtm, ""]) and throws before loadTide runs. Consequently meetsMergeGate's missing <pattern> reason is reached end-to-end only from the default [lgtm] / [lgtm, approved] lists, never from a configured pattern (wildcard, mixed case). The unit suite reaches the arm (coverage/lcov.info: BRDA:542,83,1,4; __tests__/plugins/tide.test.ts:840 routes tide:\n labels: [lgtm] with an OWNERS tree and asserts it is not read).

    docs/automatic-merging.md:317-340 documents three promises for a configured list, none exercised through dist/index.js: every entry "must be present"; "A configured list replaces the default list, it does not extend it"; and the OWNERS tree listing is "skipped entirely when tide.labels is configured".

    Unit evidence: npx vitest run --coverage on main@7f01721 — 100% lines / 99.69% branch, tide.ts 100% branch at line 542. E2E evidence: npm run test:coverage:e2e on the same revision — tide.ts 93.98% branch, arm above at 0. Both from a local run on the same checkout; lcov raw data read directly (not the table summary).

    Disjoint from #465 (tide.ts retryIf short-circuit, tideVerdictArms.test.ts), #466 (tide.ts:98 initial fallback, production change), #471 (merge-queue nulls, mergeQueueNullArms.test.ts) and the approve*/handleIssueComment clusters (#467–#470, #472): none configure tide.labels or assert on the OWNERS probe being skipped.

    Recommendation

    Add a bundle scenario file on a pull_request labeled event with tide:\n labels: […] in prow.yaml, asserting through dist/index.js:

    • labels: [lgtm, approved] on a PR carrying only lgtm → skipping pr #1: missing approved, no PUT, and no GET /git/trees/master?recursive=true
    • labels: [lgtm] on a base whose tree carries a root OWNERS → merged pr #1 and the tree is never read (the list replaces the [lgtm, approved] default)
    • labels: [LGTM, "size/*"] on a PR with lgtm + size/M → merges (case-insensitive, * spans /); [lgtm, "size/*"] on a PR with only lgtm → skipping pr #1: missing size/*

    Priority

    • Impact: medium (covered by unit tests, not end-to-end)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  12. 70 remaining items

  13. hivecommons-hive commented on Oct 16, 2026

    @hivecommons-hive
    ContributorAuthor

    Reopened by a person after #496 merged. Hive will not close this issue for #496 again; close it by hand or with a new PR.

  14. hivecommons-hive commented on Oct 16, 2026

    @hivecommons-hive
    ContributorAuthor

    🛠️ Hive agent quality (hive hosted-available-lke648397-260827-5q9t) started work on this issue at 2026-10-16T19:45:37Z. A pull request referencing this issue supersedes this mark; it lapses on its own at 2026-10-16T21:45:37Z if none appears.

  15. hivecommons-hive commented on Oct 16, 2026

    @hivecommons-hive
    ContributorAuthor

    Status check against the four items left open in the reopen comment, measured on main @ 1062ce7 (npm ci && npm run test:coverage:e2e, local run, 78 files / 487 tests passed; raw data read from coverage-e2e/lcov.info):

    • owners.ts:127-147 — expandGroups team arms already landed. The merged feat(owners): support GitHub groups in OWNERS #486 ships __tests__/bundle/ownersGroups.test.ts (4 scenarios: team-only reviewer authorized with the team read once + other-org/malformed warnings, root-OWNERS team on an issue, direct login next to a team without a team read, unreadable team refused with one warning). src/utils/owners.ts now reads 100 / 100 / 100 / 100 in the e2e report; lcov.info has no DA:…,0 or BRDA:…,0 under SF:src/utils/owners.ts. The folded finding was measured on the PR head 05f387b, before that file was added. No further test work remains for this item.
    • approve.ts:228,230 — still BRDA:228,33,0,0 / BRDA:230,34,0,0 (effectiveKind's 'ignore' arms for review-approved / review-changes).
    • approve.ts:415 — still BRDA:415,69,1,0 (existing.body ?? '' in upsertNotifier; existing is found via (comment.body ?? '').includes(notifierMarker), so body is never nullish there).
    • meow.ts:88 — still BRDA:88,8,1,0 (response.status || 'a redirect').

    The three remaining items are production-code removals (same shape as #462 for #458), so the quality lane does not open a PR for them — they need a maintainer or a lane permitted to change src/ and repack dist/. The tracker stays open for those three.


    Posted by quality agent (hold-gated mode)


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

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

  16. hivecommons-hive commented on Oct 16, 2026

    @hivecommons-hive
    ContributorAuthor

    Verification on main@1062ce7 (after #492 and #496 merged), local run, coverage-e2e/lcov.info read directly:

    Box 1 — initial required, line-98 fallback removed, dist/ repacked: landed by #492 (merged 2026-10-16T18:37Z, 1062ce7). src/plugins/tide.ts:60 is now initial: Mergeability (no ?), and tide.ts:98 reads let pr = options.initial — grep -n getPull src/plugins/tide.ts has no hit inside fetchMergeability.

    Box 2 — npm run test:coverage:e2e no longer lists tide.ts:99:

    $ npm run test:coverage:e2e        # 78 files / 487 tests passed
    tide.ts | 100 | 97.79 | 100 | 100 | 137-138,258,426
    
    coverage-e2e/lcov.info  SF:src/plugins/tide.ts
    DA:98,67   DA:99,67   DA:100,74      # loop header now counted; no BRDA on line 98 at all
    

    The remaining branch zeros on tide.ts (137-138 non-Error/non-status throw in the merge catch, 258 compared.data.files ?? [], 426 data.draft ?? false) are unrelated defensive arms, not this finding.

    Both deliverables are done on main; nothing further to implement here. The task list is only ticked by a human editing the body, so this stays open until a maintainer ticks both boxes or closes it.


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

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

  17. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Checked both task-list items against current main (1062ce7, which includes #492 and #496), local run:

    Box 1 — FetchMergeabilityOptions.initial required; line-98 fallback removed; dist/ repacked
    src/plugins/tide.ts:60 is now initial: Mergeability (required) and line 98 is let pr = options.initial — no ?? await getPull(...) remains (grep -n getPull src/plugins/tide.ts → lines 105, 180, 420, 438 only). Landed by #492.

    Box 2 — npm run test:coverage:e2e no longer lists tide.ts:99
    npm run test:coverage:e2e on 1062ce7: 78 files / 487 tests pass; tide.ts reports 100 Stmts / 97.79 Branch / 100 Funcs / 100 Lines, Uncovered Line #s 137-138,258,426. In coverage-e2e/lcov.info for SF:src/plugins/tide.ts no DA:<n>,0 entry exists; the only zero arms are BRDA:137, BRDA:138, BRDA:258, BRDA:426 — all ?? null / ?? false / ?? [] defaults on API fields, unrelated to fetchMergeability. Line 99 is no longer named.

    Nothing in this issue's scope is outstanding. Both boxes can be ticked; this is left for a maintainer since only a human edit ticks them.


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

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

  18. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    🛠️ Hive agent quality (hive hosted-available-lke648397-260827-5q9t) started work on this issue at 2026-10-17T02:00:35Z. A pull request referencing this issue supersedes this mark; it lapses on its own at 2026-10-17T04:00:35Z if none appears.

  19. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 41 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] tide/sweep optional-field folds (tide.ts:258,426; sweep.ts:141) only run under the unit suite

    Finding

    Three nullish folds on optional GitHub REST fields are unit-covered but never executed by the bundle e2e suite (npm run test:coverage:e2e, __tests__/bundle driving dist/index.js):

    • src/plugins/tide.ts:258 — explainForkWorkflows: (compared.data.files ?? []) when a compare response omits files
    • src/plugins/tide.ts:426 — getPull: data.draft ?? false when a pull request response omits draft
    • src/cronJobs/sweep.ts:141 — approveIfTrusted: (pr.labels ?? []).some(...) when a listed pull request omits labels

    Every existing bundle case serves those fields populated, so the production shape where GitHub leaves them out (both are optional in the REST schema) is only exercised against unit fixtures.

    Evidence

    • Unit: npm run test:coverage on main @ 1062ce7 — all three branches taken (coverage/lcov.info has no BRDA:…,0 for these lines).
    • E2E: npm run test:coverage:e2e on main @ 1062ce7 — coverage-e2e/lcov.info: SF:src/plugins/tide.ts BRDA:258,27,1,0, BRDA:426,63,1,0; SF:src/cronJobs/sweep.ts BRDA:141,14,1,0. 78 files / 487 tests, Branches 97.96% (1633/1667).

    Recommendation

    Add one bundle test file (__tests__/bundle/tideOptionalFields.test.ts) driving each fold through dist/index.js: a pull_request labeled lgtm whose GET /pulls/1 has no draft; a schedule lgtm fork-403 whose compare has no files; a schedule sweep whose listing item has no labels.

    • tide.ts:258 compare without files
    • tide.ts:426 pull without draft
    • sweep.ts:141 listing without labels

    Disjoint from #497 (approve.ts / meow.ts).

    Priority

    • Impact: medium (unit-covered, e2e-uncovered)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  20. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 41 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] 17 non-Error rejection normalizer arms are unreachable from dist/index.js: drop them or accept as unit-only

    Finding

    After #497 and #498, every remaining branch the bundle e2e suite (npm run test:coverage:e2e, main @ 1062ce7, coverage-e2e/lcov.info) leaves untaken in the error-handling paths is the same shape: the else arm of e instanceof Error ? e.message : String(e) (or 'status' in e / typeof e === 'object') for a rejection that is not an Error:

    • src/run.ts:40
    • src/cronJobs/labelSync.ts:107, src/cronJobs/sweep.ts:132
    • src/issueComment/handleIssueComment.ts:217 (normalizeError), src/issueComment/trigger.ts:323 (statusOf)
    • src/labels/lgtm.ts:68
    • src/plugins/approveReview.ts:226 (errorStatus), :230 (errorMessage), src/plugins/requireMatchingLabel.ts:167, src/plugins/tide.ts:137-138
    • src/utils/auth.ts:14,17,24 (getErrorDetails), src/utils/config.ts:657, src/utils/events.ts:50, src/utils/mergeQueue.ts:190

    Through dist/index.js every rejection these catch comes from Octokit (RequestError, an Error), js-yaml (YAMLException, an Error), or fetch (TypeError). No fake-GitHub response can make the runtime throw a string or a plain object, so no bundle test can take these arms; the unit suite reaches them only by throwing literals directly.

    Evidence

    • Unit: npm run test:coverage main @ 1062ce7 — all arms taken.
    • E2E: npm run test:coverage:e2e main @ 1062ce7 — each of the above appears as BRDA:<line>,…,1,0 in coverage-e2e/lcov.info; src/utils/auth.ts additionally DA:24,0.

    Decision needed

    Same question #466's reopen comment settled for approve.ts/meow.ts, now for the normalizers. Either:

    1. Drop the arms (production change, same shape as refactor: drop defensive arms unreachable from dist/index.js #462/refactor(tide): require fetchMergeability's initial read, drop the unreachable getPull fallback #492/refactor(approve, meow): drop the three dead arms left open on #466 #497): collapse to (e as Error).message / unconditional e.message where the catch only ever sees Octokit errors, and remove the unit cases that throw literals. Reaches 100% e2e branch on these files.
    2. Keep them as unit-only defensive code: mark each with /* v8 ignore next */ in the e2e config (or accept the standing delta) and close this.

    The quality lane only ships test code, so option 1 needs a maintainer or another lane. Reply with /hive decision 1 or /hive decision 2.

    Priority

    • Impact: low (defensive arms, unit-covered)
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

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

  21. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 5 closed as completed in the last 14 days) already cite coverage/lcov.info, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-reporting: unit and e2e lcov carry negative BRDA counts for 4 implicit-else arms after a conditional await (ast-v8-to-istanbul#207); text report names 4 phantom uncovered lines

    Finding

    Both coverage artifacts on main @ 1062ce7 contain negative branch hit counts, which the lcov format does not allow (a BRDA count is a non-negative integer or -):

    # coverage/lcov.info          (npm run test:coverage)
    SF:src/issueComment/close.ts   BRDA:39,3,1,-3
    SF:src/issueComment/reopen.ts  BRDA:36,3,1,-1
    SF:src/plugins/approve.ts      BRDA:503,84,1,-6
    SF:src/utils/auth.ts           BRDA:220,13,1,-51
    
    # coverage-e2e/lcov.info      (npm run test:coverage:e2e)
    SF:src/plugins/approve.ts      BRDA:503,84,1,-26
    SF:src/utils/auth.ts           BRDA:220,13,1,-43
    

    All six are the implicit else of an if whose condition is the result of a conditional await — the exact shape of the open upstream report AriPerkkio/ast-v8-to-istanbul#207 (filed 2026-10-14, reproduced with a raw node:inspector capture, no Vitest involved; we pull ast-v8-to-istanbul@1.0.6 via @vitest/coverage-v8@5.0.3):

    // close.ts:33-39 / reopen.ts:30-36
    const isAuthUser = isAuthor || (await checkCollaborator(…)) || (await closePolicyAllows(…))
    if (isAuthUser) {
    // approve.ts:502-503
    const hasOwners = typeof base === 'string' ? await branchHasOwners(…) : await repoHasOwners(…)
    if (!hasOwners) {
    // auth.ts:216-220
    const hasOwners = context.payload.issue?.pull_request !== undefined ? await assertPullRequestOwner(…) : await assertRootOwner(…)
    if (!hasOwners) {

    The arms are not uncovered. The line after each if block — the first statement of the else path — has a positive DA count in both suites (unit DA:40,12, DA:37,9, DA:504,7, DA:221,94; e2e DA:40,2, DA:37,3, DA:504,29, DA:221,48), and the bundle suite asserts on those paths directly (__tests__/bundle/defaultBranchFallback.test.ts:50 → approve: the base branch has no OWNERS files; __tests__/bundle/triggerTestAndLgtmCancel.test.ts:199 → stranger is not a org member or collaborator). The unit suite has explicit cases for each (close.test.ts:55, reopen.test.ts:55, approveEvents.test.ts:237, auth.test.ts). Re-running vitest run --coverage __tests__/issueCommentTest/close.test.ts alone still yields BRDA:39,3,1,-2, so it is not a worker-merge effect.

    What it does to our numbers

    • The unit text reporter lists close.ts:39, reopen.ts:36, approve.ts:503, auth.ts:220 under "Uncovered Line #s". Only approve.ts:415 is genuinely untaken (that one is refactor(approve, meow): drop the three dead arms left open on #466 #497's).
    • coverage-summary.json → the ### Coverage step summary in test.yml reads 1662/1667 branches (99.7%); the true figure is 1666/1667. The e2e summary reads 1633/1667 (97.96%); true is 1635/1667.
    • The two coverage-* artifacts uploaded by test.yml are not spec-valid lcov, so a strict consumer (Codecov-style parsers, lcov --summary) may reject or misreport them.
    • Nothing fails today: thresholds are 93 / 95 branches.

    No coverage-gap finding is attached to any of these four sites.

    Recommendation

    This is upstream tooling, not something a test or workflow change in this repository can correct, so no PR accompanies this issue.

    Priority

    • Impact: low (reporting accuracy only; no gate affected)
    • Effort: low (dependency bump once upstream lands)

    Filed by quality agent (hold-gated mode)


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

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

  22. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Closing out the e2e-zero catalog on main @ 1062ce7 (npm run test:coverage:e2e, coverage-e2e/lcov.info read directly). After #497, #498 and the normalizer-arms decision above, exactly two zero-count arms were not yet named on this tracker:

    1. src/utils/command.ts:23 — getLineArgs's ?? '' is unreachable from dist/index.js by construction. BRDA:23,0,0,26 BRDA:23,0,1,0 (unit: BRDA:23,0,1,3). Its only callers are milestone.ts:43 and retitle.ts:31, and the dispatcher (handleIssueComment.ts:128) runs either handler only after hasCommand(form, body) — which is findCommandArgs(...).length > 0, the same match getLineArgs performs — returned true. Neither /milestone nor /retitle has an alias in commandAliases, so the form that matched is the one getLineArgs is called with, and .at(-1) is always defined. Same shape as the approve.ts:415 arm #497 drops: production cleanup (findCommandArgs(command, body).at(-1) as string, or make getLineArgs take the already-matched args) plus the unit case that calls it with an absent command; no PR from this lane.

    • getLineArgs ?? '' arm removed, dist/ repacked; BRDA:23 no longer listed under SF:src/utils/command.ts in coverage-e2e/lcov.info

    2. src/issueComment/approve.ts:94 — String(context.payload.issue?.user?.login ?? ''). BRDA:94,6,0,30 BRDA:94,6,1,0 (unit: BRDA:94,6,1,1). A ?? '' on issue.user.login, a field GitHub always sends — the class the d93ecb8 comment above already lists as not worth a scenario. Noted here only so the catalog is complete.

    Separately, the four negative BRDA entries in both lcov files (close.ts:39, reopen.ts:36, approve.ts:503, auth.ts:220) are a reporter artifact (ast-v8-to-istanbul#207), not gaps; filed as its own coverage-reporting issue.


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

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

  23. hivecommons-hive commented on Oct 17, 2026

    @hivecommons-hive
    ContributorAuthor

    Folded finding. This was filed as a separate issue, but 1 open agent-filed issue (plus 41 closed as completed in the last 14 days) already cite dist/index.js, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.

    [quality] coverage-reporting: the e2e regression floor (99/95/98/99) now sits 49 branches and 10 functions under what main reaches

    Finding

    vitest.e2e-coverage.config.mjs gates npm run test:coverage:e2e at 99 / 95 / 98 / 99 (lines / branches / functions / statements). #484 set those "just under what main reaches" when main measured 99.54 / 96.25 / 98.79 / 99.56 (d93ecb8). Since then the bundle scenarios in #467–#496 landed and main now measures:

    metric main @ 1062ce7 floor slack
    lines 99.95 % (2424/2425) 99 23 lines
    statements 99.96 % (2545/2546) 99 24 statements
    functions 100 % (500/500) 98 10 functions
    branches 97.96 % (1633/1667) 95 49 branches

    So a bundle scenario that stops driving up to 49 src/ branches or 10 functions through dist/index.js still passes the e2e run, which is exactly the regression the floor exists to catch. The functions floor in particular was set when six reset*() hooks were unreached; #483 marked those v8 ignore, and the figure has been 100 % since.

    Evidence (both suites run locally at main@1062ce7, Node $(node --version)):

    docs/contributing.md:50 documents the same 99 / 95 / 98 / 99 values and needs the same update.

    Recommendation

    Apply the repository's own rule (#202, #484, #500: a floor just under what main reaches):

    • vitest.e2e-coverage.config.mjs coverage.thresholds: branches: 95 → 97, functions: 98 → 99 (lines/statements stay 99); update the comment to record the figure it was set under
    • docs/contributing.md:50: "Fails below 99 % lines / 97 % branches / 99 % functions / 99 % statements"

    That leaves ~16 branches / ~5 functions of budget for an ncc/vitest bump that shifts source-map attribution, the same margin #484 chose.

    Disjoint from held PR #500 (unit floor, vitest.config.mjs + docs/contributing.md:48): git merge-tree of the two heads merges cleanly.

    Priority

    • Impact: low
    • Effort: low

    Filed by quality agent (hold-gated mode)


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

    — 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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions