-
Notifications
You must be signed in to change notification settings - Fork 7
t1050: Escalate rebase-blocked PRs to opus worker (Phase 3.6) #1483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -637,6 +637,141 @@ cmd_pulse() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done <<<"$blocked_tasks" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Phase 3.6: Escalate rebase-blocked PRs to opus worker (t1050) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # When auto-rebase fails max_retry_cycles times, dispatch an opus worker to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # manually rebase, resolve conflicts, and merge the PR. Only ONE escalation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # runs at a time (sequential) so each subsequent rebase has a clean base. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local escalation_lock="${SUPERVISOR_DIR}/rebase-escalation.lock" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local escalation_cooldown=300 # 5 minutes between escalations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check if an escalation is already running or recently completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local should_escalate=true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -f "$escalation_lock" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local lock_age | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lock_age=$(($(date +%s) - $(stat -f %m "$escalation_lock" 2>/dev/null || stat -c %Y "$escalation_lock" 2>/dev/null || echo "0"))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$lock_age" -lt "$escalation_cooldown" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| should_escalate=false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log_verbose " Phase 3.6: escalation cooldown (${lock_age}s/${escalation_cooldown}s)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Stale lock — remove it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rm -f "$escalation_lock" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$should_escalate" == "true" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Find ONE task that has exhausted auto-rebase retries | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local escalation_candidate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| escalation_candidate=$(db "$SUPERVISOR_DB" " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SELECT t.id, t.repo, t.pr_url, t.branch, t.rebase_attempts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FROM tasks t | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WHERE t.status = 'blocked' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AND t.error LIKE '%Merge conflict%auto-rebase failed%' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relying on a specific error string with For better long-term maintainability, consider adding a dedicated column (e.g., |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AND t.rebase_attempts >= $max_retry_cycles | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AND t.pr_url IS NOT NULL AND t.pr_url != '' AND t.pr_url != 'no_pr' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ORDER BY t.rebase_attempts ASC, t.id ASC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LIMIT 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| " 2>/dev/null || echo "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+661
to
+673
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug:
This means Phase 3.6 escalation never fires when Phase 3.5 has nothing to process, which is precisely when escalation candidates (retries already exhausted) are most likely to exist. 🐛 Proposed fix: define the constant at Phase 3.5/3.6 shared scope+ # Shared constant for Phase 3.5 and 3.6
+ local max_retry_cycles=3
+
# 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_tasksAnd remove the duplicate declaration inside the loop: - # Cap at 3 total retry cycles to prevent infinite loops
- local max_retry_cycles=3🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -n "$escalation_candidate" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_id esc_repo esc_pr esc_branch esc_attempts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IFS='|' read -r esc_id esc_repo esc_pr esc_branch esc_attempts <<<"$escalation_candidate" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -n "$esc_id" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log_info " Phase 3.6: escalating $esc_id to opus worker (rebase_attempts=$esc_attempts, pr=$esc_pr)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Create lock file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| date +%s >"$escalation_lock" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Resolve AI CLI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_ai_cli | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esc_ai_cli=$(resolve_ai_cli 2>/dev/null || echo "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -z "$esc_ai_cli" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log_warn " Phase 3.6: no AI CLI available for escalation" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rm -f "$escalation_lock" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Find the worktree path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_worktree="" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_wt_row | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esc_wt_row=$(db "$SUPERVISOR_DB" "SELECT worktree FROM tasks WHERE id = '$(sql_escape "$esc_id")';" 2>/dev/null || echo "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -n "$esc_wt_row" && -d "$esc_wt_row" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esc_worktree="$esc_wt_row" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the escalation prompt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_prompt="You are resolving a merge conflict that automated tools could not handle. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TASK: $esc_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BRANCH: $esc_branch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PR: $esc_pr | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| REPO: $esc_repo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WORKTREE: ${esc_worktree:-$esc_repo} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| STEPS: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. cd to the worktree (or repo if no worktree) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2. Run: git fetch origin main | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3. Abort any in-progress rebase: git rebase --abort (ignore errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4. Clean any dirty state: git stash push -m 'pre-escalation' (ignore errors) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 5. Run: git rebase origin/main | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 6. If conflicts occur, resolve ALL of them: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Read each conflicting file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Understand both sides' intent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Merge intelligently (keep both sides' changes where possible) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Remove ALL conflict markers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - git add each resolved file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - git rebase --continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Repeat for each commit in the rebase | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 7. After rebase completes: git push --force-with-lease origin $esc_branch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 8. Verify the PR is no longer in conflict: gh pr view $esc_pr --json mergeStateStatus | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 9. If CI passes, merge: gh pr merge $esc_pr --squash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10. Output ONLY: 'ESCALATION_MERGED: $esc_id' if merged, 'ESCALATION_REBASED: $esc_id' if rebased but not merged, or 'ESCALATION_FAILED: reason' if failed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RULES: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Do NOT modify the intent of any code — only resolve conflicts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Prefer the feature branch for new functionality, main for structural changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - If a file has been deleted on main but modified on the branch, keep the branch version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Do NOT create new commits beyond what the rebase produces" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+700
to
+732
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Read the file around the specified lines
wc -l .agents/scripts/supervisor/pulse.shRepository: marcusquinn/aidevops Length of output: 104 🏁 Script executed: # Get context around lines 700-732
sed -n '690,740p' .agents/scripts/supervisor/pulse.shRepository: marcusquinn/aidevops Length of output: 2190 🏁 Script executed: # Check if ESCALATION_MERGED/REBASED/FAILED markers are referenced anywhere
rg -n 'ESCALATION_MERGED|ESCALATION_REBASED|ESCALATION_FAILED' --type=shRepository: marcusquinn/aidevops Length of output: 258 🏁 Script executed: # Check how esc_branch, esc_pr, esc_repo are sourced and quoted
rg -n 'esc_branch\|esc_pr\|esc_repo' --type=sh -B2 -A2 | head -100Repository: marcusquinn/aidevops Length of output: 46 🏁 Script executed: # Look for evaluate_worker function
rg -n 'evaluate_worker' --type=sh -A20Repository: marcusquinn/aidevops Length of output: 20028 🏁 Script executed: # Check if there's any CI status checking before merge
rg -n 'mergeStateStatus|ciStatus|check.*pass' --type=shRepository: marcusquinn/aidevops Length of output: 6926 🏁 Script executed: # Check where the escalation worker is dispatched and what happens with its output
rg -n 'escalation' .agents/scripts/supervisor/pulse.sh -A5 -B5 | grep -E '(dispatch|worker|eval|outcome|log|ESCALATION)' | head -60Repository: marcusquinn/aidevops Length of output: 1124 🏁 Script executed: # Look for where the escalation process is expected to complete or be handled
rg -n 'esc_log_dir|esc_model|dispatch.*esc' .agents/scripts/supervisor/pulse.sh -A10Repository: marcusquinn/aidevops Length of output: 2570 🏁 Script executed: # Check if there's a comment about handling escalation outcomes
rg -n 'escalation.*outcome|ESCALATION.*handling|phase.*escalation' .agents/scripts/supervisor/ -iRepository: marcusquinn/aidevops Length of output: 296 🏁 Script executed: # Verify variable quoting in actual shell commands within the prompt
sed -n '710,735p' .agents/scripts/supervisor/pulse.sh | grep -E 'git|gh|branch|pr|repo'Repository: marcusquinn/aidevops Length of output: 817 🏁 Script executed: # Look at the full escalation section to see variable sourcing
sed -n '640,750p' .agents/scripts/supervisor/pulse.shRepository: marcusquinn/aidevops Length of output: 4709 🏁 Script executed: # Check where esc_branch, esc_pr, esc_repo are first set
rg -n 'esc_branch=|esc_pr=|esc_repo=' .agents/scripts/supervisor/pulse.shRepository: marcusquinn/aidevops Length of output: 46 🏁 Script executed: # Check if escalation outcome is parsed anywhere after dispatch
rg -n 'esc_log_file|escalation.*log' .agents/scripts/supervisor/pulse.sh -A5Repository: marcusquinn/aidevops Length of output: 750 🏁 Script executed: # Look for any subsequent handling of escalated tasks
rg -n 'escalation_candidate|esc_id' .agents/scripts/supervisor/pulse.sh | tail -20Repository: marcusquinn/aidevops Length of output: 1227 Escalation outcome markers are defined in the prompt but never parsed by the supervisor. The prompt (line 726) instructs the worker to output Also: 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Resolve model — use opus for complex conflict resolution | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_model | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esc_model=$(resolve_model "opus" "$esc_ai_cli" 2>/dev/null || echo "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Dispatch the worker | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_log_dir="${SUPERVISOR_DIR}/logs" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p "$esc_log_dir" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_log_file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esc_log_file="${esc_log_dir}/escalation-${esc_id}-$(date +%Y%m%d-%H%M%S).log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_workdir="${esc_worktree:-$esc_repo}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$esc_ai_cli" == "opencode" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (cd "$esc_workdir" && $esc_ai_cli run \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ${esc_model:+--model "$esc_model"} \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --format json \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --title "escalation-rebase-${esc_id}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "$esc_prompt" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >"$esc_log_file" 2>&1) & | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_pid=$! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (cd "$esc_workdir" && $esc_ai_cli -p "$esc_prompt" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ${esc_model:+--model "$esc_model"} \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >"$esc_log_file" 2>&1) & | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local esc_pid=$! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Record the escalation in the DB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| db "$SUPERVISOR_DB" "UPDATE tasks SET | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = 'running', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error = 'Escalation: opus rebase worker (PID $esc_pid)', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| worker_pid = $esc_pid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updated_at = strftime('%Y-%m-%dT%H:%M:%SZ','now') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WHERE id = '$(sql_escape "$esc_id")';" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+760
to
+766
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Status update bypasses The PR description states "Uses cmd_transition so GitHub issue labels sync automatically," but line 761–766 performs a raw ♻️ Proposed fix: use cmd_transition- db "$SUPERVISOR_DB" "UPDATE tasks SET
- status = 'running',
- error = 'Escalation: opus rebase worker (PID $esc_pid)',
- worker_pid = $esc_pid,
- updated_at = strftime('%Y-%m-%dT%H:%M:%SZ','now')
- WHERE id = '$(sql_escape "$esc_id")';" 2>/dev/null || true
+ # Transition via cmd_transition for label sync + state_log
+ cmd_transition "$esc_id" "running" --error "Escalation: opus rebase worker (PID $esc_pid)" 2>>"$SUPERVISOR_LOG" || true
+ # Update worker_pid separately (cmd_transition doesn't handle this field)
+ db "$SUPERVISOR_DB" "UPDATE tasks SET
+ worker_pid = $esc_pid,
+ log_file = '$(sql_escape "$esc_log_file")'
+ WHERE id = '$(sql_escape "$esc_id")';" 2>/dev/null || true🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log_success " Phase 3.6: dispatched opus worker PID $esc_pid for $esc_id" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| send_task_notification "$esc_id" "escalated" "Opus rebase worker dispatched (PID $esc_pid)" 2>>"$SUPERVISOR_LOG" || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+752
to
+769
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: No PID file written — next pulse will orphan-kill the escalation worker. The background worker PID is captured (
Additionally, the 🐛 Proposed fix: write PID file and update log_file local esc_pid=$!
fi
+ # Write PID file so Phase 1/4 can track the worker
+ mkdir -p "$SUPERVISOR_DIR/pids" 2>/dev/null || true
+ echo "$esc_pid" > "$SUPERVISOR_DIR/pids/${esc_id}.pid"
+
# Record the escalation in the DB
db "$SUPERVISOR_DB" "UPDATE tasks SET
status = 'running',
error = 'Escalation: opus rebase worker (PID $esc_pid)',
worker_pid = $esc_pid,
+ log_file = '$(sql_escape "$esc_log_file")',
updated_at = strftime('%Y-%m-%dT%H:%M:%SZ','now')
WHERE id = '$(sql_escape "$esc_id")';" 2>/dev/null || true📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Phase 4: Worker health checks - detect dead, hung, and orphaned workers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local worker_timeout_seconds="${SUPERVISOR_WORKER_TIMEOUT:-3600}" # 1 hour default (t314: restored after merge overwrite) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Absolute max runtime: kill workers regardless of log activity. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
2>/dev/nullhere violates the repository's style guide (rule 50), which states that stderr should only be redirected to a log file. This pattern is repeated throughout the new code block (e.g., lines 651, 673, 683, 687, 690, 695, 736, 740, and 766). Suppressing errors can make debugging more difficult.Please redirect to the supervisor log file instead to adhere to the style guide and improve observability.
References
2>/dev/nullis only acceptable when redirecting to log files, not for blanket suppression of errors. This change violates that rule. (link)