fix(review): resolve dead aiReviewCloseConfidence floor with a configurable disposition - #4656
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
gittensory-ui | 4afac01 | Commit Preview URL Branch Preview URL |
Jul 10 2026, 10:06 AM |
|
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 #4656 +/- ##
=======================================
Coverage 94.12% 94.12%
=======================================
Files 434 434
Lines 38542 38565 +23
Branches 14047 14065 +18
=======================================
+ Hits 36277 36300 +23
Misses 1604 1604
Partials 661 661
🚀 New features to boost your workflow:
|
|
Caution 🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥 🛑 Gittensory review result - fixes requiredReview updated: 2026-07-10 09:55:06 UTC
🛑 Suggested Action - Manual Review
Review summary Blockers
Nits — 7 non-blocking
CI checks failing
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. 🟩 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.
|
…urable disposition (#4603) isConfiguredGateBlocker voided aiReviewCloseConfidence entirely (commit 311b761, #1781), so a sub-floor ai_consensus_defect/ai_review_split finding always one-shot-closed a contributor PR under aiReviewGateMode: block regardless of the AI reviewers' own calibrated confidence, while five other comments across the codebase still described the old (correct) "downgrades to a hold" behavior. Adds aiReviewLowConfidenceDisposition ("one_shot" | "hold_for_review" | "advisory_only", default hold_for_review) to govern a sub-floor finding: hold_for_review (shipped default) still blocks the gate but routes the would-be close through the same held-for-manual-review mechanism the disposition planner already uses for migrationCollisionHold/unlinkedIssueMatchHold; one_shot keeps today's unconditional-close behavior as an opt-in; advisory_only drops a sub-floor finding to non-blocking. Wires the new field through the full template this repo uses for a RepositorySettings field: migration + Drizzle schema + resolver/parser (src/db/repositories.ts), OpenAPI schema + regenerated apps/gittensory-ui/public/openapi.json, .gittensory.yml config-as-code override (gate.aiReview.lowConfidenceDisposition), and the maintainer /ai-review + internal settings routes. Mirrors the gate-decision change into the packages/gittensory-engine predictor twin so the MCP predict_gate tool stays accurate. Fixes all 6 stale-comment locations the original audit found.
…ose codecov/patch gap on #4603 Two independent problems found in PR #4656 (#4603) before merge, both fixed here: 1. The PR silently deleted src/services/public-accuracy-trend.ts (181 lines) and its test, un-exported the public-stats.ts helpers it depended on, and dropped the accuracyTrend field from the public GET /v1/public/stats response -- entirely unrelated to #4603's actual scope (a live, wired-in public homepage feature from epic #4445/#4447, undisclosed in the commit message or PR body). Restored all four pieces verbatim from main. 2. codecov/patch was failing (83.33% vs 99% target): the new isConfiguredGateBlocker branches for aiReviewLowConfidenceDisposition in packages/gittensory-engine/src/advisory/gate-advisory.ts had a dedicated node:test suite, but that suite runs against the compiled dist/ output in a separate test runner whose coverage never reaches the coverage/lcov.info file Codecov actually reads -- only the root vitest suite's coverage does, and it only touches this file through the handful of test/unit/*.ts files that import it directly by relative path (not via the npm package). Added the missing branch cases to the existing test/unit/predicted-gate-engine-branch-coverage.test.ts, which does import it that way. Also found src/api/routes.ts's `updated.aiReviewLowConfidenceDisposition ?? "hold_for_review"` fallback is unreachable in practice -- parseAiReviewLowConfidenceDisposition's return type is non-nullable and already falls back to the same literal itself -- so marked it /* v8 ignore next */ rather than writing a contrived test for a branch that can't actually run. Part of #4603
5c6a8e0 to
4afac01
Compare
|
Independent review before merge found two problems, both fixed in the latest push: 1. Undisclosed, out-of-scope deletion. The original commit silently removed 2. Full local run of every touched test file (11 files, 1952 tests) passes; typecheck clean. |



Summary
Resolves #4603:
aiReviewCloseConfidencehas been a dead floor since commit311b7613d(#1781) —isConfiguredGateBlockervoided the value and a sub-floorai_consensus_defect/ai_review_splitfinding always one-shot-closed a contributor PR under
aiReviewMode: block, regardless of the AIreviewers' own calibrated confidence. Five other comments across the codebase still described the old
(correct) "downgrades to a hold" behavior, which the #1781 change silently broke without updating them.
Per the maintainer decision recorded on the issue, this ships a new
aiReviewLowConfidenceDispositionfield (
"one_shot" | "hold_for_review" | "advisory_only", defaulthold_for_review) that governs whathappens to a sub-floor finding:
hold_for_review(shipped default) — the defect still blocks the gate (merge stays blocked), butroutes the would-be one-shot close through the same held-for-manual-review mechanism the disposition
planner already uses for
migrationCollisionHold/unlinkedIssueMatchHold, instead of inventing a new one.one_shot— today's live (pre-fix) behavior, unchanged. Opt-in only.advisory_only— a sub-floor finding drops to fully non-blocking.At-or-above-floor confidence behaves identically across all three values — the floor only matters below
threshold.
What changed
src/rules/advisory.ts):isConfiguredGateBlocker'sai_consensus_defect/ai_review_splitbranch now reads the resolved disposition; new exported
resolveAiReviewLowConfidenceHoldresolves the{ reason, comment }hold object for a gate failure driven solely by a sub-floor AI-judgment finding.src/settings/agent-actions.ts): newaiReviewLowConfidenceHoldinput narrowswillClose'sconclusion === "failure"arm only — a genuinely different adverse signal (red CI, a baseconflict, or a concrete blocker alongside the AI defect) still closes normally. The generic manual-review
label fallback now carries the hold's comment.
packages/gittensory-engine/src/advisory/gate-advisory.ts): mirrored so theMCP
predict_gatetool's gate-decision core stays in sync (checkGateDecisionVersionBumprequires either amatching edit to both twins or an engine version bump — this PR edits both).
0140_ai_review_low_confidence_disposition.sql(DB column, defaulthold_for_review),src/db/schema.ts/src/db/repositories.ts(resolver + parser + upsert round-trip),src/openapi/schemas.ts+ regeneratedapps/gittensory-ui/public/openapi.json,.gittensory.yml(
gate.aiReview.lowConfidenceDisposition, config-as-code override) viapackages/gittensory-engine/src/focus-manifest.ts+src/signals/focus-manifest.ts, and the maintainer/ai-reviewself-serve route + the internal full-replace settings route insrc/api/routes.ts.behavior:
src/types.ts(AdvisoryFinding.confidence,RepositorySettings.aiReviewCloseConfidence),src/services/ai-review.ts(×3:ModelReview.confidence,consensusDefectOf,runGittensoryAiReview),src/queue/processors.ts(×2: the consensus-defect and split finding construction), andisConfiguredGateBlockeritself..gittensory.yml.example+config/examples/gittensory.full.ymldocument the newgate.aiReview.lowConfidenceDispositionfield alongside the existingcloseConfidence.Deviations from the issue's suggested shape
.gittensory.yml.example". I additionally wired the maintainer self-serve/ai-reviewroute and theinternal full-replace
/v1/internal/repos/:owner/:repo/settingsroute (mirroring the siblingaiReviewModefield's own dashboard-settable pattern), since the field is explicitly DB-backed/dashboard-settable per the decision comment — leaving it with no write path other than raw SQL would be
an incomplete implementation of "DB-backed (dashboard-settable too)".
aiReviewLowConfidenceDispositionthroughpackages/gittensory-engine/src/predicted-gate.ts's own policy-building call (the MCPpredict_gatetool's actual manifest→policy mapping) — this mirrors the exact same partial-wiring precedent already set
by
linkedIssueSatisfactionGateMode, which also isn't threaded through that predictor. The predictor'sisConfiguredGateBlockercopy does receive the field (byte-correct for a future predictor-side change),it just isn't populated from a real
.gittensory.ymlread yet. Noted here rather than expanding scope.src/signals/settings-preview.ts'sRepoSettingsPreviewtype — the siblingaiReviewCloseConfidencefield is also absent from that preview type, and no automated check requiresparity there (unlike
RepositorySettingsSchema, which theui:openapi:settings-parityscript doesenforce, and which this PR does update).
Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally (unsharded) — all touched-file branches verified covered both ways viascoped coverage runs (
src/rules/advisory.ts,src/settings/agent-actions.ts,src/db/repositories.ts,src/signals/focus-manifest.ts,src/api/routes.ts,src/queue/processors.ts); full-suite run greenother than one pre-existing, unrelated flake (see Notes).
npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:openapi:settings-paritynpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderatetest/unit/rules.test.ts,test/unit/agent-actions.test.ts,test/unit/gate-check-policy.test.ts,test/unit/focus-manifest.test.ts,test/unit/repository-settings-ai-review-low-confidence-disposition.test.ts(new),test/unit/routes-ai-byok.test.ts,test/unit/queue.test.ts(2 new end-to-end regressions proving theactual bug is fixed: a sub-floor cached defect holds instead of closing under the default, and closes
under an explicit
one_shotopt-in), and a new dedicatedpackages/gittensory-engine/test/gate-advisory- ai-review-low-confidence-disposition.test.tsfor the engine twin.Safety
or private maintainer evidence are exposed.
sanitizePublicComment).RepositorySettingsSchema,openapi.json, the/ai-reviewroute, the internal full-replace route).
UI Evidencesection needed.Notes
(
test/unit/queue.test.ts› "PR-panel generate-tests checkbox (feat(review): interactive generate-tests checkbox in ORB's PR comment, maintainer-only #4589) › respects the repo's configuredcommit delivery mode via the checkbox") on this branch's original base commit — confirmed fixed on current
origin/mainby fix(review): stub the live-PR verification fetch in the checkbox commit-delivery test #4627 (already merged) and confirmed passing after rebasing this branch onto latest main.Not touched by this PR.