claude-evolve 1.2.14 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,8 +44,8 @@ fi
44
44
  # Prepare logging
45
45
  mkdir -p logs
46
46
 
47
- # Track active workers
48
- declare -A worker_pids=()
47
+ # Track active workers (using regular array for compatibility)
48
+ worker_pids=()
49
49
  consecutive_failures=0
50
50
  MAX_FAILURES=10
51
51
  rate_limit_hit=false
@@ -57,7 +57,7 @@ count_pending() {
57
57
  return
58
58
  fi
59
59
 
60
- echo "$csv_content" | awk -F',' 'NR>1 && $5 == "pending" { count++ } END { print count+0 }'
60
+ echo "$csv_content" | awk -F',' 'NR>1 && ($5 == "pending" || $5 == "") { count++ } END { print count+0 }'
61
61
  }
62
62
 
63
63
  # Start a worker
@@ -68,7 +68,7 @@ start_worker() {
68
68
  echo "[DISPATCHER] Starting worker..."
69
69
  $worker_cmd &
70
70
  local pid=$!
71
- worker_pids[$pid]=1
71
+ worker_pids+=($pid)
72
72
  echo "[DISPATCHER] Worker $pid started"
73
73
  }
74
74
 
@@ -100,13 +100,17 @@ handle_worker_exit() {
100
100
  esac
101
101
 
102
102
  # Remove from tracking
103
- unset worker_pids[$pid]
103
+ local new_pids=()
104
+ for p in "${worker_pids[@]}"; do
105
+ [[ $p != "$pid" ]] && new_pids+=($p)
106
+ done
107
+ worker_pids=("${new_pids[@]}")
104
108
  }
105
109
 
106
110
  # Signal handler for graceful shutdown
107
111
  shutdown_workers() {
108
112
  echo "[DISPATCHER] Shutting down workers..."
109
- for pid in "${!worker_pids[@]}"; do
113
+ for pid in "${worker_pids[@]}"; do
110
114
  if kill -0 "$pid" 2>/dev/null; then
111
115
  echo "[DISPATCHER] Stopping worker $pid"
112
116
  kill -TERM "$pid" 2>/dev/null || true
@@ -119,15 +123,17 @@ shutdown_workers() {
119
123
  sleep 1
120
124
  ((timeout--))
121
125
 
122
- for pid in "${!worker_pids[@]}"; do
123
- if ! kill -0 "$pid" 2>/dev/null; then
124
- unset worker_pids[$pid]
126
+ local new_pids=()
127
+ for pid in "${worker_pids[@]}"; do
128
+ if kill -0 "$pid" 2>/dev/null; then
129
+ new_pids+=($pid)
125
130
  fi
126
131
  done
132
+ worker_pids=("${new_pids[@]}")
127
133
  done
128
134
 
129
135
  # Force kill remaining workers
130
- for pid in "${!worker_pids[@]}"; do
136
+ for pid in "${worker_pids[@]}"; do
131
137
  if kill -0 "$pid" 2>/dev/null; then
132
138
  echo "[DISPATCHER] Force killing worker $pid"
133
139
  kill -KILL "$pid" 2>/dev/null || true
@@ -163,24 +169,18 @@ while true; do
163
169
 
164
170
  echo "[DISPATCHER] Status: $pending_count pending, $active_workers active workers"
165
171
 
166
- # If no pending work and no active workers, try to generate more ideas
172
+ # Debug: Show CSV status if no pending
173
+ if [[ $pending_count -eq 0 ]]; then
174
+ total_rows=$(read_csv_with_lock csv_content && echo "$csv_content" | wc -l | xargs)
175
+ complete_count=$(read_csv_with_lock csv_content && echo "$csv_content" | awk -F',' 'NR>1 && $5 == "complete" { count++ } END { print count+0 }')
176
+ echo "[DISPATCHER] CSV has $((total_rows-1)) total candidates, $complete_count complete"
177
+ fi
178
+
179
+ # If no pending work and no active workers, we're done
167
180
  if [[ $pending_count -eq 0 && $active_workers -eq 0 ]]; then
168
- echo "[DISPATCHER] No work available. Generating new ideas..."
169
-
170
- ideate_script="$SCRIPT_DIR/claude-evolve-ideate"
171
- if [[ ! -f "$ideate_script" ]]; then
172
- echo "[DISPATCHER] No ideate script found. Evolution complete."
173
- break
174
- fi
175
-
176
- if ! "$ideate_script"; then
177
- echo "[ERROR] Failed to generate new ideas" >&2
178
- break
179
- fi
180
-
181
- # Recount after ideation
182
- pending_count=$(count_pending)
183
- echo "[DISPATCHER] Generated ideas. New pending count: $pending_count"
181
+ echo "[DISPATCHER] No pending candidates found. Evolution complete."
182
+ echo "[DISPATCHER] Run 'claude-evolve ideate' to generate more candidates."
183
+ break
184
184
  fi
185
185
 
186
186
  # Start workers if we have pending work and capacity
@@ -198,14 +198,14 @@ while true; do
198
198
 
199
199
  # Wait for any worker to finish
200
200
  if [[ $active_workers -gt 0 ]]; then
201
- # Wait for any child process to exit
202
- wait -n
201
+ # Poll for finished workers (macOS compatible)
202
+ sleep 5 # Check every 5 seconds
203
203
 
204
204
  # Check which workers have finished
205
- for pid in "${!worker_pids[@]}"; do
205
+ for pid in "${worker_pids[@]}"; do
206
206
  if ! kill -0 "$pid" 2>/dev/null; then
207
207
  # Get exit status
208
- wait "$pid"
208
+ wait "$pid" 2>/dev/null
209
209
  exit_code=$?
210
210
  handle_worker_exit "$pid" "$exit_code"
211
211
  fi
@@ -187,7 +187,8 @@ eval_exit_code=0
187
187
 
188
188
  if [[ -n $timeout_seconds ]]; then
189
189
  echo "[WORKER-$$] Evaluation timeout: ${timeout_seconds}s"
190
- if eval_output=$(timeout "$timeout_seconds" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file" 2>&1); then
190
+ # For Modal compatibility, don't capture stderr
191
+ if eval_output=$(timeout "$timeout_seconds" "$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"); then
191
192
  eval_exit_code=0
192
193
  else
193
194
  eval_exit_code=$?
@@ -198,7 +199,8 @@ if [[ -n $timeout_seconds ]]; then
198
199
  fi
199
200
  fi
200
201
  else
201
- if eval_output=$("$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file" 2>&1); then
202
+ # For Modal compatibility, don't capture stderr
203
+ if eval_output=$("$PYTHON_CMD" "$FULL_EVALUATOR_PATH" "$output_file"); then
202
204
  eval_exit_code=0
203
205
  else
204
206
  eval_exit_code=$?
package/lib/config.sh CHANGED
@@ -58,14 +58,29 @@ load_config() {
58
58
  # Simple YAML parsing for key: value pairs and nested structures
59
59
  local in_ideation_section=false
60
60
  local in_parallel_section=false
61
- while IFS=': ' read -r key value; do
61
+ while IFS='' read -r line; do
62
62
  # Skip comments and empty lines
63
- [[ $key =~ ^[[:space:]]*# ]] || [[ -z $key ]] && continue
63
+ [[ $line =~ ^[[:space:]]*# ]] || [[ -z $line ]] && continue
64
+
65
+ # Parse key:value from line
66
+ if [[ ! $line =~ ^([^:]+):(.*)$ ]]; then
67
+ continue
68
+ fi
69
+ key="${BASH_REMATCH[1]}"
70
+ value="${BASH_REMATCH[2]}"
71
+
72
+ # Check if key is indented (for nested sections)
73
+ local is_indented=false
74
+ [[ $key =~ ^[[:space:]]+ ]] && is_indented=true
75
+
64
76
 
65
77
  # Remove leading/trailing whitespace
66
78
  key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
67
79
  value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
68
80
 
81
+ # Remove inline comments from value
82
+ value=$(echo "$value" | sed 's/[[:space:]]*#.*$//')
83
+
69
84
  # Remove quotes from value
70
85
  value=$(echo "$value" | sed 's/^"//;s/"$//')
71
86
 
@@ -78,8 +93,8 @@ load_config() {
78
93
  in_parallel_section=true
79
94
  in_ideation_section=false
80
95
  continue
81
- elif [[ $key =~ ^[a-z_]+ ]] && [[ $in_ideation_section == true || $in_parallel_section == true ]]; then
82
- # Top-level key found, exit nested sections
96
+ elif [[ $is_indented == false ]] && [[ $in_ideation_section == true || $in_parallel_section == true ]]; then
97
+ # Non-indented key found while in a section, exit nested sections
83
98
  in_ideation_section=false
84
99
  in_parallel_section=false
85
100
  fi
package/lib/csv-lock.sh CHANGED
@@ -135,14 +135,18 @@ find_next_pending_with_lock() {
135
135
 
136
136
  # Find oldest pending candidate and update to running
137
137
  local candidate=$(awk -F',' '
138
- NR>1 && $5 == "pending" { print $1; exit }
138
+ NR>1 && ($5 == "pending" || $5 == "") { print $1; exit }
139
139
  ' "$csv_file")
140
140
 
141
141
  if [ -n "$candidate" ]; then
142
142
  # Update status to running while we have the lock
143
143
  awk -F',' -v OFS=',' -v id="$candidate" '
144
144
  NR==1 || $1 != id { print }
145
- $1 == id { $5 = "running"; print }
145
+ $1 == id {
146
+ # Preserve existing fields but set status to running
147
+ if ($5 == "" || $5 == "pending") $5 = "running"
148
+ print
149
+ }
146
150
  ' "$csv_file" > "${csv_file}.tmp" && mv -f "${csv_file}.tmp" "$csv_file"
147
151
  fi
148
152
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.2.14",
3
+ "version": "1.3.1",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",