| name | team-branch-fix |
| description | Implement fixes for code review findings using a parallel agent team. Accepts a review report (from /team-branch-review, /team-commit-review, or pasted), interviews the user on which findings to fix (or runs autonomously with --auto), then spawns agents to implement fixes in parallel with Codex validation. |
| argument-hint | [--auto] [--epic <EPIC_ID>] [review report or path to report] |
Team Branch Fix
Implement code fixes for review findings using a parallel agent team. Each agent owns an exclusive set of files, implements all fixes for those files, and self-validates with Codex MCP. Runs verification (lint/test/build) after all agents complete.
Reference Files
This skill uses reference files in the references/ directory. Load referenced files
with the Read tool before executing the relevant phase. If a reference file is missing,
use the inline fallback instructions in the phase description.
Context
- Working directory: !
pwd
- Current branch: !
git branch --show-current
Instructions
You are the team lead coordinating parallel implementation of code fixes from a review report. You will interview the user to decide which findings to fix, group work by file ownership, spawn fix agents, and verify the results.
CRITICAL: You MUST use the AskUserQuestion tool for ALL user-facing questions in Phase 2. Do NOT print questions as text output and wait for free-form responses. Every question about whether to fix, skip, or defer a finding MUST be an AskUserQuestion tool call with structured options. This is the only way to give the user a proper interactive experience.
CRITICAL: You MUST use the TeamCreate tool to create an agent team and the Task tool (with team_name parameter) to spawn fix agents. Each fixer is an independent Claude agent session. Do NOT attempt workarounds if these tools are missing.
Phase 0: Precondition Check
Before anything else, verify required tools and git state.
Step 1: Tool availability
-
Check for the Task tool (subagent spawner). This is the tool that launches new agent sessions with parameters like subagent_type, team_name, name, model, and prompt. It is NOT the same as TaskCreate/TaskList/TaskUpdate/TaskGet (those manage a task list). Look at your available tools - if you do not have a tool called "Task" that spawns subagents, STOP IMMEDIATELY and tell the user:
"This skill requires the Task tool (subagent spawner) which is not available in custom agent sessions (claude --agent). Run this skill from a plain claude session instead."
Do NOT attempt workarounds. Just stop.
-
Check for the TeamCreate tool. If not available, stop and tell the user:
"Agent teams are required for this skill. Enable them by setting CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in your Claude Code settings, then retry."
Step 2: Git state
Verify the git state is safe to proceed:
git status --short
git log --oneline $(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)..HEAD
Require both:
- Clean working tree: No uncommitted changes (staged or unstaged). If dirty, stop and tell the user to commit or stash their changes first.
- Commits on branch: At least one commit ahead of main. If the branch has no commits vs main, there's nothing to fix - stop and tell the user.
Do NOT proceed past this phase unless both conditions are met.
Step 3: Compute team name
Compute a unique team name: take the branch name, replace / with -, truncate to 30 chars, then prefix with fix- and append - plus the first 6 chars of HEAD's commit hash. Example: branch feat/add-auth at commit a1b2c3d becomes fix-feat-add-auth-a1b2c3. Record this as TEAM_NAME and use it everywhere a team_name is needed.
Create temp directory for fixer results:
mkdir -p /tmp/fix-TEAM_NAME
Phase 0.5: Parse Auto Mode and Planning Context Flags
Parse optional leading flags from ARGUMENTS before any other processing.
Auto-mode parsing rule: If ARGUMENTS starts with --auto (first whitespace-delimited token), set AUTO_MODE = true and strip --auto from the arguments before passing the remainder to Phase 1. If --auto appears anywhere other than the first token, ignore it (treat as part of the review report text). If ARGUMENTS does not start with --auto, set AUTO_MODE = false.
Epic flag parsing rule: After stripping --auto, check whether the next tokens are --epic <EPIC_ID>. If so, capture EPIC_ID and strip both tokens. If not present, leave EPIC_ID unset — the planning-context loader falls back to branch-name parsing in Phase 1.
When AUTO_MODE is true, all AskUserQuestion calls in subsequent phases are replaced with deterministic defaults. Each auto-decision is logged to an Auto-Mode Decision Log table (columns: Phase, Finding, Decision, Reason). The Phase 2 decisions are printed at Step 4 before fix agents are spawned. Later auto-decisions (Phases 7.5 and 9) are appended and the complete log is included in the Phase 9 Auto-Mode Summary.
AUTO_MODE does not affect:
- Phase 0 precondition checks (these are not interactive)
- Phase 1 report parsing (report is provided via args when invoked with --auto; if no report is available in auto-mode, stop with an error rather than asking the user)
- Phase 1.5 canonicalization (no user interaction)
- Phase 3 fix plan construction (derived from auto-decisions)
- Phase 4, 5, 6, 7, 8 (no user interaction in these phases)
Phase 1: Gather Review Report
Obtain the review report from one of these sources (check in order):
- Conversation context: If a
/team-branch-review or /team-commit-review report exists in the conversation above, use it directly
- $ARGUMENTS: If arguments are provided, treat them as the report or a path to one
- Ask the user: If no report is available, ask the user to provide one
Parse the report and extract all findings into a structured list. Assign each finding a sequential finding_id (format: f-1, f-2, ...) and classify its finding_scope:
finding_id: Sequential identifier (f-{N}) assigned during parsing
finding_scope: One of:
line - targets a specific file:line location
file - targets a whole file (no specific line)
cross-cutting - systemic issue not tied to a specific file (e.g., "add error handling everywhere")
- Finding title
- File and line number
- Severity (Critical/High/Medium/Low)
- Category
- Issue description
- Suggested fix
- Codex validation status (Confirmed/Disputed/Adjusted)
- Found by (which reviewer)
See Decision Schema for the full finding data model including decision tracking fields populated in later phases.
After parsing the report, follow ~/.claude/skills/shared/planning-context.md to produce planning_context using the EPIC_ID captured in Phase 0.5 (falling back to branch-name parse, then to the "no linked planning context" string). Keep this value for use in Phase 5's fix agent prompt. The lead should also consult it during Phase 2 interviews: a finding that fights an explicit design decision is a strong "Skip" candidate, not a silent "Fix."
Phase 1.5: Finding Canonicalization
Before presenting findings to the user, deduplicate and group them so the interview operates on canonical findings rather than raw duplicates.
Step 1: Classify scope
For each finding, verify the finding_scope assigned in Phase 1:
- Has file AND line number ->
line
- Has file but no line number ->
file
- No specific file (or references multiple files as a pattern) ->
cross-cutting
Step 2: Group duplicates
Apply grouping rules by scope:
line-scoped: Group findings that share the same (file, line) AND describe the same underlying issue. Two findings from different reviewers catching the same nil dereference at the same location are duplicates. Two findings at the same line for different issues (e.g., nil check vs naming convention) are NOT duplicates.
file-scoped: Group findings that share the same file AND describe the same issue.
cross-cutting: Group findings that describe the same systemic concern, regardless of wording. For example, "add error handling to all API endpoints" and "missing error handling in API layer" are the same concern.
Step 3: Assign canonical IDs
For each group:
- Assign a sequential
group_id (g-1, g-2, ...)
- Set
source_finding_ids to the list of all member finding_id values
- Pick one finding as the canonical representative (
is_canonical: true) - prefer the one with the most specific suggested fix
- Merge
found_by lists (union of all members)
- Use the highest
severity among members
- Use the most specific
suggested_fix among members
Step 4: Output
Replace the raw finding list with the deduplicated canonical list. Each entry carries its group_id and source_finding_ids so downstream phases can trace back to the original findings. Only canonical findings (is_canonical: true) proceed to Phase 2.
Announce the dedup results to the user: "Parsed N findings, deduplicated to M canonical findings (K duplicates merged)."
Phase 2: User Interview
You MUST call the AskUserQuestion tool for every question below. Do NOT print questions as plain text.
See also:
Step 0: Infer session default
Before processing findings, analyze the review report and branch context to infer a default approach style. Check these signals:
| Signal | Suggests |
|---|
Branch name contains fix/, hotfix/, patch/ | minimal_patch |
| Most findings are Critical/High severity | minimal_patch |
Branch name contains refactor/, cleanup/ | refactor |
| Most findings are Medium/Low with pattern issues | refactor |
| Commit messages mention stability, reliability | defensive |
| No strong signal | minimal_patch (safe default) |
Display the inference and reason to the user in assistant text, then offer a one-click override:
Auto-mode (AUTO_MODE = true): Use the inferred default directly without asking. Log to Auto-Mode Decision Log: Phase="Step 0", Finding="-", Decision="Keep [style]", Reason="auto-mode: used inferred default". Skip the AskUserQuestion call below.
Call AskUserQuestion tool with:
questions: [{
question: "Inferred default: [style] based on [reason]. Change?",
header: "Fix style",
options: [
{ label: "Keep [style]", description: "Use [style] as the default for all findings" },
{ label: "Minimal patches", description: "Smallest change that fixes each issue" },
{ label: "Defensive fixes", description: "Fix plus guards against related failures" },
{ label: "Case by case", description: "No default - choose approach for every finding individually" }
],
multiSelect: false
}]
"Case by case" means no session default is set. Effects:
- Complex findings still get approach generation, but no approach is pre-marked as "(Recommended)" since there's no default style to prefer.
- Trivial findings still use the standard Fix/Skip/Defer flow - they do NOT get approach generation.
- Fixer agents fall through to precedence rule 4 (minimal-change) instead of rule 3 (session default) for cases where no explicit approach was chosen.
The session default determines which approach is listed first (recommended position) when generating approaches for complex findings.
Step 0.5: Disputed finding triage
Before stepping through findings individually, triage Codex-disputed findings in bulk. Disputed findings are a strong signal that reviewers disagreed - they deserve explicit handling, not one-at-a-time erosion of user attention deep in the interview.
Collect every canonical finding where codex_status == "Disputed", regardless of severity. If zero disputed findings exist, skip this step entirely.
If disputed findings exist, announce the count to the user in assistant text (e.g., "3 of 12 findings were disputed by Codex"), then call AskUserQuestion:
Auto-mode (AUTO_MODE = true): Auto-select "Skip all disputed". Disputed findings require human judgment that cannot be safely automated. For each disputed finding, log to Auto-Mode Decision Log: Phase="Step 0.5", Finding="[finding_id]: [title]", Decision="Skip", Reason="auto-mode: disputed finding, requires human judgment". Skip the AskUserQuestion call below.
Call AskUserQuestion tool with:
questions: [{
question: "N findings were disputed by Codex. How do you want to handle them?",
header: "Disputed",
options: [
{ label: "Skip all disputed (Recommended)", description: "Mark all N as skipped - reviewers disagreed, fix nothing" },
{ label: "Review each individually", description: "Walk through each disputed finding with full stance resolution" },
{ label: "Trust Claude on all", description: "Apply Claude's assessment to all N disputed findings, then pick fix/skip per finding" },
{ label: "Trust Codex on all", description: "Apply Codex's assessment to all N disputed findings, then pick fix/skip per finding" }
],
multiSelect: false
}]
Record the bulk decision per disputed finding based on user selection:
- "Skip all disputed": set
decision.disposition = "skip". These findings are done - they are excluded from Steps 1, 2, and 3.
- "Review each individually": leave
decision untouched. These findings flow into Step 2 for full stance resolution.
- "Trust Claude on all": set
decision.stance = "claude" for each. These findings flow into Step 2 but skip the stance-resolution question.
- "Trust Codex on all": set
decision.stance = "codex" for each. Same as above but with Codex's position.
Step 1: Confirmed Critical & High findings
For each Critical or High finding where codex_status != "Disputed" (disputed findings are routed to Step 0.5 and Step 2):
-
Classify complexity: Read ~50 lines of code around the finding and score against the complexity rubric. Score >= 2 = complex. If uncertain, classify complex. (Fallback if reference missing: +1 each for multi-function scope, multiple valid approaches, new patterns required, public API impact, non-obvious fix. Threshold: >= 2.)
-
If trivial (score < 2): Use the standard flow - call AskUserQuestion:
Auto-mode (AUTO_MODE = true): Auto-select "Fix (Recommended)". Log to Auto-Mode Decision Log: Phase="Step 1", Finding="[finding_id]: [title]", Decision="Fix", Reason="auto-mode: trivial confirmed finding". Skip the AskUserQuestion call below.
Call AskUserQuestion tool with:
questions: [{
question: "[Finding title] in [file:line] - [one-line issue description]. Fix this?",
header: "High finding",
options: [
{ label: "Fix (Recommended)", description: "Apply the suggested fix" },
{ label: "More info", description: "Investigate the code in depth before deciding" },
{ label: "Skip", description: "Intentional or not a real issue" },
{ label: "Defer", description: "Fix in a later session" }
],
multiSelect: false
}]
-
If complex (score >= 2): Generate 2 concrete approaches per approach generation. Present via AskUserQuestion with markdown previews (~10 lines each). Include "Validate with Codex" option per codex validation. Store chosen approach in decision schema. Limit to 2 approaches so options stay within AskUserQuestion's 4-option maximum (2 approaches + "Validate with Codex" + "Skip").
Auto-mode (AUTO_MODE = true): Still generate 2 approaches (read code, draft per approach-generation.md) since fixer agents need the approach context. Auto-select the first approach (session-default-aligned). Set decision.approach_source = "default". Log to Auto-Mode Decision Log: Phase="Step 1", Finding="[finding_id]: [title]", Decision="Approach 1: [label]", Reason="auto-mode: complex finding, selected session-default-aligned approach". Skip the AskUserQuestion call.
(Fallback if reference files missing: draft 2 approaches from different styles - pick 2 of minimal_patch, defensive, refactor. Each needs a short label, one-line description, and ~10 line code preview. Session default goes first. Include "Validate with Codex" and "Skip" options. If user validates with Codex, call mcp__codex__codex with approaches + code context, then re-present with assessments baked in. Store decision.approach, decision.approach_detail, decision.approach_source.)
If the user selects "More info" (trivial findings only):
Investigate the finding in depth:
- Read the file around the flagged line with the Read tool (include generous context, ~50 lines around the issue)
- Trace callers and dependents with Grep to show impact
- Check git blame to understand why the code exists:
git log --oneline -3 -- <file>
- Present a summary to the user:
- The actual code in question (with surrounding context)
- What the reviewer flagged and why
- What the suggested fix would change
- Potential impact: what other code depends on this
- Risk assessment: how likely is this to cause problems if left unfixed
Then re-ask with AskUserQuestion (without the "More info" option):
Call AskUserQuestion tool with:
questions: [{
question: "With the above context - fix [Finding title] in [file:line]?",
header: "Fix decision",
options: [
{ label: "Fix (Recommended)", description: "Apply the suggested fix" },
{ label: "Skip", description: "Intentional or not a real issue" },
{ label: "Defer", description: "Fix in a later session" }
],
multiSelect: false
}]
Step 2: Disputed findings (all severities)
Scope: every canonical finding where codex_status == "Disputed" AND decision.disposition != "skip" (findings skipped via Step 0.5 bulk triage are excluded). This step handles Critical, High, Medium, and Low disputed findings uniformly - disputes are treated as a first-class signal regardless of severity.
Auto-mode (AUTO_MODE = true): Auto-mode handled all disputed findings in Step 0.5. This step is a no-op under auto-mode.
Stance resolution: For each in-scope disputed finding, check whether decision.stance was already set by Step 0.5 bulk triage:
-
If stance already set (user picked "Trust Claude on all" or "Trust Codex on all" in Step 0.5): skip the stance question entirely. Announce in assistant text (e.g., "⚠ DISPUTED - using [Claude/Codex] stance from bulk triage"). Proceed directly to complexity classification.
-
If stance NOT set (user picked "Review each individually" in Step 0.5): call AskUserQuestion to resolve stance. The question text MUST lead with "⚠ DISPUTED" and the header MUST be "Disputed" so the signal is impossible to miss:
Call AskUserQuestion tool with:
questions: [{
question: "⚠ DISPUTED: [Finding title] in [file:line]. Claude: [issue]. Codex: [counter]. Whose assessment?",
header: "Disputed",
options: [
{ label: "Trust Claude", description: "[Claude's position in one line]" },
{ label: "Trust Codex", description: "[Codex's position in one line]" },
{ label: "More info", description: "Investigate both positions before deciding" },
{ label: "Skip", description: "Not a real issue" }
],
multiSelect: false
}]
If "More info", follow the investigation procedure from Step 1 but also highlight the specific disagreement with code evidence for each position. Then re-ask without "More info".
After stance is resolved, record decision.stance (claude or codex).
Then classify complexity using the winning stance's suggested fix:
- If trivial: Use the stance winner's suggested fix directly. Set
decision.disposition: "fix".
- If complex: Generate 2 approaches within the chosen stance (approaches should align with the assessment the user trusted). Present via AskUserQuestion with markdown previews, same pattern as Step 1 complex flow. The question text MUST lead with "⚠ DISPUTED" so the user knows this finding came from a disagreement even while picking an approach.
Step 3: Confirmed Medium & Low findings
Scope: every Medium or Low finding where codex_status != "Disputed". Disputed Med/Low findings were routed through Step 0.5 (for bulk triage) and Step 2 (for individual review), so they are NEVER batch-approved here. This is the fix for the biggest dispute-visibility hole: confirmed Med/Low can safely batch; disputed Med/Low cannot.
Auto-mode (AUTO_MODE = true): Auto-select "Fix all (Recommended)" for every Med/Low category. The Phase 7 verification gate catches regressions from aggressive fixes. Log to Auto-Mode Decision Log: Phase="Step 3", Finding="[category] (N findings)", Decision="Fix all", Reason="auto-mode: batch approve Med/Low". Skip the AskUserQuestion call below.
Batch these by category using AskUserQuestion:
Call AskUserQuestion tool with:
questions: [{
question: "N medium/low findings in [category]. How to handle?",
header: "Med/Low",
options: [
{ label: "Fix all (Recommended)", description: "Apply all suggested fixes in this category" },
{ label: "Review individually", description: "Decide on each finding separately" },
{ label: "Skip all", description: "Skip all findings in this category" }
],
multiSelect: false
}]
If "Fix all": Batch approve all findings in the category. Fixer agents handle implementation using the suggested fixes.
If "Review individually": Present each finding using the trivial-path AskUserQuestion (Fix/More info/Skip/Defer) - do NOT classify complexity up front for Med/Low findings. Complexity classification is deferred to the "More info" click:
- If user picks "Fix": use suggested fix directly (no complexity check needed).
- If user picks "More info": classify complexity. If complex (score >= 2), generate approaches with the same flow as Step 1 complex findings. If trivial, follow the standard investigation (read code, trace callers, git blame) then re-ask without "More info".
This is the opt-in path for approach selection on lower-severity findings. It avoids slowing the interview with approach generation for findings the user would have accepted as-is.
Step 4: Summary
Present the final fix plan to the user:
- N findings to fix (by severity)
- N findings skipped
- N findings deferred
- Files that will be modified
- For complex findings with chosen approaches: list the finding and chosen approach label
Auto-mode (AUTO_MODE = true): Auto-select "Proceed (Recommended)". Before proceeding, print the complete Auto-Mode Decision Log table:
Auto-Mode Decision Log
| Phase | Finding | Decision | Reason |
|-------|---------|----------|--------|
| Step 0 | - | Keep [style] | auto-mode: used inferred default |
| Step 0.5 | f-3: [title] | Skip | auto-mode: disputed finding, requires human judgment |
| Step 1 | f-1: [title] | Fix | auto-mode: trivial confirmed finding |
| Step 3 | [category] (N) | Fix all | auto-mode: batch approve Med/Low |
| ... | ... | ... | ... |
Log to Auto-Mode Decision Log: Phase="Step 4", Finding="-", Decision="Proceed", Reason="auto-mode: auto-confirmed fix plan". Skip the AskUserQuestion call below.
Call AskUserQuestion to confirm before proceeding:
Call AskUserQuestion tool with:
questions: [{
question: "Proceed with fixing N findings across M files?",
header: "Confirm plan",
options: [
{ label: "Proceed (Recommended)", description: "Spawn fix agents and implement all approved fixes" },
{ label: "Review plan again", description: "Go back and change fix decisions" },
{ label: "Cancel", description: "Abort without making changes" }
],
multiSelect: false
}]
Phase 3: Build Fix Plan
Findings arriving here are already deduplicated via Phase 1.5 canonical groups. Each finding carries a group_id and source_finding_ids from canonicalization.
Use canonical groups, not raw findings. When grouping work for agents, operate on the canonical finding list (entries where is_canonical: true). The group_id is the stable identifier passed to fixer agents and used in results tracking.
Early exit if nothing to fix. If no canonical findings have disposition == "fix", report "No fixes to apply - all findings were skipped or deferred." and skip to Phase 9 (with an empty fix summary).
Preserve user decisions. Each canonical finding carries its full decision from Phase 2. When building the fix plan, only include findings where disposition == "fix". Forward these decision fields to the fixer agent:
decision.approach: the label of the user's chosen approach (complex findings only)
decision.approach_detail: the code preview showing the intended fix (complex findings only)
decision.approach_source: whether the choice was default, user_choice, or codex_validated
decision.stance: for disputed findings, whose assessment (claude or codex) the user trusted
The fixer agent must respect the chosen approach. For trivial findings without an explicit approach, the fixer uses the suggested_fix from the review report.
Group all approved canonical findings by file path. Each unique file (or tight cluster of related files) becomes one agent's work unit.
Grouping rules:
- All findings for the same file go to one agent
- If a fix requires changes in two files that import each other, group them together
- Cross-cutting findings (no specific file) go to a dedicated agent, or are distributed across agents if each instance targets identifiable files
- Aim for roughly balanced work across agents, but never split a file across agents
- Maximum ~8 files per agent to keep context manageable
Record the fix plan (include canonical IDs for traceability):
- Agent 1: [files] - [N findings] (group_ids: g-1, g-3, g-7)
- Agent 2: [files] - [N findings] (group_ids: g-2, g-4)
- ...
Phase 4: Discover Verification Commands
Run a focused search to find exact development commands. Check in order:
mise.toml / .mise.toml (mise task runner)
package.json scripts / pyproject.toml / Makefile / Justfile
.github/workflows (CI jobs are authoritative)
docs/CONTRIBUTING.md or README.md
For each category, find the EXACT command:
- Lint/format:
mise run lint, golangci-lint run, ruff check ., npm run lint, etc.
- Static analysis:
mise run check, mypy ., staticcheck ./..., tsc --noEmit, etc.
- Unit tests:
mise run test, go test ./..., pytest, npm run test, etc.
- Integration/E2E:
mise run test:e2e, pytest tests/e2e/, go test -tags=integration, etc.
Store discovered commands for Phase 6.
Phase 5: Spawn Fix Team
If team creation fails (TeamCreate returns an error): fall back to spawning a single Agent (no team) that implements all fixes sequentially. Use the same fixer prompt template but include all findings in one prompt. Skip team-related operations (TaskCreate, TaskList polling). Read the single agent's results directly.
-
Create the team:
TeamCreate(team_name: "TEAM_NAME", description: "Fix implementation for BRANCH_NAME")
-
Create tasks for each agent using TaskCreate:
-
Spawn ALL fix agents in parallel (all Task calls in a single message):
Task(
subagent_type: "general-purpose",
team_name: "TEAM_NAME",
name: "fixer-1",
description: "Fix findings in [files]",
prompt: "[Fix Agent Prompt Template]"
)
Fix Agent Prompt Template
Each fix agent receives this prompt (substitute FILE_LIST, FINDINGS, CWD, TEAM_NAME, FIXER_NAME, and PLANNING_CONTEXT):
You are implementing code fixes for specific review findings. You have exclusive ownership of your assigned files - no other agent will touch them.
## Your Files (EXCLUSIVE OWNERSHIP)
FILE_LIST
Do NOT modify any files outside this list.
## Planning Context
PLANNING_CONTEXT
If a finding asks you to change something the planning context explicitly chose, prefer a minimal patch that addresses the specific defect without reversing the design decision. If the only viable fix would contradict the design decision, mark the finding as Blocked with that reason and fallback options — do not silently override the plan.
## Findings to Fix
FINDINGS
Each finding includes:
- **Finding ID**: canonical finding_id (f-N) from review report
- **File and line number**
- **Issue description**
- **Suggested fix**: the reviewer's original suggestion
- **Approach**: the user's chosen approach description, or "Use suggested fix" for trivial findings
- **Approach Source**: `default` | `user_choice` | `codex_validated`
- **Codex validation status**
## Process
### Step 1: Claim Your Task
Check TaskList for your assigned task. Claim it with TaskUpdate (set owner to your name, status to in_progress).
### Step 2: Understand Context
For each file you own:
1. Read the full file with the Read tool
2. Understand the surrounding code, not just the flagged lines
3. Check how your files relate to each other (imports, callers)
### Step 3: Implement Fixes
For each finding, in order of severity (Critical first, then High, Medium, Low):
1. Re-read the file BEFORE each fix - line numbers from the review report may have shifted due to earlier fixes in the same file
2. Find the actual code referenced by the finding (match by content, not just line number)
3. Implement the fix using the Edit tool
4. Verify the fix doesn't break surrounding code
5. If a fix would conflict with a higher-priority fix you already applied, skip it and note why
**Fix approach precedence** (use the first applicable rule):
1. **User's chosen approach** (when approach_source is `user_choice` or `codex_validated`): implement exactly what the approach describes. The user selected this approach for a reason.
2. **Suggested fix from review report** (when approach is "Use suggested fix" or approach_source is `default`): apply the reviewer's suggested fix.
3. **Session default style** (inferred by team lead in Phase 2 Step 0): if neither above applies, follow the session's default fix style (minimal_patch, refactor, or defensive).
4. **Minimal-change** (last resort): fix the issue with the smallest correct change.
**When the chosen approach allows refactoring** (e.g., "defensive refactor", "restructure"):
- Refactoring is allowed ONLY within your owned files
- No public API changes unless the approach explicitly calls for it
- Document the refactoring scope in your results file
**General quality rules:**
- Match existing code style exactly
- Don't add unnecessary comments explaining the fix
### Step 3.5: Handle Infeasible Approaches
After attempting all fixes, check if any finding's chosen approach was not viable after reading the code in context. This applies to both individually-approved findings and "Fix all" batch-approved findings.
**If an approach is not viable, do NOT silently pick an alternative.** Instead:
1. Mark the finding as **Blocked** in the results file
2. Include: why the approach is not viable given the actual code
3. Provide 2 concrete fallback options you considered (with brief descriptions)
4. Continue with remaining findings normally
5. Mark your task completed as usual - blocked findings are handled by the team lead
This is the safety net for hidden complexity. It is better to report a finding as blocked than to improvise a fix the user did not approve.
### Step 4: Self-Validate with Codex
After implementing all fixes, validate your changes using the Codex MCP tool.
Call `mcp__codex__codex` with:
- `sandbox`: `"read-only"`
- `approval-policy`: `"never"`
- `cwd`: "CWD"
Prompt:
Review these code changes for correctness. The changes implement fixes for specific review findings.
Changes Made
[List each fix: what was changed and why]
Verify
- Run
git diff to see all changes
- For each changed file, verify:
- The fix addresses the reported issue
- No new issues were introduced
- Code style is consistent
- No regressions in surrounding logic
- Report any problems found
If Codex finds issues with your fixes, correct them and re-validate.
If the Codex MCP tool is unavailable or times out, skip validation and note in your results file under Codex Validation: "Codex MCP unavailable - fixes not validated." Continue to Step 5.
### Step 5: Write Results to File
Write your results to `/tmp/fix-TEAM_NAME/FIXER_NAME.md` using the Write tool. Use this exact format:
## Fixes Applied
For each fix:
- **Finding ID**: f-N
- **Finding**: [original title]
- **File**: path:line
- **Approach used**: [chosen approach label, or "suggested fix"]
- **Change**: What was changed
- **Status**: Applied | Modified (how the fix differed from approach)
## Blocked Findings
For each finding where the chosen approach was not viable:
- **Finding ID**: f-N
- **Finding**: [original title]
- **File**: path:line
- **Chosen approach**: What the user selected
- **Why blocked**: Why this approach is not viable given the actual code
- **Fallback A**: [concrete alternative with brief description]
- **Fallback B**: [concrete alternative with brief description]
## Codex Validation
[Codex validation results - confirmed clean or issues found and corrected]
## Skipped Findings
[Any findings skipped due to conflicts with higher-priority fixes, with explanation]
After writing the results file, mark your task completed via TaskUpdate (status: completed). The team lead will read your results from the file after all fixers have finished.
After marking your task completed, your work is done. Do not wait for further instructions, attempt additional fixes, or offer to help with other tasks.
Phase 6: Wait for All Agents to Complete
CRITICAL: You MUST NOT call TaskUpdate to change the status of any fixer task. Only the fixer agent that owns a task may call TaskUpdate on it. If you believe a fixer is stuck, send them a message - do not mark their task completed yourself.
Wait for fixer agents to complete using idle notifications (the same pattern as team-branch-review Phase 4). Do NOT use a tight TaskList polling loop.
How it works: Teammates send idle notifications automatically when their turn ends. As each fixer goes idle, check TaskList to see if their task status is completed. Track which fixers have completed.
Completion check flow:
- Wait for a fixer idle notification
- Call TaskList() to check current task statuses
- If ALL tasks show
completed, proceed to collecting results
- If some tasks are still
in_progress, wait for the next idle notification
You MUST NOT do any of the following while any task is not completed:
- Run verification commands
- Send shutdown requests to any fixer
- Proceed to Phase 7.5, Phase 7, or Phase 8
- Present results to the user
- Call TaskUpdate on any fixer task
Messages from fixers are NOT completion signals. The task status completed (visible via TaskList) is the only exit condition.
Timeout handling: If a fixer has sent 3+ idle notifications without their task reaching completed status, send ONE follow-up message asking for status. If the fixer goes idle 3 more times after the follow-up without completing, declare that fixer failed and proceed without their results (note the gap in the report).
Collecting results: Once ALL tasks show status completed, read each fixer's results file:
For each fixer:
Read /tmp/fix-TEAM_NAME/{fixer-name}.md
Compile a summary of all results:
- Which findings were fixed (and how)
- Which findings were blocked (approach not viable, with fallback options)
- Which findings were skipped by agents (and why)
- Which agents failed (and what findings they owned)
Phase 7.5: Resolve Blocked Findings
See blocked-findings.md for the full resolution protocol, results file format, and follow-up fixer rules.
Auto-mode (AUTO_MODE = true): Skip all blocked findings without spawning follow-up fixers. For each blocked finding, log to Auto-Mode Decision Log: Phase="7.5", Finding="[finding_id]: [title]", Decision="Skip", Reason="auto-mode: blocked finding, requires human judgment". Proceed directly to Phase 7.
Process summary:
- Parse blocked findings from fixer results files (
## Blocked Findings section)
- If none, skip to Phase 7
- For each blocked finding, call AskUserQuestion with Fallback A, Fallback B, and Skip options
- If any fallbacks approved: spawn follow-up fixers (same prompt template, same ownership, results to
{name}-followup.md)
- Poll follow-up fixers via Phase 6 loop
- If follow-up fixer also blocks: report as unresolved (max 1 re-entry, no infinite loops)
- Proceed to Phase 7
(Fallback if reference file missing: for each blocked finding, present the fixer's two fallback options via AskUserQuestion. Spawn follow-up fixers for approved fallbacks using the Phase 5 prompt template. Max 1 follow-up round - if that also blocks, mark unresolved. Team lead never implements fixes directly.)
Phase 7: Verify
Gating condition: Only enter this phase when no pending follow-up fixer tasks remain. If Phase 7.5 spawned follow-up fixers, their polling and results collection must complete before verification runs. Verification covers ALL changes (original fixes + follow-up fixes).
Run the discovered verification commands:
[discovered lint command]
[discovered static analysis command]
[discovered test command]
[discovered e2e command]
If verification fails:
- Identify which fix caused the failure (check git diff by file)
- Report the failure to the user with the failing command output
- Do NOT attempt to auto-fix verification failures - let the user decide
Phase 8: Cleanup
Shut down all teammates in parallel (all shutdown requests in a single message):
SendMessage(type: "shutdown_request", recipient: "fixer-1", content: "Fixes complete")
SendMessage(type: "shutdown_request", recipient: "fixer-2", content: "Fixes complete")
# ... all remaining fixers simultaneously
After all teammates confirm shutdown:
TeamDelete()
Clean up temp directory:
rm -rf /tmp/fix-TEAM_NAME
Phase 9: Final Report and Commit Strategy
Present the summary to the user:
## Fix Implementation Summary
### Overview
- Findings fixed: N / N approved
- Findings resolved via fallback: N (originally blocked, fixed after user chose fallback)
- Findings skipped by user after block: N (user chose Skip in Phase 7.5)
- Findings unresolved: N (follow-up fixer also blocked; max re-entry hit)
- Findings skipped during implementation: N (conflicts with higher-priority fixes)
- Findings deferred: N
- Files modified: N
### Fixes Applied
[For each fix: finding_id, finding title, file:line, approach used, what changed]
### Blocked Finding Resolution
[For each finding that was originally blocked by a fixer:]
- **Finding ID**: f-N
- **Finding**: [title]
- **File**: [file:line]
- **Original approach**: [what was first attempted]
- **Why blocked**: [fixer's reason]
- **Resolution**: Resolved via fallback [A/B] | Skipped by user | Unresolved (follow-up also blocked)
- **Fallback used** (if resolved): [which fallback and what changed]
### Verification Results
- Lint: PASS/FAIL
- Static analysis: PASS/FAIL
- Tests: PASS/FAIL
- E2E: PASS/FAIL (if applicable)
### Skipped During Implementation
[Any findings skipped due to conflicts with higher-priority fixes]
### Codex Validation
- All fixes validated: YES/NO
- Issues found and corrected during validation: N
### Auto-Mode Summary (only when AUTO_MODE = true)
- Session default: [style]
- Disputed findings auto-skipped (Step 0.5): N
- Confirmed findings auto-approved: N
- Med/Low findings batch-approved: N
- Blocked findings auto-skipped: N
- Commit strategy: [what was actually used - fixup or single commit fallback]
- Rebase result: [Success | Failed (aborted, used single commit) | N/A]
Commit strategy with unresolved findings: If unresolved blocked findings remain (follow-up also blocked), note them in the commit summary but still offer commit options for the fixes that did succeed. The commit should not be held up by findings the user will handle manually.
If verification passed, call the AskUserQuestion tool for commit strategy:
Auto-mode (AUTO_MODE = true): Auto-select "Fixup into original commits (Recommended)". Fixup produces cleaner history and is the existing recommended default. Log to Auto-Mode Decision Log: Phase="9", Finding="-", Decision="Fixup into original commits", Reason="auto-mode: recommended commit strategy". Skip the AskUserQuestion call below.
Call AskUserQuestion tool with:
questions: [{
question: "All fixes verified. How do you want to commit the changes?",
header: "Commit",
options: [
{ label: "Fixup into original commits (Recommended)", description: "Amend each fix into the branch commit that introduced the issue" },
{ label: "Single fix commit", description: "All fixes in one commit with a summary message" },
{ label: "Multiple commits", description: "Group fixes into separate logical commits" },
{ label: "Don't commit", description: "Leave changes uncommitted for manual review" }
],
multiSelect: false
}]
Once the user selects a strategy (other than "Don't commit"), spawn a subagent to handle the commits:
Task(
subagent_type: "general-purpose",
model: "sonnet",
description: "Commit review fixes",
prompt: "[Commit Agent Prompt - see below]"
)
Use Sonnet for the commit agent since this is mechanical work that doesn't need Opus.
Commit Agent Prompt (substitute STRATEGY, FIXES_APPLIED, BASE_COMMIT, and AUTO_MODE):
You are committing code review fixes. The fixes are already applied and verified. Use the /commit skill for all commits.
Strategy: STRATEGY
Auto mode: AUTO_MODE
Fixes applied:
FIXES_APPLIED
## Instructions by Strategy
### If "Fixup into original commits":
For each fix, identify which commit on the branch introduced the code being fixed:
1. Run `git log --oneline BASE_COMMIT..HEAD -- <file>` and `git blame <file>` for the fixed lines
2. Determine the target commit
3. Stage only the files for this fix: `git add <specific files>`
4. Create a fixup commit: `git commit --fixup=<target-commit-hash>`
5. Repeat for each fix
**If AUTO_MODE is true:** Run the rebase automatically without asking. Execute `GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash BASE_COMMIT`. If the rebase fails (conflicts or other errors): run `git rebase --abort`, then `git reset --soft BASE_COMMIT` to collapse all commits (including fixup commits) into staged changes, then use /commit to create a single fix commit with a summary message. Report what happened.
**If AUTO_MODE is false:** Call AskUserQuestion to offer running the rebase:
Call AskUserQuestion tool with:
questions: [{
question: "Fixup commits created. Squash them into the original commits now?",
header: "Autosquash",
options: [
{ label: "Run rebase (Recommended)", description: "Run git rebase -i --autosquash BASE_COMMIT with GIT_SEQUENCE_EDITOR=true to auto-squash" },
{ label: "I'll do it myself", description: "Run git rebase -i --autosquash BASE_COMMIT manually when ready" }
],
multiSelect: false
}]
If the user selects "Run rebase": execute `GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash BASE_COMMIT` and report the result. If the rebase fails (e.g., conflicts), report the error and suggest the user resolve manually.
If the user selects "I'll do it myself": report the exact command they need to run.
### If "Single fix commit":
Stage all changed files and use the /commit skill to create one commit summarizing all fixes.
### If "Multiple commits":
Group the fixes by logical concern (e.g., all security fixes together, all correctness fixes together).
For each group:
1. Stage only the files for that group: `git add <specific files>`
2. Use the /commit skill to create a commit for that group
Report back what commits were created.
Don't commit: Leave all changes in the working tree. Suggest the user review with git diff.
If verification failed, do NOT offer commit options. Report the failures and let the user decide how to proceed.
Error Handling
| Scenario | Recovery |
|---|
| Fix agent fails or times out | Note which findings weren't fixed, continue with others |
| Codex MCP unavailable for an agent | Agent reports unvalidated fixes, noted in report |
| Codex unavailable during approach validation | Note unvalidated in option description, proceed without |
| Markdown previews don't render | Fall back to description-only options |
| Verification fails | Report failure details, do NOT auto-fix |
| Team spawn fails | Fall back to single-agent fix implementation |
| No findings approved by user | Report "No fixes to apply" and exit |
| User declines all fallback options for blocked finding | Mark as skipped in final report |
| Follow-up fixer also blocked (max re-entry) | Report as unresolved, user handles manually |
| Complexity classification timeout | Default to complex, proceed with approach generation |
| Reference file missing | Use inline fallback instructions in the phase description |
| --auto with no findings to fix | Report "No fixes to apply" and exit (same as non-auto) |
| --auto rebase fails during fixup | Abort rebase, fall back to single fix commit |
| --auto with all findings disputed | Skip all, report empty fix plan, exit cleanly |
Guidelines
- Model inheritance: Do NOT set a
model parameter on spawned agents - they inherit the global model setting automatically
- Exclusive file ownership: Never assign the same file to two agents
- Parallel execution: Spawn ALL fix agents simultaneously in one message
- Respect approach precedence: User's chosen approach > suggested fix > session default > minimal-change
- Preserve user decisions: Only fix what the user approved. Block (don't improvise) when approach is not viable.
- Report blocked findings: Fixer agents mark infeasible approaches as Blocked with fallback options for the team lead.
- Self-validate: Each agent validates with Codex before reporting done
- Don't auto-fix verification failures: Report and let the user decide
- Never mark fixer tasks: You MUST NOT call TaskUpdate on any fixer task. Only fixers mark their own tasks completed.
- Results come from files: Fixers write results to
/tmp/fix-TEAM_NAME/. Do not use message content as results.
- Bounded iteration: Phase 7.5 allows at most 1 follow-up round. If a follow-up fixer also blocks, the finding becomes unresolved. No infinite loops.
- Verify after all fixes: Phase 7 verification runs only after all fixers (original + follow-up) have completed.
- Auto-mode safety: --auto skips disputed and blocked findings rather than guessing. Human judgment is required for disagreements.
- Dispute visibility is first-class: Disputed findings (codex_status = "Disputed") are triaged in bulk at Phase 2 Step 0.5 and always flagged with "⚠ DISPUTED" when reviewed individually. Disputed Med/Low findings MUST NOT be silently batch-approved in Step 3.
- Auto-mode auditability: Every auto-decision is logged to the Auto-Mode Decision Log table, printed in full before execution begins.
- Auto-mode parsing: --auto must be the first token in ARGUMENTS. If it appears elsewhere, it is part of the report text.
- Auto-mode backward compatibility: When --auto is absent, all behavior is identical to the non-auto flow. No code paths change.
$ARGUMENTS