feat(review): gate AI close on a calibrated, configurable confidence threshold - #1599
Merged
Conversation
…threshold Today an AI consensus/split defect carries a hardcoded confidence: 1 and isConfiguredGateBlocker closes on ai_consensus_defect / ai_review_split whenever aiReviewGateMode is block, regardless of how confident the reviewers actually were — a frequent false-close source. Each reviewer now emits a calibrated per-rejection confidence in [0,1] (prompted + parsed, fallback 1.0 when absent/unparseable). A consensus defect carries min(a, b) (only as strong as the weaker reviewer); a single reviewer / split carries that reviewer's confidence. An AI defect now blocks only when aiReviewGateMode is block AND the finding confidence clears a configurable aiReviewCloseConfidence floor (default 0.9, set via .gittensory.yml gate.aiReview.closeConfidence, clamped to [0,1]); below-floor AI defects stay advisory. Advisory-mode-safe: aiReviewGateMode defaults to advisory, so the live posted gate is unchanged — this only affects the block path and the dry-run would-be verdict. A finding with no confidence degrades to 1.0, byte-identical to today.
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1599 +/- ##
=======================================
Coverage 95.50% 95.50%
=======================================
Files 203 203
Lines 21985 22008 +23
Branches 7943 7956 +13
=======================================
+ Hits 20996 21019 +23
Misses 413 413
Partials 576 576
🚀 New features to boost your workflow:
|
This was referenced Jun 27, 2026
Closed
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An AI consensus/split defect today carries a hardcoded
confidence: 1(consensusDefectOf/synthesizeDefect), andisConfiguredGateBlockercloses onai_consensus_defect/ai_review_splitwheneveraiReviewGateMode === "block"— regardless of how confident the reviewers actually were. That is a frequent false-close source: a speculative, low-conviction AI rejection closed PRs just as hard as a certain one.This calibrates the AI signal and gates the block on a configurable floor:
confidencein[0,1](its probability that its blockers are real defects).parseModelReviewparses it with a graceful fallback of 1.0 when absent/unparseable/out-of-range, so behavior degrades to exactly today's.consensusDefectOf(a, b)carriesmin(a.confidence, b.confidence)(a consensus is only as strong as its weaker reviewer);synthesizeDefect([r])/ a split carry that reviewer's confidence. The confidence is threaded onto the producedai_consensus_defect/ai_review_splitadvisory finding (AdvisoryFinding.confidence?).GateCheckPolicy.aiReviewCloseConfidence(default 0.9). The AI branch ofisConfiguredGateBlockernow blocks only whenaiReviewGateMode === "block"ANDfinding.confidence >= (aiReviewCloseConfidence ?? 0.9). Below-threshold AI defects stay advisory (visible, never block). A finding with no confidence is treated as1.0and always clears the floor — byte-identical to today. All other blocker codes are untouched.aiReviewCloseConfidenceresolves from.gittensory.ymlgate.aiReview.closeConfidencethrough the focus manifest into the effective settings, mirroring exactly howslopGateMinScore/qualityGateMinScoreflow (parse + clamp to[0,1]without rounding, serialize/round-trip,resolveEffectiveSettingsoverlay). No DB migration — it stays on the config-as-code/manifest path, like thoseminScorethresholds. Documented indocs/review-configuration.md.Advisory-mode-safe — no live change.
aiReviewGateModedefaults toadvisory(never blocks), so the live posted gate is unchanged; this only affects the BLOCK path and the dry-run "would-be" verdict.No issue: small, self-evident hardening of an existing false-close path (the summary explains the rationale).
Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run typechecknpm run test:coveragelocally — both sides of every new??/ ternary / threshold comparison covered (ai-review.ts 99.03% stmt / 98.68% branch; advisory.ts 99.3% stmt / 98.03% branch; focus-manifest.ts 99.73% / 99.33%; the new confidence branches in advisory.ts are 100% on both sides).npm run test:ci(full gate, incl. actionlint / migrations / workers / mcp / ui:openapi:check / ui:lint / ui:build) — green.npm audit --audit-level=moderate— 0 vulnerabilities.npm run ui:openapi:check— no drift (config-as-code-only; no API field added).Safety
docs/review-configuration.mdupdated;CHANGELOG.mduntouched.Notes
aiReviewCloseConfidenceis an optional, manifest-only field onRepositorySettings(it staysundefinedfrom the DB and is set only by the.gittensory.ymloverlay), keeping it on the same config-as-code path as theminScorethresholds.