Degrade to Codex-only rounds while CodeRabbit is rate-limited#32
Conversation
CodeRabbit's account-wide review limit used to stall crq loop for the whole window even when Codex reviews every push. Now, when the account is blocked and Codex shows observed responsiveness on the PR, the round degrades to Codex-only: - DecideFire returns FireCodexDeferred for blocked rounds with a postable required Codex: the pump posts only the Codex command and the round stays queued, so CodeRabbit still fires the moment the window opens (with no duplicate Codex post). - Loop returns Codex findings promptly (exit 10) or a clean Codex verdict (exit 0, status "deferred") instead of extending its deadline past the block; a degraded round is never completed, so the CodeRabbit review stays owed and converged stays false until it lands. Wait hands a blocked slot-wait off to the poll loop on a clean Codex answer instead of spinning out the window. - Reports carry coderabbit_deferred and coderabbit_deferred_until; the deferral requires observed Codex evidence (auto-active or round-bound activity, minus usage-limit notices), never mere configuration. Default on; CRQ_RL_CODEX_DEGRADE=0 restores the old ride-out-the-window behavior.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds configurable Codex-only degradation during CodeRabbit account rate limits, including eligibility checks, deferred fire decisions, persisted command timestamps, feedback lifecycle handling, service orchestration, tests, and agent guidance. ChangesCodex degradation flow
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant CRQLoop
participant Service.Pump
participant DecideFire
participant GitHub
participant Feedback
CRQLoop->>Service.Pump: process queued round
Service.Pump->>DecideFire: evaluate account block and Codex eligibility
DecideFire-->>Service.Pump: FireCodexDeferred
Service.Pump->>GitHub: post `@codex` review
GitHub-->>Service.Pump: command ID and timestamp
CRQLoop->>Feedback: poll deferred round
Feedback-->>CRQLoop: Codex findings or deferred status
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
The degrade only covered the account-quota block, but a round parked behind another PR's in-flight review waits the same way while Codex needs no slot at all. The slot-busy gate now posts the Codex command for a postable required Codex and keeps the round queued; CodeRabbit fires once the slot frees, with CodexCommandID preventing a duplicate Codex post.
|
@codex review |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08bd5e7fae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Feedback gates the deferred verdict on the ACCOUNT-wide quota block only; a round's own awaiting_retry cooldown also covers non-quota retries (post failures, timeouts) that must keep normal handling. - An unfired round needs current Codex evidence to defer: a head-bound review or auto-activity, not stale PR-level comments that pass the zero round cutoff. - The slot-busy degrade skips heads CodeRabbit already reviewed; those belong to the dedupe resolution once the slot frees, and a queued round cannot complete on a clean Codex answer. - Codex evidence binds from CodexCommandedAt when crq posted the command before the deferred CodeRabbit fire: a SHA-less clean answer delivered in that gap used to fall outside the completion cutoff after the late fire, wedging the round with no repost.
|
@coderabbitai review |
|
@codex review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5a0988500
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- CodexOnlyEligible now requires evidence bound to this work: a review of the current head, or round-window activity anchored by the fire or by crq's own (possibly pre-fire) Codex command. Auto-activity on older heads merely predicts evidence and no longer qualifies, and the usage-limit check shares the same anchored cutoff so a notice from a previous head cannot permanently disqualify a commanded round. - CodexCommandedAt records the command comment's GitHub timestamp, not a local post-return clock reading, so a fast Codex reply cannot land before the stored cutoff and be ignored forever. - A blocked or slot-busy queue head with its Codex command already posted no longer starves later PRs: the pump scans a bounded number of following queued rounds for a postable Codex defer.
An unrelated local file swept into the previous commit; it is not part of this project.
|
@coderabbitai review |
|
@codex review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
coderabbit-queue/internal/crq/service.go
Line 661 in 68c46ff
When a live @codex review command suppresses posting during an adopted CodeRabbit fire, only the command ID is persisted here. If that existing Codex command has already produced a SHA-less clean answer before the adopted CodeRabbit command time, codexCutoff falls back to FiredAt, ignores the answer, and no repost happens because CodexCommandID is set; persist the adopted command's CreatedAt in CodexCommandedAt as well.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
✅ Action performedReview finished.
|
- The push-freely guidance on a deferred round now requires every required bot except CodeRabbit to have finished (DoneExcept); a pending third reviewer keeps the hold-head behavior. - The pump's deferred-Codex scan runs for any blocked/slot-busy front round, not only one whose own Codex command is already posted — a CodeRabbit-only front PR no longer starves later PRs of their early Codex round. - Adopted Codex commands (fire-time and co-review-wait adoption) persist their GitHub CreatedAt as CodexCommandedAt so pre-adoption SHA-less answers bind to the round. - The usage-limit floor falls back to the qualifying head review when the round has no fire/command anchor, so an old exhaustion notice cannot suppress the degrade.
|
@coderabbitai review |
|
@codex review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 962345b6dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/crq/service.go`:
- Around line 659-668: The CodexCommandedAt lookup is duplicated at two sites.
Add a codexCommandTime helper that finds the matching non-zero
CommandSeen.CreatedAt, converts it to UTC, and returns its pointer or nil;
replace both inline loops near the CodexCommandID assignments with this helper
while preserving the existing timestamp-anchor behavior.
- Around line 264-296: Update Pump’s starvation-avoidance condition around
applyFire to stop matching decision.Reason text. Use the structured global state
from s.global(st, now), specifically BlockedUntil and SlotFree, to identify the
blocked or slot-busy cases while preserving the existing rate-limit and FireNo
checks and bounded scan behavior.
In `@internal/engine/codex.go`:
- Line 193: Update the condition in the surrounding control flow to apply De
Morgan’s law and eliminate the negated conjunction, preserving the exact
existing behavior of codexReviewedHead(obs), anchored, and
obs.CodexActiveThisRound while satisfying staticcheck QF1001.
In `@internal/engine/fire.go`:
- Around line 68-85: In DecideFire, move the reviewedHead scan for the primary
bot and obs.Head to the function’s early setup, then reuse that single boolean
in both the FireCodexDeferred condition and the later codexAwareDedupe logic.
Remove the duplicated loop while preserving the existing predicate and path
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ec334f79-1512-476e-be6d-4e735771654b
📒 Files selected for processing (13)
internal/crq/config.gointernal/crq/feedback.gointernal/crq/service.gointernal/crq/service_test.gointernal/crq/state.gointernal/engine/codex.gointernal/engine/completion.gointernal/engine/engine.gointernal/engine/engine_test.gointernal/engine/fire.gointernal/state/state.gollms.txtskills/coderabbit-queue/SKILL.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
internal/state/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
Persist schema v3 with one
Roundper PR, one globalFireSlot,AccountQuota, and anArchivering; rounds must never be deleted and illegalRoundtransitions must return errors.
Files:
internal/state/state.go
internal/{dialect,engine,state,crq,gh}/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
Maintain the dependency direction
dialect ← engine ← crq,state ← crq, andgh ← {state, crq}; do not introduce dependency cycles.
Files:
internal/state/state.gointernal/engine/engine.gointernal/crq/state.gointernal/crq/config.gointernal/engine/codex.gointernal/engine/completion.gointernal/engine/fire.gointernal/crq/service_test.gointernal/engine/engine_test.gointernal/crq/feedback.gointernal/crq/service.go
internal/engine/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
internal/engine/**/*.go: Keepinternal/enginepure: decision logic must receivenowexplicitly and must not use context or GitHub I/O.
DecideFireis the single owner of fire decisions and must consolidate all fire guards; no other code may post the review command.
Files:
internal/engine/engine.gointernal/engine/codex.gointernal/engine/completion.gointernal/engine/fire.gointernal/engine/engine_test.go
internal/crq/**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
internal/crq/**/*.go: Keepinternal/crqorchestration-only; it owns service flow and wires packages but must not contain bot wording or duplicate engine decision logic.
Use the observe → decide → apply flow: observation is built once, engine decisions remain pure, andcrq/service.gois the only effects executor for CAS writes andPostIssueComment.
DryRunmust short-circuit apply by reporting without writing state or posting comments.
Keepcrq loopexit codes frozen: 0 for converged/skipped, 10 for findings, and 2 for timeout.
Files:
internal/crq/state.gointernal/crq/config.gointernal/crq/service_test.gointernal/crq/feedback.gointernal/crq/service.go
internal/engine/**/*_test.go
📄 CodeRabbit inference engine (AGENTS.md)
Keep convergence and fire rules table-tested in
internal/enginetests.
Files:
internal/engine/engine_test.go
🪛 golangci-lint (2.12.2)
internal/engine/codex.go
[error] 193-193: QF1001: could apply De Morgan's law
(staticcheck)
🪛 LanguageTool
llms.txt
[style] ~83-~83: Consider using a different verb for a more formal wording.
Context: ...ndow opens. - 10: read .findings[], fix valid issues, and validate locally. If ...
(FIX_RESOLVE)
🔇 Additional comments (17)
internal/crq/config.go (1)
72-75: LGTM!Also applies to: 142-143
internal/engine/engine.go (1)
25-29: LGTM!internal/engine/fire.go (2)
23-23: LGTM!
102-110: LGTM!internal/engine/engine_test.go (1)
639-675: LGTM!Also applies to: 677-697, 699-750, 752-786, 788-815
internal/crq/service.go (3)
498-499: LGTM!
745-745: LGTM!
961-987: LGTM!Also applies to: 1003-1003, 1017-1060, 1544-1552
llms.txt (1)
51-52: LGTM!Also applies to: 72-93
skills/coderabbit-queue/SKILL.md (1)
43-56: LGTM!internal/state/state.go (1)
70-75: LGTM!internal/crq/state.go (1)
84-90: LGTM!internal/engine/codex.go (1)
25-39: LGTM!Also applies to: 88-91, 179-211
internal/engine/completion.go (1)
87-90: LGTM!Also applies to: 283-302
internal/crq/feedback.go (1)
29-34: LGTM!Also applies to: 247-269, 354-354, 391-398, 409-427, 452-471, 482-484
internal/crq/service_test.go (2)
1897-1951: LGTM!Also applies to: 1952-2000
2001-2072: 🗄️ Data Integrity & IntegrationNo change needed:
CodexCommandedAtis persisted after the deferred Codex post.
fireCodexDeferredonly claims the post and returns; the assertion payload is handled by the separatefireCodexReviewcall, which recordsCodexCommandIDandCodexCommandedAttogether.> Likely an incorrect or invalid review comment.
| return false | ||
| } | ||
| anchored := r.FiredAt != nil || r.CodexCommandedAt != nil | ||
| if !codexReviewedHead(obs) && !(anchored && obs.CodexActiveThisRound) { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Apply De Morgan's law per the linter.
!codexReviewedHead(obs) && !(anchored && obs.CodexActiveThisRound) is flagged by staticcheck (QF1001) as simplifiable, and the hint is reported at [error] severity, so this is likely a CI lint failure rather than a stylistic nit.
🔧 Suggested simplification
- if !codexReviewedHead(obs) && !(anchored && obs.CodexActiveThisRound) {
+ if !(codexReviewedHead(obs) || (anchored && obs.CodexActiveThisRound)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if !codexReviewedHead(obs) && !(anchored && obs.CodexActiveThisRound) { | |
| if !(codexReviewedHead(obs) || (anchored && obs.CodexActiveThisRound)) { |
🧰 Tools
🪛 golangci-lint (2.12.2)
[error] 193-193: QF1001: could apply De Morgan's law
(staticcheck)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/engine/codex.go` at line 193, Update the condition in the
surrounding control flow to apply De Morgan’s law and eliminate the negated
conjunction, preserving the exact existing behavior of codexReviewedHead(obs),
anchored, and obs.CodexActiveThisRound while satisfying staticcheck QF1001.
Source: Linters/SAST tools
Problem
CodeRabbit's account-wide limit (~1 review/hour) stalls
crq loopfor the whole window: on a rate-limit reply the loop extends its deadline past the block and polls slowly — even when Codex actively reviews every push. A Codex fix round takes ~15 minutes, so ~4 of them fit inside one wasted CodeRabbit window.Change
When the account is blocked AND Codex shows observed responsiveness on the PR (auto-active, or activity bound to this round — configuration or an unanswered command alone never qualifies, and a Codex usage-limit notice disengages it), the round degrades to Codex-only:
DecideFirereturns a newFireCodexDeferredverdict for blocked rounds with a postable required Codex: the pump posts onlyCRQ_CODEX_CMDand the round stays queued, so@coderabbitai reviewstill fires the moment the window opens, without a duplicate Codex post (CodexCommandIDguards).Loopreturns Codex findings promptly (exit 10) or a clean Codex verdict (exit 0 withstatus: "deferred") instead of waiting out the window. A degraded round is never completed:convergedstays structurally false and the CodeRabbit review stays owed and discoverable.Waithands a blocked slot-wait to the poll loop on a clean Codex answer instead of spinning.coderabbit_deferred/coderabbit_deferred_untilfields; llms.txt and the skill document the semantics (exit 0 + deferred = progress, not convergence).Engine-pure decisions (
CodexOnlyEligible,DoneExcept, theFireCodexDeferredgate) with table tests, mirroring the dynamic Codex completion gate; service tests cover the degraded loop (findings + clean), the deferred pump posting, and the window-open CodeRabbit re-fire.Default on;
CRQ_RL_CODEX_DEGRADE=0restores the previous behavior.Testing
go build ./... && go vet ./... && go test ./...— all green (engine tables + service fakes + replay suites). Local CodeRabbit preflight run; one doc-consistency finding fixed, style/architecture suggestions declined as inconsistent with existing conventions.Summary by CodeRabbit
New Features
CRQ_RL_CODEX_DEGRADE=0.Documentation
Tests