fix(review): scope review-nag ping cooldown to the actor, not one PR - #4021
Conversation
maybeThrottleReviewNagPing counted @gittensory pings via a targetKey scoped to the current PR/issue only, so a contributor who exhausted their pings on one PR got a clean 0/maxPings slate on any fresh PR (a new issue.number is a new targetKey). Add countRecentAuditEventsForActorInRepo, which counts one actor's matching audit events across every target in a repo, and wire it into the throttle so the running count follows the contributor across PRs, mirroring how the contributor blacklist and moderation-rules ban tally already persist by login rather than by thread. maybeThrottleMonitoredMentions had the identical gap for its per-maintainer mention counter. Fixed the same way via a new countRecentAuditEventsForActorInRepoWithTargetSuffix, which keeps the repo-wide carryover while still pinning to one mentioned login's own targetKey suffix, so independently-budgeted mentioned logins never bleed into each other's count.
❌ 51 Tests Failed:
View the top 3 failed test(s) by shortest run time
View the full list of 48 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-07 11:20:08 UTC
⏸️ Suggested Action - Manual Review Nits — 1 non-blocking
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.
|
…imit scope - Fetch the PR's own commit messages via a new listPullRequestCommitMessages helper and thread them into the live gate's buildSlopAssessment call, so low_quality_commit_message (weight 15) can actually fire in production instead of unconditionally short-circuiting on undefined commitMessages. - Screenshot-table gate: action: "advisory" previously discarded a violation entirely (only "close" produced any signal). Add maybeAddScreenshotTableAdvisoryFinding, mirroring the lockfile-tamper-risk advisory pattern, so an advisory-mode violation appends a visible, non-blocking finding instead of silently doing nothing. - Scope commandRateLimitPolicy's per-command counter and the intent-routing classifier's counter to (actor, command, repo) instead of (actor, command, repo#issueNumber), mirroring the JSONbored#4021 fix already applied to review-nag's cooldown. Opening a fresh issue/PR no longer resets an actor's AI-cost-bearing command budget.
Summary
maybeThrottleReviewNagPingcounted@gittensorypings via atargetKeyscoped to the current PR/issue only (countRecentAuditEventsForActorAndTarget(env, commenter, REVIEW_NAG_PING_EVENT_TYPE, targetKey, sinceIso)). Enforcement holds/closes the PR once the count reachesreviewNagMaxPings, but because the count was scoped per-target, a contributor who exhausted their pings on one PR got a clean0/maxPingsslate on any fresh PR — a newissue.numberis a newtargetKey, with zero memory of the prior PR's ping history. This is inconsistent with the contributor blacklist and moderation-rules ban tally, which correctly persist by actor login across every PR.Adds
countRecentAuditEventsForActorInRepo(src/db/repositories.ts), which counts one actor's matching audit events across every target within a repo (reusing the same literal-prefixLIKE ... ESCAPEscoping already used byfindHottestReviewTargetForRepo), and wires it intomaybeThrottleReviewNagPingin place of the per-target count. Because the count now spans every target the actor has pinged on within the repo, the very first ping on a brand-new PR already reflects a prior PR's exhausted count — no separate "still on cooldown" table is needed; the existingaudit_eventsledger read at the new repo scope already is the persistent per-actor cooldown state.The sibling
maybeThrottleMonitoredMentions(the per-maintainer@-mentionnag counter) had the identical gap, via atargetKeysuffixed#mention:<login>. Fixed the same way with a second new function,countRecentAuditEventsForActorInRepoWithTargetSuffix, which keeps the repo-wide carryover while still pinning to one mentioned login's own suffix, so independently-budgeted mentioned logins never bleed into each other's count (mentioning maintainer X vs. maintainer Y, and pinging@gittensoryvs. mentioning a maintainer, all stay on separate budgets, per the existing design).Closes #4020
Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally;codecov/patchrequires ≥97% coverage of the lines AND branches you changed (aim for 98%+ on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.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=moderateEvery changed line/branch in
src/db/repositories.tsandsrc/queue/processors.tsis covered, confirmed via the v8 lcov report (DA/BRDAentries) for the exact diff ranges. Two regression tests added: one for each throttle function, seeding an exhausted PR-A ping count then confirming a single PR-B ping already crosses the threshold; a third confirms a different mentioned login on PR B keeps its own independent budget.Note:
npm run test:coverage(part of the fulltest:cichain) currently has a small number of pre-existing failures onorigin/mainunrelated to this change (verified by running them against a clean, unmodifiedorigin/maincheckout before and after this diff, with identical results): a stale hardcoded-date assertion intest/unit/predicted-gate-engine-coverage.test.ts, a Prometheus-metrics-ordering assertion in 4 tests undertest/unit/queue.test.ts's "auto-action convergence" suite, and a doc/example drift intest/unit/config-templates.test.ts(likely from the recently-mergedreview.shared_config/ #2046). None of these touch review-nag, audit-events, or any file this PR changes.Safety
UI Evidencesection below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository.No UI/frontend files touched — this is a backend-only (
src/db/repositories.ts,src/queue/processors.ts) change, so no UI Evidence section applies.Notes
origin/main, I foundsrc/queue/processors.tscurrently failsnpm run typecheckonorigin/mainHEAD due to a splicing error introduced by the just-merged fix(queue): prevent regate repair exhaustion from premature attempt counting #3998 (regate-repair-attempts fix), around theisPriorityRepair/repairHeadShajob-dispatch code — confirmed viagit show origin/main:src/queue/processors.tsdirectly, unrelated to this diff (my changed lines don't overlap that region at all). This appears to already be tracked/being worked separately.