# Code Review Loop Pattern (v2.3)

**Purpose:** Code review loop execution using script-based automation with per-task agent configuration.

---

## Configuration

```
reviewCycle = 1
maxCycles = 5
```

---

## Agent Selection (v3.0)

Code-review uses **deterministic agent selection** from the agents file, same as all other workflow steps.

```bash
# Resolve agent for review task (uses agents file)
resolve_agent_for_task "review" "$state_file" "{story_id}"
review_agent="$primary_agent"
review_fallback="$fallback_agent"

echo "Code review using: primary=$review_agent, fallback=$review_fallback"
```

**Per-task override example in state document:**
```yaml
agentConfig:
  defaultPrimary: "codex"
  defaultFallback: "claude"
  perTask:
    review:
      primary: "claude"      # Override: use Claude for reviews
      fallback: false        # Disable fallback for reviews
```

**Note on Codex:** If Codex is configured for reviews and fails to update sprint-status, the `story-automator monitor-session --workflow review` verification catches this and returns `final_state: "incomplete"`, triggering the escalation path below.

---

## Loop Execution

**WHILE reviewCycle ≤ maxCycles:**

### 1. Spawn Review Session

```bash
scripts="$(printf "%s" "{project_root}/<installed-skill-root>/bmad-story-automator/scripts/story-automator")"
[ -n "$scripts" ] || { echo "story-automator helper not found" >&2; exit 1; }

# ⚠️ CRITICAL: --command is REQUIRED - without it, no command runs → never_active failure!
# Spawn with story-automator tmux-wrapper (handles naming, state cleanup, env vars)
session_name=$("$scripts" tmux-wrapper spawn review {epic} {story_id} \
  --agent "$review_agent" \
  --cycle $reviewCycle \
  --command "$("$scripts" tmux-wrapper build-cmd review {story_id} --agent "$review_agent" --state-file "$state_file")")
```

### 2. Monitor Session with Verification (v2.2)

```bash
# Single call replaces 14+ API roundtrips
# Pass --workflow and --story-key for completion verification
result=$("$scripts" monitor-session "$session_name" --json --verbose \
  --agent "$review_agent" \
  --workflow review --story-key {story_id} --state-file "$state_file")
final_state=$(echo "$result" | jq -r '.final_state')
output_file=$(echo "$result" | jq -r '.output_file')
```

**Note:** The `--workflow review --story-key` parameters enable sprint-status verification before marking complete.

### 3. Parse Output

```bash
# Sub-agent parsing (haiku, 99% cheaper than main context)
parsed=$("$scripts" orchestrator-helper parse-output "$output_file" review --state-file "$state_file")
```

### 4. Verify Sprint Status

```bash
status=$("$scripts" orchestrator-helper sprint-status get {story_key})
is_done=$(echo "$status" | jq -r '.done')
```

---

## Decision Logic

### Handle final_state (v2.2)

**IF final_state == "completed":**
- Session verified complete (sprint-status shows "done")
- Log "Code review passed, story marked done"
- Cleanup: `"$scripts" tmux-wrapper kill "$session_name"`
- **EXIT LOOP** → proceed to Git Commit

**IF final_state == "incomplete":** (v2.2 - Codex-specific)
- Session idle but sprint-status NOT updated
- Cleanup: `"$scripts" tmux-wrapper kill "$session_name"`
- Increment `reviewCycle`
- If `reviewCycle <= maxCycles`: count this as a failed attempt and **CONTINUE** with a retry
- If `reviewCycle > maxCycles`: Escalate with CRITICAL priority (Trigger #8), then present options:
  1. **[1] Manual Fix** - Update sprint-status.yaml yourself
  2. **[2] Run with Claude** - Re-run code-review with Claude agent
  3. **[3] Skip Story** - Mark story as skipped and continue
- **HALT** — wait for user choice only after maxCycles is exhausted

**IF final_state == "crashed" or "stuck":**
- Log "Review session failed: $final_state"
- Cleanup: `"$scripts" tmux-wrapper kill "$session_name"`
- Increment reviewCycle
- **CONTINUE** (retry with new session)

### Handle is_done check

**IF is_done == true:**
- Log "Sprint-status verified done"
- **EXIT LOOP** → proceed to Git Commit

**IF is_done == false AND final_state == "completed":**
- This shouldn't happen with v2.2 verification
- Fallback: check story file status
- If story file shows "done", treat as complete

**IF reviewCycle > maxCycles:**
- Check escalation: `"$scripts" orchestrator-helper escalate review-loop "cycles=$reviewCycle"`
- **HALT** — wait for user choice

---

## Sprint-Status Verification (v3.0)

Status is determined by **CRITICAL issues remaining** after auto-fix:
- "done" → 0 CRITICAL issues, proceed to commit
- "in-progress" → 1+ CRITICAL issues, new review cycle

HIGH/MEDIUM/LOW issues are tracked as action items but don't block automation.

---

## Output Verification Fallback (v1.4.0)

If `output_verified == false` or output truncated, use story file fallback:

```bash
file_status=$("$scripts" orchestrator-helper story-file-status {story_id})
# If status == "done", skip parsing - story is complete
```

---

## Verification Command (v2.2)

Check if code-review actually completed:

```bash
"$scripts" orchestrator-helper verify-code-review {story_id} --state-file "$state_file"
# Returns: {"verified":true/false, "sprint_status":"...", ...}
```
