#!/usr/bin/env bash set -euo pipefail MAX_ITERS=25 prev_remaining=-1 for ((i=1; i<=MAX_ITERS; i++)); do remaining=$(grep -c '^### \[ \]' IMPLEMENTATION.md || true) [ "$remaining" -eq 0 ] && { echo "All increments complete."; break; } # Stuck-detector: if last run didn't tick a box, an increment is failing — stop. if [ "$remaining" -eq "$prev_remaining" ]; then echo "No progress last iteration — stopping for human review."; exit 1 fi prev_remaining=$remaining echo "=== Iteration $i ($remaining increments left) ===" claude -p "Read SPEC.md, CLAUDE.md, IMPLEMENTATION.md and PLAN.md. Implement ONLY the next unchecked increment in IMPLEMENTATION.md — nothing else. Then run: dotnet build && dotnet test && dotnet format --verify-no-changes. If all pass: tick that increment's checkbox in IMPLEMENTATION.md and git commit with a message naming the increment. If anything fails: revert your changes with git, leave the box unchecked, and explain what broke." \ --allowedTools "Read,Edit,Write,Bash(dotnet:*),Bash(git add:*),Bash(git commit:*),Bash(git checkout:*)" \ || { echo "Claude invocation errored on iteration $i."; exit 1; } # Independent gate — the script re-verifies the committed state itself, # never trusting Claude's self-report. if ! ( dotnet build && dotnet test ); then echo "Verification failed after iteration $i — stopping for review."; exit 1 fi done