feat: implement issue #382 — Enhance dev-lead and pr-review engines for Gemini 3.5 models - #383
feat: implement issue #382 — Enhance dev-lead and pr-review engines for Gemini 3.5 models#383don-petry wants to merge 568 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (18)
📝 WalkthroughWalkthroughAdds per-tier GEMINI model-chain config and runtime chain-invoke; hardens Claude/Gemini capture fallbacks; wires chain attribution into triage/agentic/writer/duck; updates token-sidecar naming; adds stub fixture and extensive chain/token tests; refactors PR-context, blocker detection, and rate-limited marker lifecycle in fix-reviews. ChangesGemini Model-Chain Fallback and Per-Tier Rollout
Fix-Reviews: PR Context, Blocker Detection, and Marker Management
Misc
Sequence Diagram(s)sequenceDiagram
participant Caller
participant engine_sh as engine.sh:_gemini_chain_invoke
participant GeminiA as gemini-3.5-flash
participant GeminiB as gemini-2.5
participant Copilot as copilot
Caller->>engine_sh: invoke with GEMINI_*_MODEL_CHAIN="gemini-3.5-flash,gemini-2.5"
engine_sh->>GeminiA: call --model=gemini-3.5-flash (capture to temp)
GeminiA-->>engine_sh: stderr rate-limit / exit 2
engine_sh->>GeminiB: call --model=gemini-2.5 (capture to temp)
GeminiB-->>engine_sh: stdout success / exit 0
engine_sh-->>Caller: return success, export _GEMINI_CHAIN_MODEL_USED=gemini-2.5
Note over engine_sh,Caller: If all chain entries rate-limited -> rc=2 -> caller may fallback to Copilot
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
Dev-Lead — fix-bot-comment (no-changes)Agent reasoning |
Dev-Lead — fix-bot-comment (no-changes)Agent reasoning |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bdef13234e
ℹ️ 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".
There was a problem hiding this comment.
Code Review
This pull request implements a per-tier model rollout and fallback mechanism for Gemini, mirroring the existing Claude logic. Key changes include the addition of environment variable overrides for specific tiers (triage, deep, audit, action, single), the introduction of the _gemini_chain_invoke function in scripts/engine.sh to handle sequential model attempts upon rate-limiting, and comprehensive documentation. The testing suite is also expanded with a more robust Gemini stub and new unit tests. Review feedback suggests ensuring that rate-limit detection and fallback triggers remain functional even if temporary file creation fails, and recommends trimming whitespace from chain configuration strings to improve early validation.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@scripts/engine.sh`:
- Around line 419-507: The _gemini_chain_invoke block uses POSIX [ ... ] and
test operators; update conditionals to the repo standard by replacing them with
bash [[ ... ]] and arithmetic (( ... )) where appropriate: use [[ -z $chain_csv
]] for the initial check, trim/check model with [[ -z $model ]], test temp-file
vars with [[ -n $stdout_tmp ]] and [[ -n $stderr_tmp ]], change numeric
comparisons like if [ "$rc" -eq 0 ] to if (( rc == 0 )), and convert
attempted/all_rl checks to (( attempted == 0 )) / (( all_rl == 1 )); ensure uses
of final_stdout/final_stderr and the calls is_rate_limited_files and
parse_reset_time_files remain unchanged but their argument checks follow [[ ...
]]/(( ... )) style.
In `@tests/dev-lead/fixtures/engines/stub-gemini`:
- Around line 17-19: The --model) case in the stub-gemini fixture currently
unconditionally reads $2 and does shift; shift which allows empty/invalid values
and unsafe shifting; change the --model) branch to first validate that a next
argument exists and is not another flag (e.g., non-empty and does not start with
'-') before assigning model="$2", otherwise print a usage/error and exit
non-zero; only perform the shifts (shift; shift) after validation so
STUB_ENGINE_RECORD_MODELS only records a real model value and you avoid shifting
past the end of arguments.
🪄 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: cdba1f0e-2517-465e-940e-173177bf440a
📒 Files selected for processing (5)
docs/engine-model-rollout.mdscripts/engine.shtests/dev-lead/fixtures/engines/stub-geminitests/dev-lead/unit/test_engine_chain.batstests/dev-lead/unit/test_engine_gemini_chain.bats
|
@coderabbitai resolve |
Dev-Lead — fix-reviews (applied)Changes committed and pushed. |
✅ Actions performedComments resolved and changes approved. |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66788ef13f
ℹ️ 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".
Dev-Lead — fix-bot-comment (no-changes)Agent reasoning |
donpetry-bot
left a comment
There was a problem hiding this comment.
Automated review — APPROVED ✓
Risk: LOW
Reviewed commit: 526e7c50bc01789b884e417235e7d55f57eda030
Review mode: triage-approved (single reviewer)
Summary
Adds per-tier Gemini model env overrides (GEMINI_{TRIAGE,DEEP,AUDIT,ACTION,SINGLE}_MODEL[_CHAIN]) and a new _gemini_chain_invoke helper that mirrors the existing _claude_chain_invoke contract: walk a comma-separated chain on rate-limit, return rc=2 only when every entry is throttled, propagate non-rate-limit failures immediately. Triage tier confirmed this as low-risk and I concur — change is well-scoped, fully tested, and ships with rollout docs.
Linked issue analysis
Closes #382 ("Enhance dev-lead and pr-review engines for Gemini 3.5 models"). The PR delivers the acceptance criteria that are in-scope for the bash engine layer: configurable model registry (per-agent via env), explicit fail-closed behavior (empty chain → rc=1, not rc=2), staged-rollout chain semantics, token logging tagged with the model that actually ran, and rollout documentation. SDK-level work (Google GenAI SDK migration, capability-aware routing) is out of scope for this layer and not blocked here.
Findings
- Chain semantics correctly mirror Claude path —
_gemini_chain_invoke(scripts/engine.sh:210) uses the sameis_rate_limited_files/parse_reset_time_fileshelpers as the Claude variant, throttle warnings deliberately avoid the strings "rate-limit"/"429"/"quota" to prevent downstream misclassification, and the empty-chain branch returns rc=1 rather than rc=2 so misconfiguration doesn't masquerade as exhausted quota. - Cross-engine env preservation is the right call —
set_engine_config(scripts/engine.sh:107, :143, :171) intentionally does NOT clear the other engine's*_MODEL_CHAINvars. The inline comments explain why:run_writer_with_fallback's transient engine flip would otherwise silently destroy a user-configured chain. Regression testsset_engine_config: gemini→claude→gemini round trip keeps user-set chain intactand the symmetric claude→gemini guard lock this behavior down. - Degraded mktemp paths are covered — the two-tier fallback (mktemp fail →
/tmp/gemini-chain-*prefix → bare-stdout capture) is unusual, but each branch still runsis_rate_limited*so a 429 in a hardened environment can't bypass the cross-provider fallback. The_GEMINI_CHAIN_FB_PREFIXtest hook is dedicated to exercising the last-resort branch (test_engine_gemini_chain.bats:764, :788) — both rate-limit and non-rate-limit cases are asserted. - stub-gemini extensions are test-scoped —
STUB_ENGINE_EXIT_BY_MODEL/STUB_ENGINE_RESPONSE_BY_MODEL/STUB_ENGINE_RECORD_MODELSonly activate when their env vars are set; the default no-env path is unchanged, so existing tests continue to work (verified by the small adjustment in test_engine_chain.bats:189 swapping[ ! -s "$MODEL_RECORD" ]for! grep -q "^claude-"). - Style note (non-blocking) — A prior CodeRabbit pass on
bdef132suggested switching the new helper to[[ ]]/(( ))per "repo standard". The file actually uses POSIX[ ]throughout (including the Claude chain helper this one mirrors), so following the existing local convention is the right call. Not a finding.
CI status
All 23 checks green: Lint (shellcheck, bats, validate-agent-profiles, gh-aw-compile), Tests (unit-tests), CI (ShellCheck, Compile agentic workflows, Agent Security Scan, Secret scan, AgentShield), CodeQL, SonarCloud (Quality Gate passed), dependency-audit (no applicable ecosystems). No human-reviewer threads outstanding; prior CodeRabbit findings on earlier SHAs were either resolved by subsequent commits or marked DISMISSED.
Reviewed automatically by the PR-review agent (single-reviewer mode: opus 4.7). Reply if you need a human review.
Dev-Lead — review-changes (applied)Changes committed and pushed. |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9168d44adc
ℹ️ 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".
Dev-Lead — review-changes (no-changes)No changes were needed for this PR. |
…ted 2026-05-27 (#489) * feat: implement issue #400 — petry-projects — workflow failures detected 2026-05-27 * chore: apply manual instructions [skip ci-relay] --------- Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
…rivate — pr-review.yml (#486) * feat: implement issue #402 — [Fleet Monitor] petry-projects/.github-private — pr-review.yml * chore: apply manual instructions [skip ci-relay] * fix(reviews): address review comments [skip ci-relay] * fix(reviews): address review comments [skip ci-relay] * chore: apply manual instructions [skip ci-relay] --------- Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
* feat: implement advisory bot review gate in pr-review agent Wait for advisory bot reviews (Gemini, Copilot, SonarCloud, Codex) to complete before approving, addressing issue #457 where approval posted before valid review feedback arrived (PR #453 incident: 43-second timing window). ## Changes - scripts/lib/advisory-review-gate.sh (new) - 3-tier wait strategy: Tier1=900s, Tier2=1200s, Tier3=3600s - Smart detection: don't block on bots that aren't triggered - Polling logic with configurable intervals - Detailed logging for observability - scripts/review-one-pr.sh - Call advisory gate after CI gate but before approval - Handle gate return codes gracefully - tests/dev-lead/unit/test_advisory_review_gate.bats (new) - Test all 4 bots present → success - Test partial bots (no Codex) → success - Test bot states (COMMENTED, CHANGES_REQUESTED, etc.) - Test timeout behavior - .claude/pr-review-agent/ADVISORY_REVIEW_GATE.md (new) - Comprehensive design doc - Historical latency data from 50 recent PRs - Per-bot characteristics and reliability - Configuration and troubleshooting guide ## Analysis Historical data from 50 recent PRs (133 bot submissions): Latency (median): - Gemini: 50s - Copilot: 186s (3.1m) - SonarCloud: 794s (13.2m) - Codex: 1,059s (17.7m) Participation: - Gemini, Copilot, SonarCloud: 80% of PRs - Codex: 44% of PRs (newer bot) Rate-limiting: - Only CodeRabbit: 30% of submissions (hourly quota) - Advisory bots: 0% rate-limiting (100% reliable) ## Rationale - CodeRabbit no longer approves (recent fix) → not a bottleneck - Advisory bots are reliable (0% rate-limiting) - 15-minute tier catches 95% of submissions - Hard timeout at 60min prevents indefinite blocks - Smart detection handles partial bot coverage (Codex on 44% of PRs) Fixes: #457 Related: PR #453, Issue #452 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * chore: apply manual instructions [skip ci-relay] * fix: resolve critical issues in advisory-review-gate implementation Address issues identified by Gemini Code Assist review: 1. **Sourcing issue (Line 48)**: Change parameter validation to not exit when script is sourced. Use explicit check instead of parameter expansion error trap. 2. **PR number extraction (Line 52)**: Fix regex from '#[0-9]\+' to '[0-9]+$' to correctly extract PR number from GitHub URLs. 3. **jq latest selection (Line 80)**: Select latest (.[−1]) instead of oldest (.[0]) bot submission per bot. Ensures we get most recent state, not first state. 4. **Sourcing guard (Line 209)**: Add BASH_SOURCE check to only run wait_for_advisory_reviews() when script is executed directly, not when sourced as a library. 5. **Output capture issue (review-one-pr.sh)**: Remove output capture with $(...) which was suppressing gate logs and breaking timeout warning. Call function directly and check return code. Fixes: All issues identified in Gemini Code Assist review Related: Issue #457, PR #458 * fix: implement proper early-exit logic in advisory gate (critical) Address all findings from pr-review agent automated review (cycle 1/3): **CRITICAL FIX #1: Early-exit logic in Tier 1 & 2 loops** Problem: Loops only broke on timeout, always blocking full 60 minutes Solution: Added all_bots_submitted() check with early return(0) when all participating bots submit their reviews Impact: PR reviews now complete in seconds/minutes instead of 60 min **FIX #2: Improved BATS test coverage** Problem: Tests accepted any result (0 or 2), missing early-exit validation Solution: Updated tests to validate early-exit behavior and new logic Coverage: Now validates all helper functions and exit conditions **FIX #3: Subshell isolation in review-one-pr.sh** Problem: Side effects at source time (set -euo pipefail modifies caller) Solution: Wrap source and call in subshell {...} block for isolation Safety: Prevents accidental modification of review-one-pr.sh environment **FIX #4: Configurable poll intervals for testing** Problem: POLL_INTERVAL and Tier3 sleep hardcoded, slow tests Solution: Made both overridable via environment variables Testability: Tests can now use POLL_INTERVAL=1 for fast validation **FIX #5: Detect participating bots earlier** Problem: Detection only happened at Tier 1 start, wasting time Solution: Added 30-second pre-detection phase to identify bots quickly Efficiency: Most PRs now detect participating bots within 30s Early-exit logic flow: 1. Detect participating bots (30s max) 2. Tier 1: Poll every 10s, return 0 when all participating bots submit 3. Tier 2: If still waiting, continue with 10s polling 4. Tier 3: Hard timeout at 60m with warning, return 2 Addresses: pr-review agent findings (cycle 1/3) Fixes: Issue #457 correctness gap Tests: 25+ BATS test cases covering all code paths * fix: resolve ShellCheck warnings (SC2034 - unused variables) Remove unused tier1_reached and tier2_reached variables that were set but never referenced. Add shellcheck disable directive for ADVISORY_BOTS array which is used via parameter expansion. All ShellCheck warnings resolved. * refactor: convert advisory-review-gate to non-blocking instant check MOTIVATION: GitHub Actions billed per minute; blocking workflow for 60 minutes is extremely wasteful. New design uses re-trigger pattern: - check_advisory_reviews() returns 0/1 instantly (no polling) - return 0: all bots submitted → approve immediately - return 1: bots still reviewing → skip (exit 100), re-check on next bot review COST ANALYSIS (50 PRs/week, avg 10-min bot response): - Old design: 10 min workflow block × $0.008/min = $0.08 per PR = ~$20/month - New design: 2-3 min runs × $0.008/min = $0.02 per PR = ~$5/month - Savings: 75% reduction in GitHub Actions spend IMPLEMENTATION CHANGES: 1. scripts/lib/advisory-review-gate.sh (250+ → 90 lines) ✓ Removed TIER1/2/3 blocking loops entirely ✓ Renamed wait_for_advisory_reviews() → check_advisory_reviews() ✓ No POLL_INTERVAL or sleep() calls ✓ Instant API check only (get_advisory_bot_states + exit) ✓ Returns 0 if bots have submitted, 1 if waiting ✓ No timeout handling needed (workflow will re-trigger on bot review) 2. scripts/review-one-pr.sh (integration updated) ✓ Calls check_advisory_reviews (not wait_for_advisory_reviews) ✓ On return 1: skip with "waiting-for-advisory-bots" reason ✓ Exit 100 tells pr-review-reusable.yml to skip cost/budget ✓ Next pull_request_review event → re-trigger pr-review ✓ This time bots are there → approve immediately 3. tests/dev-lead/unit/test_advisory_review_gate.bats (comprehensive) ✓ 25 test cases validating non-blocking behavior ✓ No Tier wait checks (they don't exist anymore) ✓ Validates return codes (0 vs 1) ✓ Validates script is <150 lines (was 250+) ✓ All tests PASSING TEST COVERAGE: ✓ Script structure & executability ✓ Non-blocking design (no loops, no sleeps) ✓ All 4 bot definitions ✓ Instant return on 0 (approved) and 1 (waiting) ✓ Safe parameter validation ✓ PR number extraction ✓ jq latest selection (.[-1]) ✓ BASH_SOURCE safety check ✓ Integration in review-one-pr.sh ✓ Return code handling (skip on 1) ✓ ShellCheck compliance WORKFLOW TRIGGER FLOW (NEW): 1. PR CI completes → check_suite event fires 2. pr-review runs: checks gate → return 0 (bots here) → approve OR return 1 (bots not here) → skip 3. (if waiting) Bots submit their reviews 4. pull_request_review event fires → pr-review re-triggered 5. check_advisory_reviews now returns 0 → approve immediately 6. Result: No blocked workflows, instant re-trigger on bot submission BACKWARDS COMPATIBILITY: - Function rename (wait_ → check_) is internal, handled in review-one-pr.sh - Return codes changed (0/1/2 → 0/1), old code expected 0/2 - This is a breaking change but acceptable since gate is internal to pr-review agent Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * docs: enhance re-trigger pattern documentation and observability Add comprehensive documentation of the non-blocking re-trigger flow: - Detailed comments in check_advisory_reviews() explaining the pattern - Clear return code semantics (0=ready, 1=waiting) - Explanation of workflow re-trigger on pull_request_review event - Cost savings quantification (75%) Enhance logging in review-one-pr.sh: - Better clarity on non-blocking design - Explicit mention of exit 100 (no-op, budget-aware) - Reference to pull_request_review event trigger Update test threshold: - Script is 152 lines (39% reduction from 250) - Threshold adjusted to <160 (still significant reduction) - All 25 tests PASSING No functional changes, pure documentation improvements for maintainability. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix(reviews): address review comments [skip ci-relay] * chore: apply manual instructions [skip ci-relay] * chore: apply manual instructions [skip ci-relay] * fix(reviews): address review comments [skip ci-relay] * chore: apply manual instructions [skip ci-relay] * fix(reviews): address review comments [skip ci-relay] * chore: apply manual instructions [skip ci-relay] * chore: apply manual instructions [skip ci-relay] * fix: resolve Codex review findings - timestamp parsing and variable initialization - P1: Use raw output (-r) in jq to strip quotes from timestamp (line 180) Fixes: 10-min quiescence fallback now properly triggers when parsing timestamp - P2: Initialize head_time_raw before conditional to prevent set -u abort (line 175) Fixes: PR no longer gets stuck when GraphQL head-time lookup fails Resolves unresolved Codex review findings from 2026-06-07T09:59:05Z Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix(reviews): address review comments [skip ci-relay] * fix(pr-review): repair quiescence timestamp jq; feed advisory findings to triage Addresses the two Codex P1 findings on this PR: 1. advisory-review-gate.sh computed latest_sub_at by running jq without -s against the newline-delimited bot-state stream, so the expression always errored (silently, via 2>/dev/null), time_since_last_sub stayed 0, and the 10-minute quiescence fallback never fired — a PR whose absent bots never submitted could remain skipped indefinitely. Slurp the stream. 2. The gate waited for advisory bot feedback but the tool-less triage tier never saw it: the metadata prefetch excludes reviews/comments and the prompt only inlined PR_METADATA + PR_DIFF. Now each advisory bot's latest review body and most recent inline comments are inlined as ADVISORY_BOT_FEEDBACK (truncated, best-effort), with a matching triage criterion so substantive unaddressed findings escalate instead of auto-approving. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(pr-review): match [bot]-suffixed REST logins; slurp paginated comments Codex follow-up findings on the ADVISORY_BOT_FEEDBACK prefetch: - REST pulls/comments user.login carries a "[bot]" suffix (unlike the GraphQL-backed gh pr view), so the advisory filter matched nothing — strip the suffix before matching (verified live: 33 matches vs 0). - --paginate without --slurp emits one JSON array per page, so the sort/limit applied per page; gh rejects --slurp with --jq, so pipe to external jq and flatten with add. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(pr-review): head-bound, supersede-aware advisory feedback incl. PR comments Codex follow-up findings on the ADVISORY_BOT_FEEDBACK prefetch: - include PR-level (issue) comments from advisory bots — the gate counts them as submissions (e.g. SonarCloud's quality-gate report) so the triage prompt must see them too; newest per bot - group/sort per bot BEFORE dropping empty bodies, so a later empty approval suppresses an older findings body instead of resurrecting it - bound reviews and inline comments to PR_HEAD_SHA so findings already addressed by newer pushes don't cause false escalation - reuse PR_SNAPSHOT for reviews/PR comments (no extra API calls) Verified against fixtures: old-head reviews excluded, empty-latest-review suppression works, newest PR comment per bot selected, humans excluded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: apply manual instructions [skip ci-relay] * chore: apply manual instructions [skip ci-relay] --------- Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com> Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
Dev-Lead — rebase (no-changes)Agent reasoning |
CI Failure: .github/dependabot.ymlStep: Dependabot config validation The Suggested fix: Restore |
Dev-Lead Fix CI — appliedPR: #383 | SHA: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d259efe7f1
ℹ️ 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".
| run_member security claude-opus-4-6 prompts/council/security.md & | ||
| PID_SEC=$! | ||
| run_member correctness claude-sonnet-4-6 prompts/council/correctness.md & | ||
| PID_COR=$! | ||
| run_member maintainability claude-sonnet-4-6 prompts/council/maintainability.md & |
There was a problem hiding this comment.
Restore PR diff prefetch before triage
This inserted block replaces the only gh pr diff fetch and PR_DIFF assignment, but the script still runs with set -u and later expands $PR_DIFF while building TRIAGE_PROMPT_FILE. For any PR that gets past metadata prefetch, the review aborts with PR_DIFF: unbound variable before tier-1 triage can run, so restore the diff prefetch or initialize PR_DIFF before this point.
Useful? React with 👍 / 👎.
| schedule: | ||
| # Every 15 min to ensure at least one run fires per hour | ||
| # (GitHub Actions scheduled runs can be delayed/skipped under load) | ||
| - cron: "7 * * * *" | ||
| - cron: "22 * * * *" | ||
| - cron: "37 * * * *" | ||
| - cron: "52 * * * *" |
There was a problem hiding this comment.
Restore event-driven PR review triggers
This on: block now only has schedule/manual/dispatch triggers, removing the previous check_suite, pull_request_review, and pull_request events even though the job condition and env still contain logic for those payloads. In the inspected workflow, CI completion, review dismissal/approval, and new PR commits will no longer dispatch the reviewer at all, so reviews are delayed until a cron/manual/mention path happens to cover the PR instead of waking on the event that made it reviewable.
Useful? React with 👍 / 👎.
| on: | ||
| workflow_call: | ||
| secrets: | ||
| CLAUDE_CODE_OAUTH_TOKEN: | ||
| required: false | ||
| GOOGLE_API_KEY: | ||
| required: false | ||
| COPILOT_GITHUB_TOKEN: | ||
| required: false | ||
| DON_PETRY_BOT_GH_PAT: | ||
| required: false | ||
| GH_PAT: | ||
| required: false | ||
|
|
||
| # ── Event-driven triggers ──────────────────────────────────────────────── | ||
| # These replace the former time-based schedule. The review engine's own | ||
| # idempotency check (head-SHA marker) prevents duplicate reviews, so | ||
| # firing multiple times on the same PR is always safe. | ||
| # | ||
| # Coverage note: these events are scoped to this repo (.github-private). | ||
| # For org-wide event-driven triggering (broodly, markets, etc.), deploy | ||
| # a thin pr-review-auto-trigger.yml caller stub to each repo (Phase 2). | ||
|
|
||
| check_suite: | ||
| # Fires when a CI check suite completes on any branch in this repo. | ||
| # We only act when the suite succeeded (failing/pending PRs are already | ||
| # skipped by review-one-pr.sh's CI gate, but filtering here avoids | ||
| # spinning up a runner at all). Empty pull_requests arrays (e.g. pushes | ||
| # to main) are dropped in the job condition below. | ||
| types: [completed] | ||
|
|
||
| pull_request_review: | ||
| # Fires when a reviewer submits a review or dismisses one. | ||
| # submitted — covers APPROVED (green light) and CHANGES_REQUESTED | ||
| # (agent will skip via its own gate, but APPROVED is the | ||
| # common case that unlocks a previously-blocked PR). | ||
| # dismissed — a CHANGES_REQUESTED review was dismissed, clearing the | ||
| # block so the agent can re-engage with the updated code. | ||
| types: [submitted, dismissed] | ||
|
|
||
| pull_request: | ||
| # ready_for_review — draft PR promoted to open (ready for first review). | ||
| # reopened — closed PR is reopened (e.g. after revision). | ||
| # synchronize — new commits pushed (author addressed review comments); | ||
| # CI will be pending immediately, so review-one-pr.sh | ||
| # skips cheaply — the check_suite trigger fires once CI | ||
| # settles and is the real wake signal post-push. | ||
| types: [ready_for_review, reopened, synchronize] | ||
|
|
||
| # ── Manual / programmatic triggers ────────────────────────────────────── | ||
| schedule: |
There was a problem hiding this comment.
Restore workflow_call for reusable callers
Fresh evidence beyond the earlier resolved thread is that the current on: block still starts with schedule and has no workflow_call, while .github/workflows/pr-review-reusable.yml still invokes this file with uses: petry-projects/.github-private/.github/workflows/pr-review.yml@main. Cross-repo reusable dispatches will therefore be rejected before the review job starts, so add the workflow_call trigger back or update the wrapper to call a reusable workflow.
Useful? React with 👍 / 👎.
| if [ -z "${HEAD_SHA:-}" ]; then | ||
| HEAD_SHA=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.head.sha' 2>/dev/null || true) | ||
| fi | ||
| checkout_pr_in_worktree "$PR_NUMBER" "$REPO" |
There was a problem hiding this comment.
Remove repeated worktree checkouts
Fresh evidence beyond the earlier outdated checkout thread is that this non-dry-run path now performs consecutive checkout_pr_in_worktree calls. That helper cds into a new temp worktree and stores only the latest path in the global cleanup state, so later duplicate calls overwrite the cleanup target and leave the earlier temp worktrees registered under /tmp after the run.
Useful? React with 👍 / 👎.
| # | ||
| # Sets _GEMINI_CHAIN_MODEL_USED to the model that produced the final output | ||
| # (success or last attempt) so callers can log which model actually ran. | ||
| _gemini_chain_invoke() { |
There was a problem hiding this comment.
Route Gemini triage through an existing helper
This new _gemini_chain_invoke replaces the deleted _gemini_invoke, but the active run_triage Gemini branch still calls _gemini_invoke and there is no definition left in scripts/engine.sh. When REVIEW_ENGINE=gemini, tier-1 triage hits command not found instead of reviewing the PR, so migrate that branch to _gemini_chain_invoke or restore the wrapper.
Useful? React with 👍 / 👎.
| else | ||
| printf '%s' "${TOKEN_LOG_FILE}.last-usage.$$" | ||
| fi | ||
| printf '%s' "${TOKEN_LOG_FILE}.last-usage.${BASHPID}" |
There was a problem hiding this comment.
Keep token sidecars stable when reading usage
Fresh evidence beyond the earlier sidecar thread is that the current _record_engine_tokens still obtains the sidecar path via command substitution in scripts/engine.sh, so this BASHPID is computed in a new subshell rather than the process that ran parse_engine_usage. Token-logged Claude/Gemini calls therefore miss the real usage file and fall back to estimates; use the exported per-call sidecar or compute the same path without command substitution.
Useful? React with 👍 / 👎.
| - cron: "7 * * * *" | ||
| - cron: "22 * * * *" | ||
| - cron: "37 * * * *" | ||
| - cron: "52 * * * *" |
There was a problem hiding this comment.
Avoid canceling scheduled batch reviews
Fresh evidence beyond the earlier resolved schedule thread is that these 15-minute cron entries still run with no PR URL, so the current concurrency expression falls through to the shared pr-review-batch group with cancel-in-progress: true. Any scheduled batch that takes longer than 15 minutes can be canceled by the next schedule before it writes review markers, so schedule runs need a unique or non-canceling group.
Useful? React with 👍 / 👎.
|
@dev-lead CI blocker (ShellCheck SC2034, real bug) in Please make the code act on |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47587177a6
ℹ️ 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".
| # are empty; passing them would clobber the timestamp parse_reset_time | ||
| # already wrote inside the loop for each throttled response. | ||
| if [ -n "$final_stdout" ] || [ -n "$final_stderr" ]; then | ||
| parse_reset_time_files "$final_stdout" "$final_stderr" |
There was a problem hiding this comment.
Preserve Claude reset time across throttled chain
When a Claude model chain exhausts through the normal temp-file path and an earlier throttled model reports a reset time but the final throttled model does not, this parses only the final attempt's files. parse_reset_time_files clears /tmp/dev-lead-rate-limit-reset when no timestamp is found, and dev-lead-retry.sh:is_reset_in_future treats an empty reset as ready to retry, so the retry cron can immediately redispatch before the Claude quota actually resets; keep the last non-empty reset from any throttled Claude attempt, as the Gemini chain does.
Useful? React with 👍 / 👎.
| _diff_limit=1000 | ||
| else | ||
| _diff_limit=3000 | ||
| run_member security claude-opus-4-6 prompts/council/security.md & |
There was a problem hiding this comment.
Remove the undefined council calls before triage
For any PR that gets past metadata prefetch, this new run_member invocation aborts the script before tier-1 triage because there is no run_member function or command in the repo (I checked with rg "run_member"), and the referenced prompts/council/*.md files are also absent. With set -e active, scheduled/manual PR review runs fail here instead of producing a review; either add the council implementation/assets or remove this block.
Useful? React with 👍 / 👎.
| claude) | ||
| unset COPILOT_GITHUB_TOKEN 2>/dev/null || true | ||
| unset GOOGLE_API_KEY 2>/dev/null || true | ||
| if [ -n "$_tok_tmp" ] && [ "$_duck_usage_json" -eq 1 ]; then |
There was a problem hiding this comment.
Initialize duck usage mode in the active helper
When token logging is enabled (TOKEN_LOG_FILE set) and the rubber-duck engine is Claude, this active later run_duck definition reaches $_duck_usage_json without defining it; the only initializer is in an earlier run_duck definition that Bash has already shadowed. Because engine.sh runs with set -u, the duck reviewer exits with an unbound-variable error before it can produce /tmp/cascade/rubber-duck.json; carry the _duck_usage_json initialization into this final definition.
Useful? React with 👍 / 👎.
| if [ -n "$_tok_tmp" ]; then | ||
| _gemini_invoke "$prompt_file" "$TRIAGE_TIMEOUT_SEC" "$ENGINE_TRIAGE_MODEL" \ | ||
| _gemini_chain_invoke "$_triage_chain" "$prompt_file" "$TRIAGE_TIMEOUT_SEC" \ | ||
| --approval-mode auto_edit | tee "$_tok_tmp" || rc=${PIPESTATUS[0]} |
There was a problem hiding this comment.
Pass Gemini triage approval mode positionally
When REVIEW_ENGINE=gemini, _gemini_chain_invoke treats its fourth argument as the approval-mode value, but this call passes a flag pair instead. That makes the actual CLI invocation --approval-mode --approval-mode auto_edit, so Gemini triage fails with a command-format error before reviewing any PR; pass the mode value positionally (for example plan) rather than another --approval-mode flag.
Useful? React with 👍 / 👎.
Dev-Lead — review-changes (applied)Changes committed and pushed. |
|
Dev-Lead — waiting on PR blockers (intent: review-changes)PR: #383 |
|
Note @don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c47077f255
ℹ️ 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".
| else | ||
| printf '%s' "${TOKEN_LOG_FILE}.last-usage.$$" | ||
| fi | ||
| printf '%s' "${TOKEN_LOG_FILE}.last-usage.${BASHPID}" |
There was a problem hiding this comment.
Clear the same usage sidecar before parsing
Because the sidecar name now depends on BASHPID, the existing f="$(_engine_usage_sidecar)" calls in reset_engine_usage/parse_engine_usage compute the path in a command-substitution subshell rather than the caller process. With TOKEN_LOG_FILE enabled, a successful JSON-mode call leaves .last-usage.<caller-BASHPID> behind; if the next engine response has no parseable usage block, reset removes the wrong file and _record_engine_tokens reads the stale usage from the prior call instead of falling back to estimates, corrupting token records across calls.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/review-one-pr.sh (1)
422-425:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
PR_DIFFis used without initialization and will hard-fail under strict mode.Line 614 expands
"$PR_DIFF"but no assignment is present before prompt construction; withset -u, this exits the script before tier 1 completes.Suggested fix
_gh_meta_err=/tmp/cascade/gh-meta-prefetch.err _gh_diff_err=/tmp/cascade/gh-diff-prefetch.err _gh_diff_tmp=/tmp/cascade/gh-diff-raw.txt @@ PR_METADATA=$(gh pr view "$PR_URL" --json "$_meta_fields,files" --jq ' @@ ' 2>"$_gh_meta_err") || { @@ } + +PR_DIFF=$(gh pr diff "$PR_URL" 2>"$_gh_diff_err" || true) +if [ -z "${PR_DIFF:-}" ] && [ -s "$_gh_diff_err" ]; then + _gh_diff_err_content=$(cat "$_gh_diff_err" 2>/dev/null || true) + if is_rate_limited "$_gh_diff_err_content"; then + echo "{\"pr\":\"$PR_URL\",\"sha\":\"$PR_HEAD_SHA\",\"decision\":\"skip\",\"reason\":\"gh-rate-limited\"}" + exit 100 + fi +fiAlso applies to: 613-615
🤖 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 `@scripts/review-one-pr.sh` around lines 422 - 425, PR_DIFF is referenced without initialization causing failures under set -u; initialize it (e.g., PR_DIFF="") alongside other top-level temp vars or change expansions where it's used (the prompt construction that expands "$PR_DIFF") to use a safe default like "${PR_DIFF:-}" so the script won't hard-fail; apply the same fix to the other occurrences that expand PR_DIFF (the nearby prompt/usage sites).
🤖 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 `@prompts/dev-lead/fix-bot-comment.md`:
- Around line 106-131: Remove the duplicated "## SonarQube / SonarCloud
comments" section (the second repeated block) so the prompt contains only one
canonical instance of that heading and its steps; locate the duplicate by
searching for the exact heading text "## SonarQube / SonarCloud comments" and
the repeated list of steps (Script injection, Hardcoded credentials, Dynamic
code execution, Insecure download) and delete the extra copy, ensuring the
remaining single section preserves the original wording and ordering.
In `@prompts/dev-lead/fix-reviews.md`:
- Around line 105-124: The file contains duplicate instruction blocks titled
"Phase 2 — Test Verification" and "Phase 3 — Rubber Duck Review"; remove the
redundant copies and keep a single canonical "Phase 2 — Test Verification" block
and a single canonical "Phase 3 — Rubber Duck Review" block (preserve content
such as steps 1–4 under Phase 2 and steps 1–6 under Phase 3), updating any
cross-references if needed so there is only one authoritative instance of each
heading and no repeated instructions that would increase token usage or cause
repeated execution.
In `@scripts/dev-lead-fix-reviews.sh`:
- Around line 82-850: There are duplicated function suites; the later
definitions shadow the earlier ones and drop important logic — remove the
dead/duplicated first set (the earlier build_and_run..handle_rate_limit block)
and ensure the kept definitions merge the missing pieces: in fetch_pr_context
preserve the advanced check-run dedup Stage 1/Stage 2 logic (the group_by +
filter that fixes issue `#461`), in try_enable_auto_merge honor _AM_MERGE_METHOD
and include optional _AM_COMMIT_TITLE/_AM_COMMIT_MESSAGE handling rather than
hardcoding squash, and in commit_and_push retain the safer push_with_merge_guard
call (instead of a plain git push); update the final definitions of
fetch_pr_context, try_enable_auto_merge, and commit_and_push to include these
behaviors and delete the duplicate prior implementations so only one
authoritative version remains.
- Around line 30-80: The checkout/worktree sequence is duplicated three times;
remove the redundant copies and keep a single block that runs when
DEV_LEAD_DRY_RUN is false and PR_NUMBER is set, preserving the trap
restore_auto_merge EXIT, the hold_auto_merge call, the HEAD_SHA resolution logic
(if [ -z "${HEAD_SHA:-}" ] ...), checkout_pr_in_worktree "$PR_NUMBER" "$REPO",
and setup_git_identity; ensure calls to restore_auto_merge, hold_auto_merge,
checkout_pr_in_worktree, and setup_git_identity appear only once to avoid
duplicate API/trap/worktree operations.
In `@scripts/engine.sh`:
- Around line 773-819: There are multiple duplicated function definitions
(notably run_duck, run_writer, run_writer_with_fallback and several parsing
helpers) which cause last-definition shadowing and unbound-variable risks (e.g.
use of _duck_usage_json under set -u). Remove the duplicate/older redefinitions
and keep one canonical implementation per function (search for run_duck,
run_writer, run_writer_with_fallback and the parsing helper names and delete
extras), and ensure any variables used across callers are initialized (e.g.
initialize _duck_usage_json with a default value or use ${_duck_usage_json:-""}
before use, or declare -g/_local with a default) and add guards where
token-logging paths rely on them to avoid unbound-variable errors.
- Around line 861-865: The triage invocation is passing --approval-mode as extra
args which _gemini_chain_invoke treats incorrectly (arg 4 is the mode) and
accidentally enables edit-capable triage; change both calls that use
_gemini_chain_invoke with _triage_chain to pass "plan" as the 4th positional
argument (i.e., _gemini_chain_invoke "$_triage_chain" "$prompt_file" "plan"
"$TRIAGE_TIMEOUT_SEC") and move the approval flag back to the proper
positional/optional handling so triage remains in no-edit mode and approval_mode
is passed positionally; update both the tee branch and the else branch
invocations of _gemini_chain_invoke accordingly.
In `@scripts/review-one-pr.sh`:
- Around line 450-478: The script currently always launches three council
run_member processes (run_member ... producing
/tmp/council/{security,correctness,maintainability}.json) and then only warns on
failures even though no later step reads those JSON results; to fix, gate the
whole council fan-out and its subsequent wait/validation block behind a feature
flag (e.g. check ENABLE_COUNCIL or an equivalent env var) or remove the launches
if unused: wrap the run_member calls, the PID_SEC/PID_COR/PID_MAI vars, the wait
... || { ... FAILED=1; } lines, and the for loop that validates
/tmp/council/*.json in a single if [ "$ENABLE_COUNCIL" = "true" ] ... fi block
(or call a new function run_council) so we only incur cost when the council
outputs will actually be consumed.
In `@tests/dev-lead/unit/test_fix_reviews.bats`:
- Around line 2210-2496: There are two conflicting fetch_pr_context functions
and the active one (the second fetch_pr_context) is missing the advanced
check-run dedup logic present in the first definition (the group_by/sort_by
dedup that handles superseded cancelled runs, cross-suite matching, and id-based
tie-breaks); fix this by removing the duplicate/older fetch_pr_context
definition and merging or copying the dedup block from the first
fetch_pr_context into the single active fetch_pr_context (preserving the stage-1
per-suite grouping and the stage-2 cross-suite dedup that uses name+app and
id-based sort), so the tests like "superseded cancelled check run is not a hard
blocker", "same app different suites — superseded cancelled run is dropped", and
"queued check run without started_at wins over older cancelled run by id"
exercise the intended logic.
- Around line 502-586: The test file contains repeated Bats test blocks — remove
the duplicate occurrences and keep a single copy of each test: "no-changes path
also calls notify_coderabbit_resolve", "try_enable_auto_merge dry-run output
present for fix-reviews", "try_enable_auto_merge dry-run output present for
fix-bot-comment", and "try_enable_auto_merge dry-run output present for
review-changes"; locate the duplicated test blocks by those exact test names and
delete the extra copies so each test appears only once, preserving the original
environment exports and assertions from the remaining single instance.
---
Outside diff comments:
In `@scripts/review-one-pr.sh`:
- Around line 422-425: PR_DIFF is referenced without initialization causing
failures under set -u; initialize it (e.g., PR_DIFF="") alongside other
top-level temp vars or change expansions where it's used (the prompt
construction that expands "$PR_DIFF") to use a safe default like "${PR_DIFF:-}"
so the script won't hard-fail; apply the same fix to the other occurrences that
expand PR_DIFF (the nearby prompt/usage sites).
🪄 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: df235b2b-6d2e-423e-8a8e-b0cb6eca751c
📒 Files selected for processing (18)
.github/workflows/pr-review.yml.gitleaksignoredocs/engine-model-rollout.mdprompts/dev-lead/fix-bot-comment.mdprompts/dev-lead/fix-reviews.mdscripts/dev-lead-fix-reviews.shscripts/engine.shscripts/lib/git-identity.shscripts/lib/token-metrics.shscripts/list-prs.shscripts/review-one-pr.shtests/dev-lead/fixtures/engines/stub-geminitests/dev-lead/unit/test_engine_chain.batstests/dev-lead/unit/test_engine_gemini_chain.batstests/dev-lead/unit/test_engine_writer.batstests/dev-lead/unit/test_fix_reviews.batstests/dev-lead/unit/test_token_metrics.batstests/token_report.bats
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/review-one-pr.sh (1)
422-425:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
PR_DIFFis used without initialization and will hard-fail under strict mode.Line 614 expands
"$PR_DIFF"but no assignment is present before prompt construction; withset -u, this exits the script before tier 1 completes.Suggested fix
_gh_meta_err=/tmp/cascade/gh-meta-prefetch.err _gh_diff_err=/tmp/cascade/gh-diff-prefetch.err _gh_diff_tmp=/tmp/cascade/gh-diff-raw.txt @@ PR_METADATA=$(gh pr view "$PR_URL" --json "$_meta_fields,files" --jq ' @@ ' 2>"$_gh_meta_err") || { @@ } + +PR_DIFF=$(gh pr diff "$PR_URL" 2>"$_gh_diff_err" || true) +if [ -z "${PR_DIFF:-}" ] && [ -s "$_gh_diff_err" ]; then + _gh_diff_err_content=$(cat "$_gh_diff_err" 2>/dev/null || true) + if is_rate_limited "$_gh_diff_err_content"; then + echo "{\"pr\":\"$PR_URL\",\"sha\":\"$PR_HEAD_SHA\",\"decision\":\"skip\",\"reason\":\"gh-rate-limited\"}" + exit 100 + fi +fiAlso applies to: 613-615
🤖 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 `@scripts/review-one-pr.sh` around lines 422 - 425, PR_DIFF is referenced without initialization causing failures under set -u; initialize it (e.g., PR_DIFF="") alongside other top-level temp vars or change expansions where it's used (the prompt construction that expands "$PR_DIFF") to use a safe default like "${PR_DIFF:-}" so the script won't hard-fail; apply the same fix to the other occurrences that expand PR_DIFF (the nearby prompt/usage sites).
🤖 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 `@prompts/dev-lead/fix-bot-comment.md`:
- Around line 106-131: Remove the duplicated "## SonarQube / SonarCloud
comments" section (the second repeated block) so the prompt contains only one
canonical instance of that heading and its steps; locate the duplicate by
searching for the exact heading text "## SonarQube / SonarCloud comments" and
the repeated list of steps (Script injection, Hardcoded credentials, Dynamic
code execution, Insecure download) and delete the extra copy, ensuring the
remaining single section preserves the original wording and ordering.
In `@prompts/dev-lead/fix-reviews.md`:
- Around line 105-124: The file contains duplicate instruction blocks titled
"Phase 2 — Test Verification" and "Phase 3 — Rubber Duck Review"; remove the
redundant copies and keep a single canonical "Phase 2 — Test Verification" block
and a single canonical "Phase 3 — Rubber Duck Review" block (preserve content
such as steps 1–4 under Phase 2 and steps 1–6 under Phase 3), updating any
cross-references if needed so there is only one authoritative instance of each
heading and no repeated instructions that would increase token usage or cause
repeated execution.
In `@scripts/dev-lead-fix-reviews.sh`:
- Around line 82-850: There are duplicated function suites; the later
definitions shadow the earlier ones and drop important logic — remove the
dead/duplicated first set (the earlier build_and_run..handle_rate_limit block)
and ensure the kept definitions merge the missing pieces: in fetch_pr_context
preserve the advanced check-run dedup Stage 1/Stage 2 logic (the group_by +
filter that fixes issue `#461`), in try_enable_auto_merge honor _AM_MERGE_METHOD
and include optional _AM_COMMIT_TITLE/_AM_COMMIT_MESSAGE handling rather than
hardcoding squash, and in commit_and_push retain the safer push_with_merge_guard
call (instead of a plain git push); update the final definitions of
fetch_pr_context, try_enable_auto_merge, and commit_and_push to include these
behaviors and delete the duplicate prior implementations so only one
authoritative version remains.
- Around line 30-80: The checkout/worktree sequence is duplicated three times;
remove the redundant copies and keep a single block that runs when
DEV_LEAD_DRY_RUN is false and PR_NUMBER is set, preserving the trap
restore_auto_merge EXIT, the hold_auto_merge call, the HEAD_SHA resolution logic
(if [ -z "${HEAD_SHA:-}" ] ...), checkout_pr_in_worktree "$PR_NUMBER" "$REPO",
and setup_git_identity; ensure calls to restore_auto_merge, hold_auto_merge,
checkout_pr_in_worktree, and setup_git_identity appear only once to avoid
duplicate API/trap/worktree operations.
In `@scripts/engine.sh`:
- Around line 773-819: There are multiple duplicated function definitions
(notably run_duck, run_writer, run_writer_with_fallback and several parsing
helpers) which cause last-definition shadowing and unbound-variable risks (e.g.
use of _duck_usage_json under set -u). Remove the duplicate/older redefinitions
and keep one canonical implementation per function (search for run_duck,
run_writer, run_writer_with_fallback and the parsing helper names and delete
extras), and ensure any variables used across callers are initialized (e.g.
initialize _duck_usage_json with a default value or use ${_duck_usage_json:-""}
before use, or declare -g/_local with a default) and add guards where
token-logging paths rely on them to avoid unbound-variable errors.
- Around line 861-865: The triage invocation is passing --approval-mode as extra
args which _gemini_chain_invoke treats incorrectly (arg 4 is the mode) and
accidentally enables edit-capable triage; change both calls that use
_gemini_chain_invoke with _triage_chain to pass "plan" as the 4th positional
argument (i.e., _gemini_chain_invoke "$_triage_chain" "$prompt_file" "plan"
"$TRIAGE_TIMEOUT_SEC") and move the approval flag back to the proper
positional/optional handling so triage remains in no-edit mode and approval_mode
is passed positionally; update both the tee branch and the else branch
invocations of _gemini_chain_invoke accordingly.
In `@scripts/review-one-pr.sh`:
- Around line 450-478: The script currently always launches three council
run_member processes (run_member ... producing
/tmp/council/{security,correctness,maintainability}.json) and then only warns on
failures even though no later step reads those JSON results; to fix, gate the
whole council fan-out and its subsequent wait/validation block behind a feature
flag (e.g. check ENABLE_COUNCIL or an equivalent env var) or remove the launches
if unused: wrap the run_member calls, the PID_SEC/PID_COR/PID_MAI vars, the wait
... || { ... FAILED=1; } lines, and the for loop that validates
/tmp/council/*.json in a single if [ "$ENABLE_COUNCIL" = "true" ] ... fi block
(or call a new function run_council) so we only incur cost when the council
outputs will actually be consumed.
In `@tests/dev-lead/unit/test_fix_reviews.bats`:
- Around line 2210-2496: There are two conflicting fetch_pr_context functions
and the active one (the second fetch_pr_context) is missing the advanced
check-run dedup logic present in the first definition (the group_by/sort_by
dedup that handles superseded cancelled runs, cross-suite matching, and id-based
tie-breaks); fix this by removing the duplicate/older fetch_pr_context
definition and merging or copying the dedup block from the first
fetch_pr_context into the single active fetch_pr_context (preserving the stage-1
per-suite grouping and the stage-2 cross-suite dedup that uses name+app and
id-based sort), so the tests like "superseded cancelled check run is not a hard
blocker", "same app different suites — superseded cancelled run is dropped", and
"queued check run without started_at wins over older cancelled run by id"
exercise the intended logic.
- Around line 502-586: The test file contains repeated Bats test blocks — remove
the duplicate occurrences and keep a single copy of each test: "no-changes path
also calls notify_coderabbit_resolve", "try_enable_auto_merge dry-run output
present for fix-reviews", "try_enable_auto_merge dry-run output present for
fix-bot-comment", and "try_enable_auto_merge dry-run output present for
review-changes"; locate the duplicated test blocks by those exact test names and
delete the extra copies so each test appears only once, preserving the original
environment exports and assertions from the remaining single instance.
---
Outside diff comments:
In `@scripts/review-one-pr.sh`:
- Around line 422-425: PR_DIFF is referenced without initialization causing
failures under set -u; initialize it (e.g., PR_DIFF="") alongside other
top-level temp vars or change expansions where it's used (the prompt
construction that expands "$PR_DIFF") to use a safe default like "${PR_DIFF:-}"
so the script won't hard-fail; apply the same fix to the other occurrences that
expand PR_DIFF (the nearby prompt/usage sites).
🪄 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: df235b2b-6d2e-423e-8a8e-b0cb6eca751c
📒 Files selected for processing (18)
.github/workflows/pr-review.yml.gitleaksignoredocs/engine-model-rollout.mdprompts/dev-lead/fix-bot-comment.mdprompts/dev-lead/fix-reviews.mdscripts/dev-lead-fix-reviews.shscripts/engine.shscripts/lib/git-identity.shscripts/lib/token-metrics.shscripts/list-prs.shscripts/review-one-pr.shtests/dev-lead/fixtures/engines/stub-geminitests/dev-lead/unit/test_engine_chain.batstests/dev-lead/unit/test_engine_gemini_chain.batstests/dev-lead/unit/test_engine_writer.batstests/dev-lead/unit/test_fix_reviews.batstests/dev-lead/unit/test_token_metrics.batstests/token_report.bats
🛑 Comments failed to post (9)
prompts/dev-lead/fix-bot-comment.md (1)
106-131: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Remove duplicated SonarCloud sections to keep the prompt deterministic.
The same “SonarQube / SonarCloud comments” instructions are repeated twice after the original block, which unnecessarily bloats context and can skew agent behavior toward that subsection.
🤖 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 `@prompts/dev-lead/fix-bot-comment.md` around lines 106 - 131, Remove the duplicated "## SonarQube / SonarCloud comments" section (the second repeated block) so the prompt contains only one canonical instance of that heading and its steps; locate the duplicate by searching for the exact heading text "## SonarQube / SonarCloud comments" and the repeated list of steps (Script injection, Hardcoded credentials, Dynamic code execution, Insecure download) and delete the extra copy, ensuring the remaining single section preserves the original wording and ordering.prompts/dev-lead/fix-reviews.md (1)
105-124: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Deduplicate repeated Phase 2/3 instructions.
These added blocks duplicate the same “Test Verification” and “Rubber Duck Review” steps that already exist, increasing token usage and risking repetitive execution behavior in the agent.
🤖 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 `@prompts/dev-lead/fix-reviews.md` around lines 105 - 124, The file contains duplicate instruction blocks titled "Phase 2 — Test Verification" and "Phase 3 — Rubber Duck Review"; remove the redundant copies and keep a single canonical "Phase 2 — Test Verification" block and a single canonical "Phase 3 — Rubber Duck Review" block (preserve content such as steps 1–4 under Phase 2 and steps 1–6 under Phase 3), updating any cross-references if needed so there is only one authoritative instance of each heading and no repeated instructions that would increase token usage or cause repeated execution.scripts/dev-lead-fix-reviews.sh (2)
30-80:
⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Checkout logic is duplicated three times.
Lines 30-50, 52-72, and 74-80 contain overlapping/duplicate checkout blocks that will all execute sequentially when
DEV_LEAD_DRY_RUN=false. This appears to be a merge conflict artifact or automated agent copy-paste error.Effects:
trap restore_auto_merge EXITis set twice (second overwrites first — safe but wasteful)hold_auto_mergecalled twice (may be idempotent, but double API calls)checkout_pr_in_worktreecalled twice (second call may fail or no-op depending on implementation)setup_git_identitycalled three timesRemove the duplicate blocks and keep only one checkout sequence.
🤖 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 `@scripts/dev-lead-fix-reviews.sh` around lines 30 - 80, The checkout/worktree sequence is duplicated three times; remove the redundant copies and keep a single block that runs when DEV_LEAD_DRY_RUN is false and PR_NUMBER is set, preserving the trap restore_auto_merge EXIT, the hold_auto_merge call, the HEAD_SHA resolution logic (if [ -z "${HEAD_SHA:-}" ] ...), checkout_pr_in_worktree "$PR_NUMBER" "$REPO", and setup_git_identity; ensure calls to restore_auto_merge, hold_auto_merge, checkout_pr_in_worktree, and setup_git_identity appear only once to avoid duplicate API/trap/worktree operations.
82-850:
⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftCritical: Entire function suite is duplicated with conflicting implementations.
The file contains two complete sets of function definitions. Due to Bash's sequential evaluation, the second definitions (lines 852-1651) shadow the first (lines 82-850), making the first set dead code. However, some first-set implementations contain important logic that's missing from the second set:
Function First def has Second def has Effect fetch_pr_contextAdvanced check-run dedup (issue #461fix)Simple version Loses dedup logic try_enable_auto_merge_AM_MERGE_METHOD, commit title/messageHardcoded squash Loses customization commit_and_pushpush_with_merge_guardPlain git pushLoses safety guard This appears to be a merge/rebase conflict that was resolved by keeping both versions instead of merging them. The entire first set (lines 82-850) should either be removed or properly merged with the second set.
The advanced
fetch_pr_contextcheck-run dedup logic (lines 276-293) that fixes issue#461is particularly concerning — it exists only in the dead-code first definition.🤖 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 `@scripts/dev-lead-fix-reviews.sh` around lines 82 - 850, There are duplicated function suites; the later definitions shadow the earlier ones and drop important logic — remove the dead/duplicated first set (the earlier build_and_run..handle_rate_limit block) and ensure the kept definitions merge the missing pieces: in fetch_pr_context preserve the advanced check-run dedup Stage 1/Stage 2 logic (the group_by + filter that fixes issue `#461`), in try_enable_auto_merge honor _AM_MERGE_METHOD and include optional _AM_COMMIT_TITLE/_AM_COMMIT_MESSAGE handling rather than hardcoding squash, and in commit_and_push retain the safer push_with_merge_guard call (instead of a plain git push); update the final definitions of fetch_pr_context, try_enable_auto_merge, and commit_and_push to include these behaviors and delete the duplicate prior implementations so only one authoritative version remains.scripts/engine.sh (2)
773-819:
⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftRemove duplicated function redefinitions; they are shadowing behavior and reintroducing runtime risk.
The file redefines core functions multiple times (e.g.
run_duck,run_writer,run_writer_with_fallback, parsing helpers). In Bash, the last definition wins. This creates dead code and behavior drift; e.g., the laterrun_duckpath uses$_duck_usage_jsonwithout guaranteed initialization underset -u(unbound variable abort risk when token logging is enabled).Also applies to: 1383-1415, 1417-1884, 2304-2341
🤖 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 `@scripts/engine.sh` around lines 773 - 819, There are multiple duplicated function definitions (notably run_duck, run_writer, run_writer_with_fallback and several parsing helpers) which cause last-definition shadowing and unbound-variable risks (e.g. use of _duck_usage_json under set -u). Remove the duplicate/older redefinitions and keep one canonical implementation per function (search for run_duck, run_writer, run_writer_with_fallback and the parsing helper names and delete extras), and ensure any variables used across callers are initialized (e.g. initialize _duck_usage_json with a default value or use ${_duck_usage_json:-""} before use, or declare -g/_local with a default) and add guards where token-logging paths rely on them to avoid unbound-variable errors.
861-865:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winPass
approval_modepositionally and keep triage in no-edit mode.Line 861/864 currently pass
--approval-mode auto_editas extra args, but_gemini_chain_invokereads arg 4 as the mode. This makes arg parsing wrong and also enables edit-capable triage. Pass"plan"as the 4th arg.Suggested fix
- _gemini_chain_invoke "$_triage_chain" "$prompt_file" "$TRIAGE_TIMEOUT_SEC" \ - --approval-mode auto_edit | tee "$_tok_tmp" || rc=${PIPESTATUS[0]} + _gemini_chain_invoke "$_triage_chain" "$prompt_file" "$TRIAGE_TIMEOUT_SEC" \ + "plan" | tee "$_tok_tmp" || rc=${PIPESTATUS[0]} @@ - _gemini_chain_invoke "$_triage_chain" "$prompt_file" "$TRIAGE_TIMEOUT_SEC" \ - --approval-mode auto_edit || rc=$? + _gemini_chain_invoke "$_triage_chain" "$prompt_file" "$TRIAGE_TIMEOUT_SEC" \ + "plan" || rc=$?🤖 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 `@scripts/engine.sh` around lines 861 - 865, The triage invocation is passing --approval-mode as extra args which _gemini_chain_invoke treats incorrectly (arg 4 is the mode) and accidentally enables edit-capable triage; change both calls that use _gemini_chain_invoke with _triage_chain to pass "plan" as the 4th positional argument (i.e., _gemini_chain_invoke "$_triage_chain" "$prompt_file" "plan" "$TRIAGE_TIMEOUT_SEC") and move the approval flag back to the proper positional/optional handling so triage remains in no-edit mode and approval_mode is passed positionally; update both the tee branch and the else branch invocations of _gemini_chain_invoke accordingly.scripts/review-one-pr.sh (1)
450-478:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winCouncil fan-out runs unconditionally, but its outputs are never consumed.
This block triggers three extra model runs per PR and only logs warnings; no later step reads
/tmp/council/*.json. That adds latency/cost and increases rate-limit exposure without affecting decisions.🤖 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 `@scripts/review-one-pr.sh` around lines 450 - 478, The script currently always launches three council run_member processes (run_member ... producing /tmp/council/{security,correctness,maintainability}.json) and then only warns on failures even though no later step reads those JSON results; to fix, gate the whole council fan-out and its subsequent wait/validation block behind a feature flag (e.g. check ENABLE_COUNCIL or an equivalent env var) or remove the launches if unused: wrap the run_member calls, the PID_SEC/PID_COR/PID_MAI vars, the wait ... || { ... FAILED=1; } lines, and the for loop that validates /tmp/council/*.json in a single if [ "$ENABLE_COUNCIL" = "true" ] ... fi block (or call a new function run_council) so we only incur cost when the council outputs will actually be consumed.tests/dev-lead/unit/test_fix_reviews.bats (2)
502-586:
⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Test definitions are duplicated/triplicated.
The following tests appear multiple times with identical names:
Test name Occurrences no-changes path also calls notify_coderabbit_resolveLines 385, 502, 545 try_enable_auto_merge dry-run output present for fix-reviewsLines 395, 512, 555 try_enable_auto_merge dry-run output present for fix-bot-commentLines 405, 522, 565 try_enable_auto_merge dry-run output present for review-changesLines 416, 533, 576 Bats will execute all duplicates (wasting CI time), but this is clearly unintentional — the same merge/rebase artifact affecting
dev-lead-fix-reviews.shalso affected this test file.Remove the duplicate test blocks (lines 502-586).
🤖 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 `@tests/dev-lead/unit/test_fix_reviews.bats` around lines 502 - 586, The test file contains repeated Bats test blocks — remove the duplicate occurrences and keep a single copy of each test: "no-changes path also calls notify_coderabbit_resolve", "try_enable_auto_merge dry-run output present for fix-reviews", "try_enable_auto_merge dry-run output present for fix-bot-comment", and "try_enable_auto_merge dry-run output present for review-changes"; locate the duplicated test blocks by those exact test names and delete the extra copies so each test appears only once, preserving the original environment exports and assertions from the remaining single instance.
2210-2496:
⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftTests depend on check-run dedup logic that's in dead code.
These comprehensive check-run dedup tests (superseded cancelled runs, cross-suite handling, etc.) are well-designed but they test the advanced dedup logic from lines 276-293 of
dev-lead-fix-reviews.sh— which is in the firstfetch_pr_contextdefinition.Due to the function duplication issue, the second (active)
fetch_pr_contextdefinition (lines 1054-1111) lacks this dedup logic entirely. These tests will likely fail:
superseded cancelled check run is not a hard blockersame app different suites — superseded cancelled run is droppedqueued check run without started_at wins over older cancelled run by idOnce the duplication is resolved and the advanced dedup logic is retained in the active definition, these tests should pass.
🤖 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 `@tests/dev-lead/unit/test_fix_reviews.bats` around lines 2210 - 2496, There are two conflicting fetch_pr_context functions and the active one (the second fetch_pr_context) is missing the advanced check-run dedup logic present in the first definition (the group_by/sort_by dedup that handles superseded cancelled runs, cross-suite matching, and id-based tie-breaks); fix this by removing the duplicate/older fetch_pr_context definition and merging or copying the dedup block from the first fetch_pr_context into the single active fetch_pr_context (preserving the stage-1 per-suite grouping and the stage-2 cross-suite dedup that uses name+app and id-based sort), so the tests like "superseded cancelled check run is not a hard blocker", "same app different suites — superseded cancelled run is dropped", and "queued check run without started_at wins over older cancelled run by id" exercise the intended logic.
Dev-Lead — waiting on PR blockers (intent: fix-reviews)PR: #383 |
|
Closing this PR in favor of a fresh implementation of #382. Why: This branch was opened 2026-05-24 and Rather than reconcile 20+ regressions against a moving target, #382 will be re-implemented fresh against current |



Closes #382
Implemented by dev-lead agent. Please review.
Summary by CodeRabbit
New Features
Documentation
Bug Fixes
Tests
Chores