Skip to content

fix(review): close two gaps in the per-repo dual-AI combine override - #2695

Merged
JSONbored merged 3 commits into
mainfrom
fix/dual-ai-combine-onmerge-bypass
Jul 3, 2026
Merged

fix(review): close two gaps in the per-repo dual-AI combine override#2695
JSONbored merged 3 commits into
mainfrom
fix/dual-ai-combine-onmerge-bypass

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Two confirmed bugs in the already-merged #2677 (issue #2567):

1. The operator's onMerge floor could be bypassed via unclamped combine/reviewers. Flagged by gittensory's own live AI review on the original PR: resolveEffectiveAiReviewOnMerge clamped onMerge alone, so an operator plan of { combine: "synthesis", onMerge: "either", reviewers: [A, B] } (two reviewers, either one can flag a blocker) could be effectively neutered by a repo override of { combine: "single", reviewers: [A] } — reviewer B's vote never happens, without ever touching onMerge directly.

Added resolveEffectiveAiReviewPlan, which clamps combine/reviewers together with onMerge: when the operator has set an either floor, a repo override that would reduce the effective reviewer count (a shorter reviewers list or a switch to combine: "single") is clamped back to the operator's own values, while onMerge still resolves through the existing resolveEffectiveAiReviewOnMerge.

2. The AI-review cache fingerprint didn't include the new per-repo overrides. Found by an independent adversarial review: aiReviewCacheInputFingerprint's reviewerPlan field only reflects env.AI_REVIEW_PLAN (the operator's boot config) — never aiReviewCombine/aiReviewOnMerge/aiReviewReviewers. Since the actual gate-blocking verdict is directly shaped by these, a same-head-SHA cache hit (a re-delivered webhook or the block-mode re-gate sweep — both normal operational triggers) could replay a stale verdict computed under the old plan after a maintainer changes the override on an already-open PR.

Added the three fields to AiReviewCacheInput/aiReviewCacheInputFingerprint, mirroring exactly how the precedent field aiReviewCloseConfidence is already handled there.

Addresses gate-review findings on #2677.

Test plan

  • npm run typecheck
  • npx vitest run test/unit/ai-review.test.ts test/unit/ai-review-cache-input.test.ts test/unit/ai-review-cache.test.ts test/unit/ai-review-advisory.test.ts test/unit/focus-manifest.test.ts test/unit/queue.test.ts — 732/732 pass, including 7 new tests covering resolveEffectiveAiReviewPlan's clamp/no-clamp cases (no floor, reduced reviewer count, collapse to single, implicit default reviewer count, unaffected tightening, independent onMerge-only clamp) and 1 new test covering the cache fingerprint change for all three new fields

@loopover-orb

loopover-orb Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - fixes required

Review updated: 2026-07-03 07:09:07 UTC

7 files · 1 AI reviewer · 1 blocker · readiness 93/100 · CI failing · blocked

🛑 Suggested Action - Manual Review

  • AI reviewers agree on a likely critical defect: src/services/ai-review.ts:143: `resolveEffectiveAiReviewPlan` computes `collapsesToSingleReviewer` from `repoOverride.combine ?? operatorPlan?.combine`, so an operator-owned plan such as `{ onMerge: "either", combine: "single", reviewers: [A, B] }` returns `clamped: true` with no repo override and increments the clamp metric on every run
  • gate this branch on `repoOverride.combine === "single"` or otherwise require a repo-authored collapse. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
The cache fingerprint wiring correctly adds the repo-level dual-AI knobs, and the queue path now passes those settings into cache identity. The new plan resolver closes the intended shorter-reviewer-list and explicit single-combine bypass, but its clamp detection also fires on the operator's own `combine: "single"` value, which makes the helper report a clamp when no repo override happened.

Blockers

  • src/services/ai-review.ts:143: `resolveEffectiveAiReviewPlan` computes `collapsesToSingleReviewer` from `repoOverride.combine ?? operatorPlan?.combine`, so an operator-owned plan such as `{ onMerge: "either", combine: "single", reviewers: [A, B] }` returns `clamped: true` with no repo override and increments the clamp metric on every run; gate this branch on `repoOverride.combine === "single"` or otherwise require a repo-authored collapse.
Nits — 4 non-blocking
  • src/services/ai-review.ts:145: The reviewer-count clamp only compares length, so a repo can replace the operator's second reviewer with a different reviewer at the same count; either document that identity substitution is intentionally allowed or compare the effective reviewer set when `onMerge` is floored to `either`.
  • test/unit/ai-review.test.ts:1170: Add the regression case where the operator plan itself has `combine: "single"` and no repo combine override, so the helper cannot silently reintroduce the false clamp metric.
  • src/services/ai-review.ts:143: Split the two clamp predicates into `repoReducedReviewers` and `repoCollapsedCombine` so the code mirrors the policy and does not mix operator defaults into repo-bypass detection.
  • test/unit/ai-review.test.ts:1165: Add one integration-level `runGittensoryAiReview` test that verifies a clamped repo override actually runs the operator's two-reviewer path, not just the pure resolver output.

Why this is blocked

  • src/services/ai-review.ts:143: `resolveEffectiveAiReviewPlan` computes `collapsesToSingleReviewer` from `repoOverride.combine ?? operatorPlan?.combine`, so an operator-owned plan such as `{ onMerge: "either", combine: "single", reviewers: [A, B] }` returns `clamped: true` with no repo override and increments the clamp metric on every run; gate this branch on `repoOverride.combine === "single"` or otherwise require a repo-authored collapse.

CI checks failing

  • codecov/patch — 95.45% of diff hit (target 99.00%)
Signal Result Evidence
Code review ❌ 1 blocker 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 61 registered-repo PR(s), 52 merged, 489 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 61 PR(s), 489 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: not available
  • Official Gittensor activity: 61 PR(s), 489 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • No action.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added gittensor gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. labels Jul 3, 2026
@JSONbored
JSONbored force-pushed the fix/dual-ai-combine-onmerge-bypass branch from d40449f to c3d9509 Compare July 3, 2026 06:59
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.13%. Comparing base (a6f4a36) to head (9e30a31).
⚠️ Report is 14 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2695   +/-   ##
=======================================
  Coverage   96.13%   96.13%           
=======================================
  Files         241      241           
  Lines       27033    27048   +15     
  Branches     9822     9832   +10     
=======================================
+ Hits        25988    26003   +15     
  Misses        433      433           
  Partials      612      612           
Files with missing lines Coverage Δ
src/queue/processors.ts 92.70% <ø> (ø)
src/review/ai-review-cache-input.ts 100.00% <100.00%> (ø)
src/services/ai-review.ts 95.50% <100.00%> (+0.13%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

JSONbored added 3 commits July 3, 2026 00:15
The gate's own live AI review flagged that resolveEffectiveAiReviewOnMerge
clamped onMerge alone, but a repo could still neuter an operator's
either-floor by shrinking gate.aiReview.reviewers or switching to
combine: "single" -- either change reduces the number of independent
opinions that can trigger a blocker, the same effective loosening
onMerge clamping alone was meant to prevent. Added
resolveEffectiveAiReviewPlan, which clamps combine/reviewers together
with onMerge whenever the operator has an either floor and a repo
override would reduce the effective reviewer count.

Also closes a cache-staleness gap an independent adversarial review
found: the AI-review result cache's fingerprint never included the new
per-repo aiReviewCombine/aiReviewOnMerge/aiReviewReviewers overrides,
so a same-head-SHA cache hit (a re-delivered webhook or the block-mode
re-gate sweep) could replay a stale verdict computed under the old
plan after a maintainer changed the override on an already-open PR.
…cache fingerprint

The fingerprint collapsed null/undefined/[] to the same value, but
resolveEffectiveAiReviewPlan treats an explicit [] as a real repo
override (falls through to the built-in default reviewers) while
nullish falls through to the operator's own reviewer plan -- a
same-SHA cache hit could replay a verdict produced under the other
effective plan.
…or's own combine value

collapsesToSingleReviewer fell through to the operator's own combine
setting via repoOverride.combine ?? operatorPlan?.combine, so an
operator plan that itself sets combine: "single" reported clamped:
true on every call even with no repo override at all. Now requires
the repo to have actually set combine: "single" itself.

Addresses gate-review findings on #2695.
@JSONbored
JSONbored force-pushed the fix/dual-ai-combine-onmerge-bypass branch from c3d9509 to 9e30a31 Compare July 3, 2026 07:15
@JSONbored

Copy link
Copy Markdown
Owner Author

Fixed the blocker: `collapsesToSingleReviewer` computed its combine value via `repoOverride.combine ?? operatorPlan?.combine`, so an operator plan that itself sets `combine: "single"` (with no repo override at all) fell through to that same value and reported `clamped: true` on every single call, incrementing the clamp metric for no reason — there was nothing for a repo to have bypassed. Now requires `repoOverride.combine === "single"` directly, i.e. an actual repo-authored override.

Added a regression test for the operator's-own-single-combine case (asserts `clamped: false`) and a companion test confirming the reviewer-count clamp still correctly fires when a repo does try to shrink the reviewer list under that same operator plan. Verified by temporarily reverting the fix and confirming the new test fails exactly as expected, then restoring it.

@JSONbored
JSONbored merged commit 2d9e6bd into main Jul 3, 2026
8 checks passed
@JSONbored
JSONbored deleted the fix/dual-ai-combine-onmerge-bypass branch July 3, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Development

Successfully merging this pull request may close these issues.

1 participant