feat(review-stats): add finding acceptance-rate signal to the maintainer stats feed (#1967)#5127
Conversation
…es (JSONbored#1967) Introduces the FindingAcceptanceAggregate interface to track the acceptance rate of PRs flagged with blocking findings (hold/close). Implements aggregateFindingAcceptance function to compute the acceptance metrics from flagged PR outcomes. Updates computeStats to include finding acceptance data and adds corresponding tests to validate the new functionality.
|
🚨 Contributor flagged. Click here for more info: Superagent Dashboard |
|
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 #5127 +/- ##
=======================================
Coverage 94.32% 94.32%
=======================================
Files 471 471
Lines 39821 39834 +13
Branches 14533 14535 +2
=======================================
+ Hits 37560 37573 +13
Misses 1583 1583
Partials 678 678
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-11 21:10:10 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Flagged checks (non-blocking)
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 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.
|
Summary
Adds the finding acceptance-rate signal to the maintainer stats feed — the one metric #1967 calls out as missing: "no acceptance-rate metric. Add a finding acceptance-rate signal (did the contributor act on a finding → merged)."
Of PRs whose gate raised a blocking finding (a
gate_decisionofholdorclose— the gate did not clear the PR to merge), it measures how often the contributor acted on it and the PR still merged. The realizedpr_outcome(merged vs closed) is the answer key, so acceptance is measurable with zero manual labeling — the maintainer-ROI "our review feedback gets acted on X% of the time" signal.This follows the existing metric-adder pattern in
src/review/stats.tsexactly — the same shape as cycle-time (#2194), calibration bins (#2192), and review-effort (#2155):FindingAcceptanceAggregatetype +EMPTY_FINDING_ACCEPTANCEconstant.aggregateFindingAcceptance(samples)— a pure fold (addressed/unaddressed/acceptanceRate).computeFindingAcceptance(env, opts)— a fail-safe D1 reader overreview_audit, reusing the samegate_decision→pr_outcomejoin the gate-eval already uses. A PR is "flagged" if it ever got a hold/close decision in the window (DISTINCT target_id) — so held-then-fixed-then-merged still counts as addressed — joined to the latestpr_outcomeper target.findingAcceptancefield wired intocomputeStats/StatsPayload.Scoped deliberately to the
stats.tsfeed (which #1967 names). Surfacing it on the operator-dashboard payload and a dashboard card is deferred to keep this diff narrow and single-purpose.Closes #1967
Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally (focused):npx vitest run test/unit/stats.test.ts— 52 pass, v8 coverage 100% stmts/lines/funcs onsrc/review/stats.ts, 100% on every changed line and branch (the sole uncovered branch is pre-existingtimingSafeEqual, untouched by this diff). Will run fullnpm run test:ci+npm auditbefore push.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderatern=1, fail-safe reject, null-results?? [], window default/clamp).If any required check was skipped, explain why:
Backend-only change (
src/review/stats.ts+ its unit test). No workflow, MCP, OpenAPI, or UI surface is touched, soactionlint,build:mcp/test:mcp-pack,ui:*, andui:openapi:checkare N/A.handleStatsreturns a raw JSON feed (not OpenAPI-typed), so no schema regeneration is required. Fulltest:ci+npm auditwill run before push.Safety
UI Evidence
N/A — no UI/frontend/docs changes in this PR.
Notes
flagged = addressed + unaddressed,acceptanceRate = addressed / flagged(3 dp),nullwhen nothing was flagged.computeCycleTimeAggregate): any D1 read error or a stats-window without flagged PRs degrades toEMPTY_FINDING_ACCEPTANCE, never throwing.