Parent: #1936
Problem
The only throttle on the @gittensory mention-command surface is maybeThrottleReviewNagPing (src/queue/processors.ts), and it is deliberately narrow: it only fires for the THREAD'S OWN AUTHOR pinging on their own PR/issue, and only when reviewNagPolicy is hold/close (default off). Every OTHER command in the catalog — the public commands (help, ask, preflight, blockers, duplicate-check, miner-context, next-action, reviewability, repo-fit, packet) and the maintainer-only queue-digest commands (queue-summary, confirmed-miners, review-now, needs-author, duplicate-clusters, burden-forecast, intake-health, outcome-patterns, noise-report) defined in src/github/commands.ts — has NO cooldown at all. isAuthorizedCommandActor gates WHO can invoke a command, nothing gates HOW OFTEN. Most of these dispatch to real, AI-cost-bearing orchestrator calls (planNextWork, explainBlockersWithAgent, preflightBranchWithAgent, preparePrPacketWithAgent), not free cache reads — so a careless or malicious actor can spam any of these dozens of times on the same thread, burning AI budget and posting comment noise each time.
Requirements
- Generalize the review-nag cooldown's audit-ledger counting pattern (
countRecentAuditEventsForActorAndTarget) into a per-command-family rate limit: keyed by (actor, command.name, targetKey) instead of hardcoded to the review-nag ping event type.
- Config-driven per repo (
.gittensory.yml), off by default / conservative default so existing repos see no behavior change until opted in.
- Distinguish AI-cost-bearing commands from cheap ones if practical (e.g. a tighter default limit for
ask/packet/preflight than for help).
- Reuse the existing hold-style response pattern from review-nag (a clear cooldown notice, no silent drop) — a rate-limited command should tell the requester why, not just go quiet.
Deliverables
- A generalized command-rate-limit helper built on the existing audit-ledger pattern, reusable by any
@gittensory command.
- The new setting(s) wired through the full config-as-code chain.
- Tests: under-threshold commands proceed normally; over-threshold commands get a cooldown reply instead of dispatching; the review-nag-specific cooldown continues to work unchanged (this generalizes the pattern, it doesn't replace review-nag's own narrower author-only/thread-only semantics).
Acceptance criteria
- Any
@gittensory command can be rate-limited per-repo via config, independent of review-nag's own settings.
- Default behavior for existing repos is unchanged (opt-in).
- A rate-limited invocation gets a clear, public cooldown notice, not silence.
Expected outcome
The entire @gittensory command surface — not just review-request pings — has a real defense against spam/AI-budget abuse, closing a strict superset of the exact problem review-nag was built to solve for one command.
Parent: #1936
Problem
The only throttle on the
@gittensorymention-command surface ismaybeThrottleReviewNagPing(src/queue/processors.ts), and it is deliberately narrow: it only fires for the THREAD'S OWN AUTHOR pinging on their own PR/issue, and only whenreviewNagPolicyishold/close(defaultoff). Every OTHER command in the catalog — the public commands (help,ask,preflight,blockers,duplicate-check,miner-context,next-action,reviewability,repo-fit,packet) and the maintainer-only queue-digest commands (queue-summary,confirmed-miners,review-now,needs-author,duplicate-clusters,burden-forecast,intake-health,outcome-patterns,noise-report) defined insrc/github/commands.ts— has NO cooldown at all.isAuthorizedCommandActorgates WHO can invoke a command, nothing gates HOW OFTEN. Most of these dispatch to real, AI-cost-bearing orchestrator calls (planNextWork,explainBlockersWithAgent,preflightBranchWithAgent,preparePrPacketWithAgent), not free cache reads — so a careless or malicious actor can spam any of these dozens of times on the same thread, burning AI budget and posting comment noise each time.Requirements
countRecentAuditEventsForActorAndTarget) into a per-command-family rate limit: keyed by(actor, command.name, targetKey)instead of hardcoded to the review-nag ping event type..gittensory.yml), off by default / conservative default so existing repos see no behavior change until opted in.ask/packet/preflightthan forhelp).Deliverables
@gittensorycommand.Acceptance criteria
@gittensorycommand can be rate-limited per-repo via config, independent of review-nag's own settings.Expected outcome
The entire
@gittensorycommand surface — not just review-request pings — has a real defense against spam/AI-budget abuse, closing a strict superset of the exact problem review-nag was built to solve for one command.