feat: add fix_ci action to supervisor AI lifecycle for automatic CI repair#2144
feat: add fix_ci action to supervisor AI lifecycle for automatic CI repair#2144marcusquinn merged 1 commit intomainfrom
Conversation
…epair Closes the gap in the supervisor pipeline where CI failures (format, lint, typecheck) on PRs caused tasks to get stuck in 'blocked' state indefinitely. Changes to ai-lifecycle.sh: - gather_task_state: extract PR_CI_FAILED_CHECKS (names of failed CI checks) - fast_path_decision: deterministic routing to fix_ci when all failures are mechanically fixable (Format, Lint, Typecheck, Unit Tests/E2E skipped) - execute_lifecycle_action: new fix_ci case that calls fix_ci_failures() - decide_next_action: added fix_ci to AI action vocabulary and rules - fix_ci_failures(): new function implementing tiered CI repair: Tier 1: Mechanical (pnpm format:fix, pnpm lint:fix, linters-local.sh) Tier 2: Typecheck verification after format/lint fixes Auto-detects package manager (pnpm/yarn/npm) and available scripts. Commits fixes and pushes to trigger CI re-run. Falls back to escalation if mechanical fixes produce no changes. This replaces the previous behavior where blocked PRs required either: - A full opus worker dispatch (expensive, slow) - Manual human intervention - A diagnostic subtask (overkill for format:fix)
|
Caution Review failedThe pull request is closed. WalkthroughThis PR extends the AI lifecycle automation script with mechanical CI fixing capabilities, introducing a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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 significantly enhances the supervisor AI lifecycle by introducing an automated mechanism to resolve common CI failures. It streamlines the development workflow by automatically applying fixes for formatting, linting, and type-checking issues, reducing manual intervention and accelerating the progression of pull requests. Highlights
Changelog
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
|
🔍 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: Sun Feb 22 15:37:24 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
There was a problem hiding this comment.
Code Review
The pull request introduces a fix_ci action to the AI lifecycle engine, enabling automatic repair of common CI failures like formatting and linting. This is a great addition for reducing manual intervention. My feedback focuses on adhering to the repository's style guide regarding SQLite parameterized queries and following general best practices for JSON construction and error suppression in shell scripts.
| IFS="$IFS_SAVE" | ||
|
|
||
| if [[ "$all_fixable" == "true" && "$worktree_exists" == "true" ]]; then | ||
| echo "{\"action\":\"fix_ci\",\"reason\":\"CI failed on fixable checks: ${ci_failed_checks}\",\"status_tag\":\"ci-failed\"}" |
There was a problem hiding this comment.
Constructing JSON via string interpolation is fragile and can lead to invalid JSON if variables contain special characters (like quotes or backslashes). Use jq --arg to safely construct the JSON object.
| echo "{\"action\":\"fix_ci\",\"reason\":\"CI failed on fixable checks: ${ci_failed_checks}\",\"status_tag\":\"ci-failed\"}" | |
| jq -cn --arg action "fix_ci" --arg reason "CI failed on fixable checks: ${ci_failed_checks}" --arg status_tag "ci-failed" '{action: $action, reason: $reason, status_tag: $status_tag}' |
References
- Use jq --arg for strings to safely pass variables into a jq filter, avoiding syntax errors if variables contain special characters.
|
|
||
| # Extract names of failed checks for fix_ci routing | ||
| local failed_check_names | ||
| failed_check_names=$(printf '%s' "$check_rollup" | jq -r '[.[] | select((.conclusion | test("FAILURE|TIMED_OUT|ACTION_REQUIRED")) or .state == "FAILURE" or .state == "ERROR") | .name] | join(",")' 2>/dev/null || echo "") |
There was a problem hiding this comment.
Avoid using 2>/dev/null for blanket suppression of jq errors. Keeping stderr visible helps diagnose issues with malformed input or syntax errors, while the || echo "" fallback still provides a safe default value.
| failed_check_names=$(printf '%s' "$check_rollup" | jq -r '[.[] | select((.conclusion | test("FAILURE|TIMED_OUT|ACTION_REQUIRED")) or .state == "FAILURE" or .state == "ERROR") | .name] | join(",")' 2>/dev/null || echo "") | |
| failed_check_names=$(printf '%s' "$check_rollup" | jq -r '[.[] | select((.conclusion | test("FAILURE|TIMED_OUT|ACTION_REQUIRED")) or .state == "FAILURE" or .state == "ERROR") | .name] | join(",")' || echo "") |
References
- In shell scripts with 'set -e' enabled, use '|| true' or default values to prevent script exit on optional lookup failures, while keeping stderr visible for debugging.
| local escaped_id | ||
| escaped_id=$(sql_escape "$task_id") | ||
|
|
||
| # Get worktree and branch from DB | ||
| local tworktree tbranch | ||
| tworktree=$(db "$SUPERVISOR_DB" "SELECT worktree FROM tasks WHERE id = '$escaped_id';" 2>/dev/null || echo "") | ||
| tbranch=$(db "$SUPERVISOR_DB" "SELECT branch FROM tasks WHERE id = '$escaped_id';" 2>/dev/null || echo "") |
There was a problem hiding this comment.
The repository style guide requires using parameterized queries for SQLite to prevent SQL injection and improve performance. The db helper should be used with parameters instead of string interpolation.
| local escaped_id | |
| escaped_id=$(sql_escape "$task_id") | |
| # Get worktree and branch from DB | |
| local tworktree tbranch | |
| tworktree=$(db "$SUPERVISOR_DB" "SELECT worktree FROM tasks WHERE id = '$escaped_id';" 2>/dev/null || echo "") | |
| tbranch=$(db "$SUPERVISOR_DB" "SELECT branch FROM tasks WHERE id = '$escaped_id';" 2>/dev/null || echo "") | |
| # Get worktree and branch from DB | |
| local tworktree tbranch | |
| tworktree=$(db "$SUPERVISOR_DB" "SELECT worktree FROM tasks WHERE id = ?;" "$task_id" || echo "") | |
| tbranch=$(db "$SUPERVISOR_DB" "SELECT branch FROM tasks WHERE id = ?;" "$task_id" || echo "") |
References
- All SQLite databases use WAL mode + busy_timeout=5000. Use parameterized queries where possible. (link)
| local has_format_fix="false" has_lint_fix="false" has_typecheck="false" | ||
| if [[ -n "$pkg_mgr" && -f "$workdir/package.json" ]]; then | ||
| local scripts_json | ||
| scripts_json=$(jq -r '.scripts // {}' "$workdir/package.json" 2>/dev/null || echo "{}") |
There was a problem hiding this comment.
Avoid using 2>/dev/null to suppress errors when the file's existence has already been verified. This can mask permission issues or malformed JSON errors.
| scripts_json=$(jq -r '.scripts // {}' "$workdir/package.json" 2>/dev/null || echo "{}") | |
| scripts_json=$(jq -r '.scripts // {}' "$workdir/package.json" || echo "{}") |
References
- Avoid using 2>/dev/null to suppress errors on file operations if the file's existence has already been verified, as it can mask important issues like permissions problems.



Summary
fix_ciaction to the supervisor AI lifecycle engine (ai-lifecycle.sh)blockedstateHow It Works
Detection (fast-path in
fast_path_decision):statusCheckRollupFormat,Lint,Typecheck(plus skippedUnit Tests/Merge E2E Reports), routes tofix_ciExecution (tiered in
fix_ci_failures):format:fixandlint:fixtypecheckto check if format/lint fixes resolved type errorsRepo detection:
package.jsonscripts for available fix commandslinters-local.shfor shellcheck fixespnpm install) before running fixesBefore vs After
blocked→ manual fix or opus dispatchfix_cirunsformat:fix, pushes, CI re-runsblocked→ expensive diagnostic subtaskfix_ciruns fixes mechanically, verifies typecheckblocked→ escalationTesting
bash -n: passshellcheck -S warning: zero violationsSummary by CodeRabbit