- Nx 22.7 monorepo (pnpm 11.1, TypeScript 5.9, Node 24) - apps/api: NestJS 11 (CJS conforme CODING-RULES.md PGD-DB-004) - apps/web: React 19 + Vite 8 (ESM) - libs/shared/api-interface: Zod contract base - Docker Compose dev: Postgres 18, Valkey 8, MinIO, Mailpit - WDS artifacts: - design-artifacts/A-Product-Brief/ (5 docs canônicos + 16 dialogs) - design-artifacts/B-Trigger-Map/ (hub + 4 personas + feature impact) - Stack canon: STACK.md v2.2 + CODING-RULES.md v2.0 + brand.md - AGENTS.md + README.md como entrada para devs/agentes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.1 KiB
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.
# 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:
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
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)
# 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
# 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
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] Manual Fix - Update sprint-status.yaml yourself
- [2] Run with Claude - Re-run code-review with Claude agent
- [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:
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:
"$scripts" orchestrator-helper verify-code-review {story_id} --state-file "$state_file"
# Returns: {"verified":true/false, "sprint_status":"...", ...}