#!/usr/bin/env bash
set -euo pipefail

# Ralph loop: repeatedly hand a TASK.md file to Claude and let it iterate.
#
# All task-specific instructions (phases, rules, priorities, tools, etc.)
# belong in the task file itself — this script stays generic and just drives
# the loop.
#
# Usage:
#   ./ralph-loop.sh [TASK_FILE] [ITERATIONS]
#
# Environment variables:
#   TASK_FILE      Path to the task markdown file (default: TASK.md)
#   ITERATIONS     Number of iterations to run (default: 100)
#   REFLECTION_FILE Path to the reflection file the agent reads/writes
#                  between runs (default: REFLECTION.md)
#   MODEL          Claude model to use (default: opus)
#   WORK_DIR       Directory to run the loop in (default: script dir)
#   PRE_CMD        Optional command to run once before the loop starts
#   ITER_CMD       Optional command to run after each iteration
#   LOG_DIR        Where to write per-iteration logs
#                  (default: $WORK_DIR/ralph-logs)
#   STOP_FILE      If the agent creates this file, the loop exits early
#                  (default: DONE)

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

TASK_FILE="${1:-${TASK_FILE:-TASK.md}}"
TOTAL="${2:-${ITERATIONS:-100}}"
REFLECTION_FILE="${REFLECTION_FILE:-REFLECTION.md}"
MODEL="${MODEL:-opus}"
WORK_DIR="${WORK_DIR:-$SCRIPT_DIR}"
LOG_DIR="${LOG_DIR:-$WORK_DIR/ralph-logs}"
STOP_FILE="${STOP_FILE:-DONE}"

cd "$WORK_DIR"

if [ ! -f "$TASK_FILE" ]; then
  echo "ERROR: task file not found: $TASK_FILE" >&2
  echo "Create a $TASK_FILE describing what you want the agent to do," >&2
  echo "or pass a path: ./ralph-loop.sh path/to/task.md" >&2
  exit 1
fi

mkdir -p "$LOG_DIR"

echo "Ralph loop configuration:"
echo "  Task file:       $TASK_FILE"
echo "  Reflection file: $REFLECTION_FILE"
echo "  Iterations:      $TOTAL"
echo "  Model:           $MODEL"
echo "  Work dir:        $WORK_DIR"
echo "  Log dir:         $LOG_DIR"
echo ""

if [ -n "${PRE_CMD:-}" ]; then
  echo "Running PRE_CMD: $PRE_CMD"
  bash -c "$PRE_CMD"
fi

for i in $(seq 1 "$TOTAL"); do
  TIMESTAMP=$(date +%Y%m%d-%H%M%S)
  LOG_FILE="$LOG_DIR/run-${i}-${TIMESTAMP}.log"

  echo ""
  echo "========================================="
  echo "  RALPH LOOP — iteration $i / $TOTAL"
  echo "  $(date)"
  echo "  Log: $LOG_FILE"
  echo "========================================="
  echo ""

  PROMPT="Read the file $TASK_FILE in this repository and execute it end-to-end. \
The task file is the source of truth — follow its phases, rules, and priorities exactly. \
This is iteration $i of $TOTAL. \
If $REFLECTION_FILE already exists from a previous iteration, read it first and factor in \
prior learnings — do not repeat the same mistakes, and build on what was already done. \
Update $REFLECTION_FILE at the end of this iteration with what you learned and what should \
change next time. \
Do not ask the user for input at any point — make reasonable decisions and keep going. \
When all success criteria in the task file are met, create a file named '$STOP_FILE' \
(just 'touch $STOP_FILE') to signal the loop should stop. Only create it when you are \
confident the task is fully complete. \
When you finish, print a concise summary of what you accomplished in this iteration."

  claude \
    --print \
    --dangerously-skip-permissions \
    --model "$MODEL" \
    --verbose \
    "$PROMPT" \
    2>&1 | tee "$LOG_FILE"

  EXIT_CODE=${PIPESTATUS[0]}

  echo ""
  echo "Iteration $i finished with exit code $EXIT_CODE at $(date)"
  echo "---"

  if [ "$EXIT_CODE" -ne 0 ]; then
    echo "WARNING: Iteration $i exited non-zero ($EXIT_CODE). Continuing..."
  fi

  if [ -n "${ITER_CMD:-}" ]; then
    echo "Running ITER_CMD: $ITER_CMD"
    bash -c "$ITER_CMD" || true
  fi

  if [ -f "$WORK_DIR/$STOP_FILE" ]; then
    echo ""
    echo "Stop file found ($STOP_FILE) — task complete, exiting early after iteration $i."
    break
  fi
done

echo ""
echo "========================================="
echo "  RALPH LOOP COMPLETE — $TOTAL iterations"
echo "========================================="
