t1029: Auto-retry blocked merge-conflict tasks in supervisor pulse#1355
t1029: Auto-retry blocked merge-conflict tasks in supervisor pulse#1355marcusquinn merged 1 commit intomainfrom
Conversation
WalkthroughA database migration adds a Changes
Sequence DiagramsequenceDiagram
participant Pulse as Pulse Cycle
participant Phase35 as Phase 3.5<br/>Auto-Retry
participant Rebase as rebase_sibling_pr
participant DB as Tasks Table
participant Git as origin/main
Pulse->>Phase35: Execute Phase 3.5
Phase35->>DB: Query blocked tasks<br/>with merge-conflict error
DB-->>Phase35: Return matching tasks
loop For each task (max 3 retries)
Phase35->>DB: Read current main SHA
DB-->>Phase35: Return main SHA
alt Main SHA changed
Phase35->>Git: Fetch origin/main
Git-->>Phase35: Latest main branch
Phase35->>Rebase: Invoke rebase against<br/>origin/main
Rebase-->>Phase35: Rebase success/failure
alt Rebase Successful
Phase35->>DB: Update last_main_sha
Phase35->>DB: Increment rebase_attempts
Phase35->>DB: Transition to pr_review
else Rebase Failed
Phase35->>DB: Keep blocked status
Phase35->>DB: Increment rebase_attempts
end
else Main SHA unchanged
Phase35->>Phase35: Skip retry
end
end
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly Related Issues
Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (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 |
Summary of ChangesHello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces an automated mechanism to handle pull requests that are blocked due to merge conflicts. By periodically checking for advancements in the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a useful auto-retry mechanism for tasks blocked by merge conflicts, which should reduce the need for manual intervention. The implementation, including the database migration and the new pulse phase, is well-structured and follows the existing patterns in the script. I've identified a minor opportunity to refactor some duplicated code in the new logic to improve maintainability. Overall, this is a solid addition to the supervisor's capabilities.
| if rebase_sibling_pr "$blocked_id" 2>>"$SUPERVISOR_LOG"; then | ||
| log_success " Auto-rebase retry succeeded for $blocked_id — transitioning to pr_review" | ||
| # Increment rebase_attempts counter | ||
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | ||
| # Transition back to pr_review so CI can run | ||
| cmd_transition "$blocked_id" "pr_review" --error "" 2>>"$SUPERVISOR_LOG" || true | ||
| else | ||
| # Rebase still failed — increment counter and stay blocked | ||
| log_warn " Auto-rebase retry failed for $blocked_id — staying blocked" | ||
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | ||
| fi |
There was a problem hiding this comment.
There's an opportunity to deduplicate code here. The db command to update rebase_attempts is called in both the if and else blocks. You can move this line to before the if statement to make the code more concise and easier to maintain, since the counter is incremented for every attempt regardless of the outcome.
| if rebase_sibling_pr "$blocked_id" 2>>"$SUPERVISOR_LOG"; then | |
| log_success " Auto-rebase retry succeeded for $blocked_id — transitioning to pr_review" | |
| # Increment rebase_attempts counter | |
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | |
| # Transition back to pr_review so CI can run | |
| cmd_transition "$blocked_id" "pr_review" --error "" 2>>"$SUPERVISOR_LOG" || true | |
| else | |
| # Rebase still failed — increment counter and stay blocked | |
| log_warn " Auto-rebase retry failed for $blocked_id — staying blocked" | |
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | |
| fi | |
| # Increment rebase_attempts counter before the attempt. | |
| # This is done for both successful and failed rebases. | |
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | |
| if rebase_sibling_pr "$blocked_id" 2>>"$SUPERVISOR_LOG"; then | |
| log_success " Auto-rebase retry succeeded for $blocked_id — transitioning to pr_review" | |
| # Transition back to pr_review so CI can run | |
| cmd_transition "$blocked_id" "pr_review" --error "" 2>>"$SUPERVISOR_LOG" || true | |
| else | |
| # Rebase still failed — stay blocked | |
| log_warn " Auto-rebase retry failed for $blocked_id — staying blocked" | |
| fi |
- Add last_main_sha column to tasks table for tracking main advancement - Add Phase 3.5 between Phase 3b and Phase 4 in pulse cycle - Find blocked tasks with merge_conflict error - Reset and retry rebase when main advances - Cap at 3 total retry cycles to prevent infinite loops - Transition back to pr_review on successful rebase
159fd71 to
4f16b01
Compare
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Fri Feb 13 13:29:50 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.agents/scripts/supervisor-helper.sh:
- Around line 1764-1771: ensure_db returns early after init_db so fresh installs
never get later migrations (missing last_main_sha and rebase_attempts), causing
Phase 3.5 to disable itself; update the initial tasks table creation in init_db
to include the missing columns (add last_main_sha TEXT and rebase_attempts
INTEGER/appropriate type) so new DBs have the same schema as migrated DBs and
subsequent logic referencing last_main_sha and rebase_attempts won't break.
Locate the tasks table CREATE statement in init_db within
.agents/scripts/supervisor-helper.sh and add the two columns with sensible
defaults/nullability to match the ALTER TABLE migrations already applied.
- Around line 11904-11955: The current logic reads origin/main SHA without
ensuring the repo exists or that origin/main is up-to-date; before calling git
-C "$blocked_repo" rev-parse origin/main, first verify the repo exists (e.g.,
check "$blocked_repo/.git" or git -C "$blocked_repo" rev-parse
--is-inside-work-tree) and if present run a fetch (git -C "$blocked_repo" fetch
origin main) and guard fetch errors; if the repo is missing or fetch/rev-parse
fails, log via log_warn and continue, otherwise assign current_main_sha from the
freshly-fetched origin/main and proceed to the existing comparison and
rebase_sibling_pr flow, keeping existing db updates and logging (references:
blocked_repo, current_main_sha, blocked_last_main_sha, rebase_sibling_pr,
log_warn, log_info, db).
| # Migrate: add last_main_sha column to tasks (t1029) | ||
| local has_last_main_sha | ||
| has_last_main_sha=$(db "$SUPERVISOR_DB" "SELECT count(*) FROM pragma_table_info('tasks') WHERE name='last_main_sha';" 2>/dev/null || echo "0") | ||
| if [[ "$has_last_main_sha" -eq 0 ]]; then | ||
| log_info "Migrating tasks table: adding last_main_sha column (t1029)..." | ||
| db "$SUPERVISOR_DB" "ALTER TABLE tasks ADD COLUMN last_main_sha TEXT;" 2>/dev/null || true | ||
| log_success "Added last_main_sha column to tasks (t1029)" | ||
| fi |
There was a problem hiding this comment.
New DBs won’t get last_main_sha (and rebase_attempts), so Phase 3.5 silently disables itself.
ensure_db returns after init_db, so migrations won’t run on fresh installs. Add these columns to the init_db tasks table to keep schema parity.
🔧 Suggested schema update (init_db)
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
repo TEXT NOT NULL,
description TEXT,
status TEXT NOT NULL DEFAULT 'queued'
CHECK(status IN ('queued','dispatched','running','evaluating','retrying','complete','pr_review','review_triage','merging','merged','deploying','deployed','verifying','verified','verify_failed','blocked','failed','cancelled')),
session_id TEXT,
worktree TEXT,
branch TEXT,
log_file TEXT,
retries INTEGER NOT NULL DEFAULT 0,
+ rebase_attempts INTEGER NOT NULL DEFAULT 0,
max_retries INTEGER NOT NULL DEFAULT 3,
deploying_recovery_attempts INTEGER NOT NULL DEFAULT 0,
model TEXT DEFAULT 'anthropic/claude-opus-4-6',
error TEXT,
pr_url TEXT,
+ last_main_sha TEXT,
issue_url TEXT,
diagnostic_of TEXT,
triage_result TEXT,
escalation_depth INTEGER NOT NULL DEFAULT 0,
max_escalation INTEGER NOT NULL DEFAULT 2,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
started_at TEXT,
completed_at TEXT,
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now'))
);As per coding guidelines, Automation scripts should focus on reliability and robustness.
🤖 Prompt for AI Agents
In @.agents/scripts/supervisor-helper.sh around lines 1764 - 1771, ensure_db
returns early after init_db so fresh installs never get later migrations
(missing last_main_sha and rebase_attempts), causing Phase 3.5 to disable
itself; update the initial tasks table creation in init_db to include the
missing columns (add last_main_sha TEXT and rebase_attempts INTEGER/appropriate
type) so new DBs have the same schema as migrated DBs and subsequent logic
referencing last_main_sha and rebase_attempts won't break. Locate the tasks
table CREATE statement in init_db within .agents/scripts/supervisor-helper.sh
and add the two columns with sensible defaults/nullability to match the ALTER
TABLE migrations already applied.
| # Phase 3.5: Auto-retry blocked merge-conflict tasks (t1029) | ||
| # When a task is blocked with "Merge conflict — auto-rebase failed", periodically | ||
| # re-attempt the rebase after main advances. Other PRs merging often resolve conflicts. | ||
| local blocked_tasks | ||
| blocked_tasks=$(db "$SUPERVISOR_DB" "SELECT id, repo, error, rebase_attempts, last_main_sha FROM tasks WHERE status = 'blocked' AND error LIKE '%Merge conflict%auto-rebase failed%';" 2>/dev/null || echo "") | ||
|
|
||
| if [[ -n "$blocked_tasks" ]]; then | ||
| while IFS='|' read -r blocked_id blocked_repo blocked_error blocked_rebase_attempts blocked_last_main_sha; do | ||
| [[ -z "$blocked_id" ]] && continue | ||
|
|
||
| # Cap at 3 total retry cycles to prevent infinite loops | ||
| local max_retry_cycles=3 | ||
| if [[ "${blocked_rebase_attempts:-0}" -ge "$max_retry_cycles" ]]; then | ||
| log_info " Skipping $blocked_id — max retry cycles ($max_retry_cycles) reached" | ||
| continue | ||
| fi | ||
|
|
||
| # Get current main SHA | ||
| local current_main_sha | ||
| current_main_sha=$(git -C "$blocked_repo" rev-parse origin/main 2>/dev/null || echo "") | ||
| if [[ -z "$current_main_sha" ]]; then | ||
| log_warn " Failed to get origin/main SHA for $blocked_id in $blocked_repo" | ||
| continue | ||
| fi | ||
|
|
||
| # Check if main has advanced since last attempt | ||
| if [[ -n "$blocked_last_main_sha" && "$current_main_sha" == "$blocked_last_main_sha" ]]; then | ||
| # Main hasn't advanced — skip retry | ||
| continue | ||
| fi | ||
|
|
||
| # Main has advanced (or this is first retry) — reset counter and retry | ||
| log_info " Main advanced for $blocked_id — retrying rebase (attempt $((blocked_rebase_attempts + 1))/$max_retry_cycles)" | ||
|
|
||
| # Update last_main_sha before attempting rebase | ||
| local escaped_blocked_id | ||
| escaped_blocked_id=$(sql_escape "$blocked_id") | ||
| db "$SUPERVISOR_DB" "UPDATE tasks SET last_main_sha = '$current_main_sha' WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | ||
|
|
||
| # Attempt rebase | ||
| if rebase_sibling_pr "$blocked_id" 2>>"$SUPERVISOR_LOG"; then | ||
| log_success " Auto-rebase retry succeeded for $blocked_id — transitioning to pr_review" | ||
| # Increment rebase_attempts counter | ||
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | ||
| # Transition back to pr_review so CI can run | ||
| cmd_transition "$blocked_id" "pr_review" --error "" 2>>"$SUPERVISOR_LOG" || true | ||
| else | ||
| # Rebase still failed — increment counter and stay blocked | ||
| log_warn " Auto-rebase retry failed for $blocked_id — staying blocked" | ||
| db "$SUPERVISOR_DB" "UPDATE tasks SET rebase_attempts = $((blocked_rebase_attempts + 1)) WHERE id = '$escaped_blocked_id';" 2>/dev/null || true | ||
| fi | ||
| done <<<"$blocked_tasks" |
There was a problem hiding this comment.
Fetch origin/main and guard repo existence before SHA comparison.
Without a fetch, origin/main can be stale and the retry loop may never trigger. Also, git -C on a missing repo risks mis-targeting the current directory.
🛠️ Suggested hardening
while IFS='|' read -r blocked_id blocked_repo blocked_error blocked_rebase_attempts blocked_last_main_sha; do
[[ -z "$blocked_id" ]] && continue
+ if [[ -z "$blocked_repo" || ! -d "$blocked_repo/.git" ]]; then
+ log_warn " Skipping $blocked_id — repo not found: $blocked_repo"
+ continue
+ fi
+
+ if ! git -C "$blocked_repo" fetch origin main 2>>"$SUPERVISOR_LOG"; then
+ log_warn " Failed to fetch origin/main for $blocked_id in $blocked_repo"
+ continue
+ fi
# Get current main SHA
local current_main_sha
current_main_sha=$(git -C "$blocked_repo" rev-parse origin/main 2>/dev/null || echo "")As per coding guidelines, Automation scripts should focus on reliability and robustness, clear logging and feedback, proper exit codes, and error recovery mechanisms.
🤖 Prompt for AI Agents
In @.agents/scripts/supervisor-helper.sh around lines 11904 - 11955, The current
logic reads origin/main SHA without ensuring the repo exists or that origin/main
is up-to-date; before calling git -C "$blocked_repo" rev-parse origin/main,
first verify the repo exists (e.g., check "$blocked_repo/.git" or git -C
"$blocked_repo" rev-parse --is-inside-work-tree) and if present run a fetch (git
-C "$blocked_repo" fetch origin main) and guard fetch errors; if the repo is
missing or fetch/rev-parse fails, log via log_warn and continue, otherwise
assign current_main_sha from the freshly-fetched origin/main and proceed to the
existing comparison and rebase_sibling_pr flow, keeping existing db updates and
logging (references: blocked_repo, current_main_sha, blocked_last_main_sha,
rebase_sibling_pr, log_warn, log_info, db).



Summary
Implements auto-retry mechanism for tasks blocked with merge conflicts. When a task is blocked with "Merge conflict — auto-rebase failed", the supervisor now periodically re-attempts the rebase after main advances.
Changes
last_main_shacolumn to tasks table to track main branch advancementrebase_sibling_prwhen main advancespr_reviewon successRationale
Other PRs merging often resolve the conflict context. Instead of requiring manual intervention for every merge conflict, the supervisor now automatically retries when the conflict context changes (main advances).
Testing
Ref #1354
Summary by CodeRabbit