fix(review): per-actor rate ceiling + shared budget check on unlinked-issue AI verifier - #4551
Conversation
|
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 #4551 +/- ##
=======================================
Coverage 94.08% 94.08%
=======================================
Files 427 427
Lines 37961 37988 +27
Branches 13864 13868 +4
=======================================
+ Hits 35715 35742 +27
Misses 1586 1586
Partials 660 660
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-10 02:42:59 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 6 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🟩 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.
|
…hared budget counter Review feedback on #4551: the shared-budget check added in this PR read sumAiEstimatedNeuronsSince before running the verifier, but nothing wrote this feature's own actual calls back into that counter -- a free rider that respected every other feature's spend while never counting its own, so the true aggregate could silently exceed AI_DAILY_NEURON_BUDGET by however much this feature used. Record the same worst-case per-candidate estimate the budget check itself uses, mirroring ai-slop.ts's pre-computed-estimate recording convention.
b1f077a to
e053ed0
Compare
|
Confirmed — good catch. Fixed in e053ed0: records the same worst-case per-candidate estimate the budget check itself uses into the shared counter, right alongside the existing rate-ceiling attempt recording. Added tests confirming the counter increases after a verification call (including with an unknown author) and that a write failure there is swallowed. |
…-issue AI verifier The unlinked-issue-match AI verifier had no cost bound of its own: an actor opening many low-quality PRs across many repos could trigger arbitrarily many AI calls in a short window, and the verifier's own candidate loop could run against the shared daily neuron budget with no awareness of it. Add two gates ahead of the verification loop, both fail-safe toward "proceed normally" on a read error so a DB hiccup can never silently disable the guardrail: a per-actor rate ceiling (tracked via a new audit-event type) and a check against the same shared daily neuron budget every other free-tier AI feature draws from. Fixes #4515
…hared budget counter Review feedback on #4551: the shared-budget check added in this PR read sumAiEstimatedNeuronsSince before running the verifier, but nothing wrote this feature's own actual calls back into that counter -- a free rider that respected every other feature's spend while never counting its own, so the true aggregate could silently exceed AI_DAILY_NEURON_BUDGET by however much this feature used. Record the same worst-case per-candidate estimate the budget check itself uses, mirroring ai-slop.ts's pre-computed-estimate recording convention.
e053ed0 to
b1540df
Compare
Summary
The unlinked-issue-match AI verifier (
src/review/unlinked-issue-match.ts) had no cost bound of its own — every unlinked PR that produces at least one deterministic pre-filter candidate runs a real AI call, with no per-actor rate awareness and no check against the shared daily neuron budget every other free-tier AI feature (ai-review.ts,ai-slop.ts) already respects.This adds two gates in
resolveUnlinkedIssueMatchDisposition(src/review/unlinked-issue-guardrail.ts), both running before the candidate-verification loop:github_app.unlinked_issue_verify_attemptaudit event (cross-repo, keyed on PR author login) and skips verification once an actor hits 15 attempts in an hour. An unidentifiable author (no login) can't be rate-limited individually, so only the shared budget check applies to them — consistent with how the rest of this file already treats an unknown author.sumAiEstimatedNeuronsSince/AI_DAILY_NEURON_BUDGET, mirroringai-slop.ts's own pre-call budget check exactly (same default/clamp) since both draw from the same counter.Both gates fail toward "proceed as if this layer didn't exist" on any read error — a DB hiccup must never silently disable the guardrail itself, only this additive cost control.
MAX_CANDIDATES(signals/unlinked-issue-candidates.ts) andMAX_TOKENS/DIFF_CHAR_BUDGET(review/unlinked-issue-match.ts) are now exported so the orchestrator sizes its estimate off the same numbers rather than a second, driftable copy.Fixes #4515
Test plan
npx tsc --noEmitcleannpx vitest run test/unit/unlinked-issue-guardrail.test.ts test/unit/unlinked-issue-match.test.ts test/unit/unlinked-issue-candidates.test.ts test/unit/ai-slop.test.ts test/unit/ai-review.test.ts— 287/287 passingsrc/review/unlinked-issue-guardrail.ts: 100% branch, 100% lines on all new code (the one function coverage gap reported is a pre-existing fix(review): velocity-aware exception in the unlinked-issue-match escalation for machine-cadence (miner) authors #4512 line untouched by this diff)