From 9e5e760c7fa273ab492b5e7a48a8ecc7ee51f0ea Mon Sep 17 00:00:00 2001 From: sambella Date: Sun, 11 Jan 2026 13:41:34 +0530 Subject: [PATCH 1/6] Add PRD validation script to fail fast on common mistakes --- scripts/validate_prd.sh | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 scripts/validate_prd.sh diff --git a/scripts/validate_prd.sh b/scripts/validate_prd.sh new file mode 100644 index 00000000..27f19bdf --- /dev/null +++ b/scripts/validate_prd.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -e + +FILE=${1:-prd.json} + +if [ ! -f "$FILE" ]; then + echo "✗ PRD file not found: $FILE" + exit 1 +fi + +REQUIRED_FIELDS=("id" "description" "status" "priority") +VALID_STATUS=("todo" "in_progress" "done") + +ERROR=0 + +echo "Validating PRD: $FILE" +echo "-------------------------" + +IDS=$(jq -r '.tasks[].id' "$FILE") + +# Duplicate IDs +DUP_IDS=$(echo "$IDS" | sort | uniq -d) +if [ -n "$DUP_IDS" ]; then + echo "✗ Duplicate task IDs:" + echo "$DUP_IDS" + ERROR=1 +fi + +# Validate each task +COUNT=$(jq '.tasks | length' "$FILE") + +for ((i=0; i Date: Mon, 12 Jan 2026 10:36:52 +0530 Subject: [PATCH 2/6] Align PRD validator with Ralph userStories schema --- scripts/validate_prd.sh | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/scripts/validate_prd.sh b/scripts/validate_prd.sh index 27f19bdf..39de63bc 100644 --- a/scripts/validate_prd.sh +++ b/scripts/validate_prd.sh @@ -8,41 +8,39 @@ if [ ! -f "$FILE" ]; then exit 1 fi -REQUIRED_FIELDS=("id" "description" "status" "priority") -VALID_STATUS=("todo" "in_progress" "done") +if ! command -v jq >/dev/null 2>&1; then + echo "✗ jq is required but not installed" + exit 1 +fi +REQUIRED_FIELDS=("id" "title" "priority") ERROR=0 echo "Validating PRD: $FILE" echo "-------------------------" -IDS=$(jq -r '.tasks[].id' "$FILE") +# Collect all user story IDs +IDS=$(jq -r '.userStories[].id' "$FILE") -# Duplicate IDs +# Check for duplicate IDs DUP_IDS=$(echo "$IDS" | sort | uniq -d) if [ -n "$DUP_IDS" ]; then - echo "✗ Duplicate task IDs:" + echo "✗ Duplicate userStory IDs:" echo "$DUP_IDS" ERROR=1 fi -# Validate each task -COUNT=$(jq '.tasks | length' "$FILE") +# Validate each user story +COUNT=$(jq '.userStories | length' "$FILE") for ((i=0; i Date: Fri, 16 Jan 2026 14:15:54 +0530 Subject: [PATCH 3/6] Run PRD validation before starting Ralph loop --- ralph.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ralph.sh b/ralph.sh index 677b120c..9d6aa42d 100755 --- a/ralph.sh +++ b/ralph.sh @@ -11,6 +11,14 @@ 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/validator_prd.sh" ]; then + "$SCRIPT_DIR/validator_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 "") From 4c9488950d5148dc51d52ab6f339dd74b4f3c640 Mon Sep 17 00:00:00 2001 From: sambella Date: Wed, 21 Jan 2026 21:15:18 +0530 Subject: [PATCH 4/6] Fix PRD validation to check field existence using jq has() --- scripts/validate_prd.sh | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/validate_prd.sh b/scripts/validate_prd.sh index 39de63bc..e8eae4e4 100644 --- a/scripts/validate_prd.sh +++ b/scripts/validate_prd.sh @@ -3,22 +3,31 @@ 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 + # Collect all user story IDs IDS=$(jq -r '.userStories[].id' "$FILE") @@ -35,8 +44,8 @@ COUNT=$(jq '.userStories | length' "$FILE") for ((i=0; i Date: Fri, 23 Jan 2026 23:34:04 +0530 Subject: [PATCH 5/6] Fix validator path in ralph.sh --- scripts/validate_prd.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/validate_prd.sh b/scripts/validate_prd.sh index e8eae4e4..3600abae 100644 --- a/scripts/validate_prd.sh +++ b/scripts/validate_prd.sh @@ -45,10 +45,11 @@ COUNT=$(jq '.userStories | length' "$FILE") for ((i=0; i Date: Mon, 2 Feb 2026 09:45:36 +0530 Subject: [PATCH 6/6] Fix validator path and run PRD validation before loop --- ralph.sh | 39 +++++++++++++++++++++------------------ scripts/validate_prd.sh | 14 +++++--------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/ralph.sh b/ralph.sh index 9d6aa42d..20845d46 100755 --- a/ralph.sh +++ b/ralph.sh @@ -11,40 +11,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/validator_prd.sh" ]; then - "$SCRIPT_DIR/validator_prd.sh" "$PRD_FILE" +# ------------------------------------------------------------ +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 @@ -52,7 +52,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" @@ -61,23 +63,24 @@ fi echo "Starting Ralph - 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" echo "═══════════════════════════════════════════════════════" - - # Run amp with the ralph prompt + OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr) || true - - # Check for completion signal + if echo "$OUTPUT" | grep -q "COMPLETE"; then echo "" echo "Ralph completed all tasks!" 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 index 3600abae..517d4648 100644 --- a/scripts/validate_prd.sh +++ b/scripts/validate_prd.sh @@ -28,10 +28,8 @@ if ! jq -e '.userStories | type == "array"' "$FILE" >/dev/null; then exit 1 fi -# Collect all user story IDs -IDS=$(jq -r '.userStories[].id' "$FILE") - # 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:" @@ -39,17 +37,15 @@ if [ -n "$DUP_IDS" ]; then ERROR=1 fi -# Validate each user story +# Validate required fields exist (existence, not truthiness) COUNT=$(jq '.userStories | length' "$FILE") - for ((i=0; i