claude-evolve 1.3.12 → 1.3.13

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.
package/README.md CHANGED
@@ -172,7 +172,11 @@ Evolution experiments can fail for various reasons. The system tracks these fail
172
172
  ### Required
173
173
  - Node.js >= 14.0.0
174
174
  - Python 3.x (for algorithm execution)
175
- - Unix-like environment (macOS, Linux)
175
+ - Automatically detected on all platforms
176
+ - Windows: Uses `python` if it's Python 3
177
+ - macOS/Linux: Prefers `python3`
178
+ - Can override in config.yaml: `python_cmd: "C:\\Python39\\python.exe"`
179
+ - Bash shell (Git Bash on Windows, native on macOS/Linux)
176
180
  - [Claude CLI](https://docs.anthropic.com/en/docs/claude-code) (`claude` command)
177
181
 
178
182
  ### Optional (but recommended)
@@ -92,35 +92,69 @@ top_score=""
92
92
  top_id=""
93
93
  top_desc=""
94
94
 
95
- while IFS=, read -r id _ desc perf status; do
96
- [[ $id == "id" ]] && continue # Skip header
97
-
98
- ((total++))
99
-
100
- case "$status" in
101
- "complete" | "completed")
102
- ((completed++))
103
- # Only count performance for completed runs with non-zero values
104
- if [[ -n $perf && $perf != "" ]]; then
105
- # Skip zeros (they're errors)
106
- if (( $(echo "$perf > 0" | bc -l 2>/dev/null || echo "0") )); then
107
- total_performance=$(echo "$total_performance + $perf" | bc -l 2>/dev/null || echo "$total_performance")
108
- ((count_with_performance++))
109
-
110
- # Check if this is the top performer
111
- if [[ -z $top_score ]] || (($(echo "$perf > $top_score" | bc -l 2>/dev/null || echo "0"))); then
112
- top_score="$perf"
113
- top_id="$id"
114
- top_desc="$desc"
115
- fi
116
- fi
117
- fi
118
- ;;
119
- "running") ((running++)) ;;
120
- "failed" | "timeout" | "interrupted") ((failed++)) ;;
121
- *) ((pending++)) ;;
122
- esac
123
- done <"$csv_file"
95
+ # Use Python to parse CSV and generate stats
96
+ eval "$("$PYTHON_CMD" -c "
97
+ import csv
98
+
99
+ # Initialize counters
100
+ total = 0
101
+ completed = 0
102
+ running = 0
103
+ failed = 0
104
+ pending = 0
105
+ total_performance = 0
106
+ count_with_performance = 0
107
+ top_score = None
108
+ top_id = ''
109
+ top_desc = ''
110
+
111
+ with open('$csv_file', 'r') as f:
112
+ reader = csv.reader(f)
113
+ next(reader) # Skip header
114
+
115
+ for row in reader:
116
+ if len(row) < 5:
117
+ continue
118
+
119
+ id, _, desc, perf, status = row[:5]
120
+ total += 1
121
+
122
+ if status in ['complete', 'completed']:
123
+ completed += 1
124
+ if perf and perf != '':
125
+ try:
126
+ perf_val = float(perf)
127
+ if perf_val > 0: # Skip zeros (they're errors)
128
+ total_performance += perf_val
129
+ count_with_performance += 1
130
+
131
+ if top_score is None or perf_val > top_score:
132
+ top_score = perf_val
133
+ top_id = id
134
+ top_desc = desc
135
+ except ValueError:
136
+ pass
137
+ elif status == 'running':
138
+ running += 1
139
+ elif status in ['failed', 'timeout', 'interrupted']:
140
+ failed += 1
141
+ else:
142
+ pending += 1
143
+
144
+ # Output shell variable assignments
145
+ print(f'total={total}')
146
+ print(f'completed={completed}')
147
+ print(f'running={running}')
148
+ print(f'failed={failed}')
149
+ print(f'pending={pending}')
150
+ print(f'total_performance={total_performance}')
151
+ print(f'count_with_performance={count_with_performance}')
152
+ print(f'top_score={top_score if top_score is not None else \"\"}')
153
+ print(f'top_id=\"{top_id}\"')
154
+ # Escape special characters in description
155
+ desc_escaped = top_desc.replace('\\\\', '\\\\\\\\').replace('\"', '\\\\\"').replace('\$', '\\\\\$').replace('\`', '\\\\\`')
156
+ print(f'top_desc=\"{desc_escaped}\"')
157
+ ")"
124
158
 
125
159
  # Display summary
126
160
  echo "Total Candidates: $total"
@@ -154,30 +188,44 @@ echo "=== Generation Analysis ==="
154
188
  gen_stats_file="/tmp/evolution_gen_stats_$$.tmp"
155
189
  >"$gen_stats_file"
156
190
 
157
- while IFS=, read -r id _ desc perf status; do
158
- [[ $id == "id" ]] && continue # Skip header
159
-
160
- # Extract generation from ID
161
- gen="gen01" # default for old numeric IDs
162
- if [[ $id =~ ^(gen[0-9]+)- ]]; then
163
- gen="${BASH_REMATCH[1]}"
164
- elif [[ $id =~ ^[0-9]+$ ]]; then
165
- gen="gen00" # Mark old numeric IDs as gen00
166
- fi
167
-
168
- # Write generation data to temp file
169
- echo -n "$gen " >> "$gen_stats_file"
170
- if [[ $status =~ ^(complete|completed)$ && -n $perf && $perf != "" ]]; then
171
- # Exclude zeros from statistics (they're errors)
172
- if (( $(echo "$perf > 0" | bc -l 2>/dev/null || echo "0") )); then
173
- echo "completed $perf" >> "$gen_stats_file"
174
- else
175
- echo "error" >> "$gen_stats_file"
176
- fi
177
- else
178
- echo "incomplete" >> "$gen_stats_file"
179
- fi
180
- done <"$csv_file"
191
+ # Use Python to write generation stats
192
+ "$PYTHON_CMD" -c "
193
+ import csv
194
+ import re
195
+
196
+ with open('$csv_file', 'r') as f:
197
+ reader = csv.reader(f)
198
+ next(reader) # Skip header
199
+
200
+ with open('$gen_stats_file', 'w') as out:
201
+ for row in reader:
202
+ if len(row) < 5:
203
+ continue
204
+
205
+ id, _, desc, perf, status = row[:5]
206
+
207
+ # Extract generation from ID
208
+ gen = 'gen01' # default for old numeric IDs
209
+ match = re.match(r'^(gen[0-9]+)-', id)
210
+ if match:
211
+ gen = match.group(1)
212
+ elif re.match(r'^[0-9]+$', id):
213
+ gen = 'gen00' # Mark old numeric IDs as gen00
214
+
215
+ # Write generation data
216
+ out.write(gen + ' ')
217
+ if status in ['complete', 'completed'] and perf and perf != '':
218
+ try:
219
+ perf_val = float(perf)
220
+ if perf_val > 0:
221
+ out.write(f'completed {perf}\\n')
222
+ else:
223
+ out.write('error\\n')
224
+ except ValueError:
225
+ out.write('error\\n')
226
+ else:
227
+ out.write('incomplete\\n')
228
+ "
181
229
 
182
230
  # Process generation stats
183
231
  for gen in $(cut -d' ' -f1 "$gen_stats_file" | sort -u || echo ""); do
@@ -206,14 +254,30 @@ rm -f "$gen_stats_file"
206
254
 
207
255
  # Count valid performance entries for chart (excluding zeros)
208
256
  valid_performance_count=0
209
- while IFS=, read -r id _ desc perf status; do
210
- [[ $id == "id" ]] && continue # Skip header
211
- if [[ $status =~ ^(complete|completed)$ && -n $perf && $perf != "" ]]; then
212
- if (( $(echo "$perf > 0" | bc -l 2>/dev/null || echo "0") )); then
213
- ((valid_performance_count++))
214
- fi
215
- fi
216
- done <"$csv_file"
257
+ # Count valid performance entries using Python
258
+ valid_performance_count=$("$PYTHON_CMD" -c "
259
+ import csv
260
+
261
+ count = 0
262
+ with open('$csv_file', 'r') as f:
263
+ reader = csv.reader(f)
264
+ next(reader) # Skip header
265
+
266
+ for row in reader:
267
+ if len(row) < 5:
268
+ continue
269
+ status = row[4]
270
+ perf = row[3]
271
+
272
+ if status in ['complete', 'completed'] and perf and perf != '':
273
+ try:
274
+ if float(perf) > 0:
275
+ count += 1
276
+ except ValueError:
277
+ pass
278
+
279
+ print(count)
280
+ ")
217
281
 
218
282
  # Simple chart generation using gnuplot if available
219
283
  if command -v gnuplot >/dev/null 2>&1 && [[ $valid_performance_count -gt 0 ]]; then
@@ -250,40 +314,75 @@ if command -v gnuplot >/dev/null 2>&1 && [[ $valid_performance_count -gt 0 ]]; t
250
314
  max_row=0
251
315
  max_id=""
252
316
 
253
- while IFS=, read -r id _ desc perf status; do
254
- [[ $id == "id" ]] && continue # Skip header
255
- ((row_num++))
317
+ # Use Python to generate chart data
318
+ "$PYTHON_CMD" -c "
319
+ import csv
320
+ import re
321
+
322
+ row_num = 0
323
+ max_perf = 0
324
+ max_row = 0
325
+ max_id = ''
326
+
327
+ with open('$csv_file', 'r') as f:
328
+ reader = csv.reader(f)
329
+ next(reader) # Skip header
256
330
 
257
- # Extract generation from ID
258
- gen="gen01" # default
259
- if [[ $id =~ ^(gen[0-9]+)- ]]; then
260
- gen="${BASH_REMATCH[1]}"
261
- fi
331
+ data_lines = []
332
+ gen_temp_lines = []
262
333
 
263
- # Only include completed algorithms with non-zero performance
264
- if [[ -n $perf && $perf != "" && $status =~ ^(complete|completed)$ ]]; then
265
- # Skip zero values (they're errors)
266
- if (( $(echo "$perf > 0" | bc -l) )); then
267
- # Assign generation number for coloring (1-based)
268
- gen_num=1
269
- if [[ $id =~ ^gen([0-9]+)- ]]; then
270
- gen_num=$((10#${BASH_REMATCH[1]}))
271
- fi
272
-
273
- echo "$row_num \"$id\" $perf $gen_num" >>"$data_file"
334
+ for row in reader:
335
+ if len(row) < 5:
336
+ continue
337
+
338
+ row_num += 1
339
+ id, _, desc, perf, status = row[:5]
274
340
 
275
- # Track for generation averages
276
- echo "$gen $perf" >>"$gen_data_temp"
341
+ # Extract generation from ID
342
+ gen = 'gen01' # default
343
+ match = re.match(r'^(gen[0-9]+)-', id)
344
+ if match:
345
+ gen = match.group(1)
277
346
 
278
- # Track the winner
279
- if (( $(echo "$perf > $max_perf" | bc -l) )); then
280
- max_perf=$perf
281
- max_row=$row_num
282
- max_id=$id
283
- fi
284
- fi
285
- fi
286
- done <"$csv_file"
347
+ # Only include completed algorithms with non-zero performance
348
+ if perf and perf != '' and status in ['complete', 'completed']:
349
+ try:
350
+ perf_val = float(perf)
351
+ if perf_val > 0:
352
+ # Assign generation number for coloring (1-based)
353
+ gen_num = 1
354
+ match = re.match(r'^gen([0-9]+)-', id)
355
+ if match:
356
+ gen_num = int(match.group(1))
357
+
358
+ data_lines.append(f'{row_num} \"{id}\" {perf} {gen_num}')
359
+ gen_temp_lines.append(f'{gen} {perf}')
360
+
361
+ # Track the winner
362
+ if perf_val > max_perf:
363
+ max_perf = perf_val
364
+ max_row = row_num
365
+ max_id = id
366
+ except ValueError:
367
+ pass
368
+
369
+ # Write data file
370
+ with open('$data_file', 'a') as f:
371
+ for line in data_lines:
372
+ f.write(line + '\\n')
373
+
374
+ # Write gen temp file
375
+ with open('$gen_data_temp', 'a') as f:
376
+ for line in gen_temp_lines:
377
+ f.write(line + '\\n')
378
+
379
+ # Output max values for shell
380
+ print(f'max_perf={max_perf}')
381
+ print(f'max_row={max_row}')
382
+ print(f'max_id=\"{max_id}\"')
383
+ " | while read -r line; do
384
+ eval "$line"
385
+ done
287
386
 
288
387
  # Create generation averages file and track max generation
289
388
  gen_index=1
package/lib/config.sh CHANGED
@@ -9,7 +9,25 @@ DEFAULT_BRIEF_FILE="BRIEF.md"
9
9
  DEFAULT_EVOLUTION_CSV="evolution.csv"
10
10
  DEFAULT_OUTPUT_DIR=""
11
11
  DEFAULT_PARENT_SELECTION="best"
12
- DEFAULT_PYTHON_CMD="python3"
12
+ # Detect Python command based on platform
13
+ detect_python_cmd() {
14
+ # Try python3 first (macOS, Linux)
15
+ if command -v python3 >/dev/null 2>&1; then
16
+ echo "python3"
17
+ # Try python (Windows, some Linux)
18
+ elif command -v python >/dev/null 2>&1; then
19
+ # Verify it's Python 3
20
+ if python -c "import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)" 2>/dev/null; then
21
+ echo "python"
22
+ else
23
+ echo "python3" # Fallback
24
+ fi
25
+ else
26
+ echo "python3" # Default fallback
27
+ fi
28
+ }
29
+
30
+ DEFAULT_PYTHON_CMD="$(detect_python_cmd)"
13
31
 
14
32
  # Default ideation strategy values
15
33
  DEFAULT_TOTAL_IDEAS=15
@@ -195,7 +213,16 @@ validate_config() {
195
213
 
196
214
  if ! command -v "$PYTHON_CMD" >/dev/null 2>&1; then
197
215
  echo "[ERROR] Python command not found: $PYTHON_CMD" >&2
216
+ echo "[ERROR] Please install Python 3.x or set python_cmd in config.yaml" >&2
217
+ echo "[ERROR] Examples: python_cmd: \"python\" or python_cmd: \"C:\\Python39\\python.exe\"" >&2
198
218
  ((errors++))
219
+ else
220
+ # Verify Python version is 3.x
221
+ if ! "$PYTHON_CMD" -c "import sys; sys.exit(0 if sys.version_info[0] >= 3 else 1)" 2>/dev/null; then
222
+ echo "[ERROR] Python 3.x required, but $PYTHON_CMD appears to be Python 2" >&2
223
+ echo "[ERROR] Please set python_cmd in config.yaml to point to Python 3" >&2
224
+ ((errors++))
225
+ fi
199
226
  fi
200
227
 
201
228
  return $errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.3.12",
3
+ "version": "1.3.13",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",