diff --git a/ralph.sh b/ralph.sh index baff052a..ea29c353 100755 --- a/ralph.sh +++ b/ralph.sh @@ -39,32 +39,40 @@ PROGRESS_FILE="$SCRIPT_DIR/progress.txt" ARCHIVE_DIR="$SCRIPT_DIR/archive" LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch" +# ------------------------------------------------------------ +# Fail fast on malformed PRDs before starting the agent loop +# ------------------------------------------------------------ +if [ -f "$SCRIPT_DIR/scripts/validate_prd.sh" ]; then + "$SCRIPT_DIR/scripts/validate_prd.sh" "$PRD_FILE" +fi + +# ------------------------------------------------------------ # Archive previous run if branch changed +# ------------------------------------------------------------ if [ -f "$PRD_FILE" ] && [ -f "$LAST_BRANCH_FILE" ]; then CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") LAST_BRANCH=$(cat "$LAST_BRANCH_FILE" 2>/dev/null || echo "") - + if [ -n "$CURRENT_BRANCH" ] && [ -n "$LAST_BRANCH" ] && [ "$CURRENT_BRANCH" != "$LAST_BRANCH" ]; then - # Archive the previous run DATE=$(date +%Y-%m-%d) - # Strip "ralph/" prefix from branch name for folder FOLDER_NAME=$(echo "$LAST_BRANCH" | sed 's|^ralph/||') ARCHIVE_FOLDER="$ARCHIVE_DIR/$DATE-$FOLDER_NAME" - + echo "Archiving previous run: $LAST_BRANCH" mkdir -p "$ARCHIVE_FOLDER" [ -f "$PRD_FILE" ] && cp "$PRD_FILE" "$ARCHIVE_FOLDER/" [ -f "$PROGRESS_FILE" ] && cp "$PROGRESS_FILE" "$ARCHIVE_FOLDER/" echo " Archived to: $ARCHIVE_FOLDER" - - # Reset progress file for new run + echo "# Ralph Progress Log" > "$PROGRESS_FILE" echo "Started: $(date)" >> "$PROGRESS_FILE" echo "---" >> "$PROGRESS_FILE" fi fi +# ------------------------------------------------------------ # Track current branch +# ------------------------------------------------------------ if [ -f "$PRD_FILE" ]; then CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "") if [ -n "$CURRENT_BRANCH" ]; then @@ -72,7 +80,9 @@ if [ -f "$PRD_FILE" ]; then fi fi -# Initialize progress file if it doesn't exist +# ------------------------------------------------------------ +# Initialize progress file if needed +# ------------------------------------------------------------ if [ ! -f "$PROGRESS_FILE" ]; then echo "# Ralph Progress Log" > "$PROGRESS_FILE" echo "Started: $(date)" >> "$PROGRESS_FILE" @@ -81,8 +91,12 @@ fi echo "Starting Ralph - Tool: $TOOL - Max iterations: $MAX_ITERATIONS" -for i in $(seq 1 $MAX_ITERATIONS); do +# ------------------------------------------------------------ +# Main agent loop +# ------------------------------------------------------------ +for i in $(seq 1 "$MAX_ITERATIONS"); do echo "" + echo "===============================================================" echo " Ralph Iteration $i of $MAX_ITERATIONS ($TOOL)" echo "===============================================================" @@ -102,7 +116,7 @@ for i in $(seq 1 $MAX_ITERATIONS); do echo "Completed at iteration $i of $MAX_ITERATIONS" exit 0 fi - + echo "Iteration $i complete. Continuing..." sleep 2 done diff --git a/scripts/validate_prd.sh b/scripts/validate_prd.sh new file mode 100644 index 00000000..517d4648 --- /dev/null +++ b/scripts/validate_prd.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -e + +FILE=${1:-prd.json} + +# Ensure PRD file exists +if [ ! -f "$FILE" ]; then + echo "✗ PRD file not found: $FILE" + exit 1 +fi + +# Ensure jq is available +if ! command -v jq >/dev/null 2>&1; then + echo "✗ jq is required but not installed" + exit 1 +fi + +# Fields that must exist on each user story +REQUIRED_FIELDS=("id" "title" "priority") +ERROR=0 + +echo "Validating PRD: $FILE" +echo "-------------------------" + +# Ensure userStories exists and is an array +if ! jq -e '.userStories | type == "array"' "$FILE" >/dev/null; then + echo "✗ 'userStories' must be an array" + exit 1 +fi + +# Check for duplicate IDs +IDS=$(jq -r '.userStories[].id' "$FILE") +DUP_IDS=$(echo "$IDS" | sort | uniq -d) +if [ -n "$DUP_IDS" ]; then + echo "✗ Duplicate userStory IDs:" + echo "$DUP_IDS" + ERROR=1 +fi + +# Validate required fields exist (existence, not truthiness) +COUNT=$(jq '.userStories | length' "$FILE") +for ((i=0; i