claude-evolve 1.5.1 → 1.5.2

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.
@@ -6,6 +6,10 @@ set -e
6
6
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
7
  # shellcheck source=../lib/config.sh
8
8
  source "$SCRIPT_DIR/../lib/config.sh"
9
+ # shellcheck source=../lib/csv-lock.sh
10
+ source "$SCRIPT_DIR/../lib/csv-lock.sh"
11
+ # shellcheck source=../lib/ai-cli.sh
12
+ source "$SCRIPT_DIR/../lib/ai-cli.sh"
9
13
 
10
14
  # Use CLAUDE_EVOLVE_CONFIG if set, otherwise default
11
15
  if [[ -n ${CLAUDE_EVOLVE_CONFIG:-} ]]; then
@@ -14,154 +18,57 @@ else
14
18
  load_config
15
19
  fi
16
20
 
17
- # Function to determine which model to use based on generation
18
- get_model_for_generation() {
19
- local generation="$1"
20
- local gen_num
21
-
22
- # Extract numeric part of generation (e.g., "05" from gen05)
23
- if [[ $generation =~ ^0*([0-9]+)$ ]]; then
24
- gen_num=$((10#${BASH_REMATCH[1]}))
25
- else
26
- gen_num=1 # Default for malformed input
27
- fi
28
-
29
- # Check which AI tools are available
30
- local has_o3=false
31
- local has_gemini=false
32
-
33
- if command -v codex >/dev/null 2>&1; then
34
- has_o3=true
35
- fi
36
-
37
- if command -v gemini >/dev/null 2>&1; then
38
- has_gemini=true
39
- fi
40
-
41
- # Determine rotation based on what's available
42
- if [[ "$has_o3" == "true" && "$has_gemini" == "true" ]]; then
43
- # All three available: opus -> o3 -> gemini rotation
44
- case $((gen_num % 3)) in
45
- 1) echo "opus" ;; # 1, 4, 7, 10...
46
- 2) echo "o3" ;; # 2, 5, 8, 11...
47
- 0) echo "gemini" ;; # 3, 6, 9, 12...
48
- esac
49
- elif [[ "$has_o3" == "true" ]]; then
50
- # Only opus and o3: alternate between them
51
- if (( gen_num % 2 == 1 )); then
52
- echo "opus" # Odd generations
53
- else
54
- echo "o3" # Even generations
55
- fi
56
- elif [[ "$has_gemini" == "true" ]]; then
57
- # Only opus and gemini: alternate between them
58
- if (( gen_num % 2 == 1 )); then
59
- echo "opus" # Odd generations
60
- else
61
- echo "gemini" # Even generations
62
- fi
63
- else
64
- # Only opus available
65
- echo "opus"
66
- fi
67
- }
68
-
69
- # Helper function to call AI model (alternating based on generation)
21
+ # Helper function to call AI with limit check
70
22
  call_ai_with_limit_check() {
71
23
  local prompt="$1"
72
24
  local generation="${2:-01}" # Default to generation 01 if not provided
73
25
 
74
- # Determine which model to use for this generation
75
- local preferred_model
76
- preferred_model=$(get_model_for_generation "$generation")
77
-
78
- echo "[INFO] Generation $generation: Using $preferred_model" >&2
79
-
80
- # Try preferred model first
81
- if [[ "$preferred_model" == "o3" ]] && command -v codex >/dev/null 2>&1; then
82
- echo "[INFO] Using codex o3 for ideation" >&2
83
-
84
- # Call codex with o3 model using exec subcommand
85
- local ai_output
86
- # Pass prompt as argument, not via stdin
87
- ai_output=$(timeout 300 codex exec -m o3 --dangerously-bypass-approvals-and-sandbox "$prompt" 2>&1)
88
- local ai_exit_code=$?
89
-
90
- if [[ $ai_exit_code -eq 0 ]]; then
91
- # For ideation, AI modifies files directly - just return success
92
- echo "[INFO] Codex o3 succeeded" >&2
93
- return 0
94
- else
95
- echo "[WARN] Codex o3 failed with exit code $ai_exit_code, falling back to Claude Opus" >&2
96
- preferred_model="opus"
97
- fi
98
- elif [[ "$preferred_model" == "gemini" ]] && command -v gemini >/dev/null 2>&1; then
99
- echo "[INFO] Using gemini 2.5 pro for ideation" >&2
100
-
101
- # Call gemini with -y and -p flags
102
- local ai_output
103
- ai_output=$(echo "$prompt" | timeout 300 gemini -y -p 2>&1)
104
- local ai_exit_code=$?
105
-
106
- if [[ $ai_exit_code -eq 0 ]]; then
107
- # For ideation, AI modifies files directly - just return success
108
- echo "[INFO] Gemini succeeded" >&2
109
- return 0
110
- else
111
- echo "[WARN] Gemini failed with exit code $ai_exit_code, falling back to Claude Opus" >&2
112
- preferred_model="opus"
113
- fi
26
+ # Calculate hash value for round-robin based on generation
27
+ local gen_num
28
+ if [[ $generation =~ ^0*([0-9]+)$ ]]; then
29
+ gen_num=$((10#${BASH_REMATCH[1]}))
30
+ else
31
+ gen_num=1
114
32
  fi
115
33
 
116
- # Use Claude with preferred model (or fallback)
117
- echo "[INFO] Using Claude $preferred_model for ideation" >&2
34
+ # Use centralized AI library for ideation
35
+ local ai_output
36
+ ai_output=$(call_ai_with_round_robin "$prompt" "ideate" "$gen_num")
37
+ local ai_exit_code=$?
118
38
 
119
- # Call Claude and capture output
120
- local claude_output
121
- claude_output=$(echo "$prompt" | timeout 300 claude --dangerously-skip-permissions --model "$preferred_model" -p 2>&1)
122
- local claude_exit_code=$?
123
-
124
- # Check for usage limit
125
- if echo "$claude_output" | grep -q "Claude AI usage limit reached"; then
126
- # Extract timestamp if available
127
- local limit_timestamp=$(echo "$claude_output" | grep -o "Claude AI usage limit reached|[0-9]*" | cut -d'|' -f2)
128
-
129
- # Print red error message
130
- echo -e "\033[31m[ERROR] CLAUDE AI USAGE LIMIT REACHED!\033[0m" >&2
39
+ # Handle special exit codes
40
+ if [[ $ai_exit_code -eq 3 ]]; then
41
+ # All models hit usage limits
42
+ echo -e "\033[31m[ERROR] ALL AI MODELS HIT USAGE LIMITS!\033[0m" >&2
131
43
  echo -e "\033[31m[ERROR] Ideation halted due to API rate limits.\033[0m" >&2
132
-
133
- if [[ -n $limit_timestamp ]]; then
134
- # Convert timestamp to human-readable format
135
- local limit_date=$(date -r "$limit_timestamp" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "Unknown time")
136
- echo -e "\033[31m[ERROR] Limit will be released at: $limit_date\033[0m" >&2
137
- fi
138
-
139
- echo -e "\033[33m[INFO] Please wait for the rate limit to reset before continuing.\033[0m" >&2
140
- echo -e "\033[33m[INFO] No ideas were generated. Run ideate again when the limit resets.\033[0m" >&2
141
-
44
+ echo -e "\033[33m[INFO] Please wait for the rate limits to reset before continuing.\033[0m" >&2
45
+ echo -e "\033[33m[INFO] No ideas were generated. Run ideate again when the limits reset.\033[0m" >&2
142
46
  exit 1
143
47
  fi
144
48
 
145
- if [[ $claude_exit_code -eq 0 ]]; then
49
+ if [[ $ai_exit_code -eq 0 ]]; then
146
50
  # For ideation, AI modifies files directly - just return success
147
- echo "[INFO] Claude $preferred_model succeeded" >&2
51
+ echo "[INFO] AI succeeded" >&2
148
52
  return 0
149
53
  else
150
- return $claude_exit_code
54
+ return $ai_exit_code
151
55
  fi
152
56
  }
153
57
 
58
+
154
59
  # Backward compatibility alias
155
60
  call_claude_with_limit_check() {
156
61
  call_ai_with_limit_check "$@"
157
62
  }
158
63
 
159
64
  # Robust AI calling with fallbacks across all available models
160
- call_ai_with_fallbacks() {
65
+ call_ai_for_ideation() {
161
66
  local prompt="$1"
162
67
  local generation="${2:-01}"
68
+ local expected_count="${3:-1}" # Number of ideas expected to be added
69
+ local temp_csv_file="${4:-temp-csv-$$.csv}" # Optional temp CSV filename
163
70
 
164
- # Determine which model to use based on generation (round-robin)
71
+ # Calculate hash value for round-robin based on generation
165
72
  local gen_num
166
73
  if [[ $generation =~ ^0*([0-9]+)$ ]]; then
167
74
  gen_num=$((10#${BASH_REMATCH[1]}))
@@ -169,81 +76,47 @@ call_ai_with_fallbacks() {
169
76
  gen_num=1
170
77
  fi
171
78
 
172
- # Check which AI tools are available
173
- local available_models=()
174
- if command -v codex >/dev/null 2>&1; then
175
- available_models+=("o3")
176
- fi
177
- if command -v gemini >/dev/null 2>&1; then
178
- available_models+=("gemini")
79
+ # Get the current row count before any modifications
80
+ local original_csv_count
81
+ if [[ -f "$temp_csv_file" ]]; then
82
+ original_csv_count=$(grep -v '^[[:space:]]*$' "$temp_csv_file" | tail -n +2 | wc -l)
83
+ else
84
+ original_csv_count=0
179
85
  fi
180
- available_models+=("opus") # Claude Opus always available
181
-
182
- # Create ordered list based on round-robin for this generation
183
- local num_models=${#available_models[@]}
184
- local start_index=$((gen_num % num_models))
185
- local models=()
186
86
 
187
- # Add models in round-robin order starting from the calculated index
188
- for ((i=0; i<num_models; i++)); do
189
- local idx=$(((start_index + i) % num_models))
190
- models+=("${available_models[$idx]}")
191
- done
87
+ # Use centralized AI library
88
+ local ai_output
89
+ ai_output=$(call_ai_with_round_robin "$prompt" "ideate" "$gen_num")
90
+ local ai_exit_code=$?
192
91
 
193
- echo "[INFO] Model order for generation $generation (round-robin): ${models[*]}" >&2
92
+ # Handle special exit codes
93
+ # No special handling for exit codes anymore
194
94
 
195
- # Try each model in the ordered sequence
196
- for model in "${models[@]}"; do
197
- echo "[INFO] Trying $model for ideation" >&2
198
-
199
- local ai_output
200
- local ai_exit_code
201
-
202
- if [[ "$model" == "o3" ]] && command -v codex >/dev/null 2>&1; then
203
- # Pass prompt as argument, not via stdin
204
- ai_output=$(timeout 300 codex exec -m o3 --dangerously-bypass-approvals-and-sandbox "$prompt" 2>&1)
205
- ai_exit_code=$?
95
+ if [[ $ai_exit_code -eq 0 ]]; then
96
+ # For ideation, we need to verify the CSV file was actually modified
97
+ if [[ -f "$temp_csv_file" ]]; then
98
+ local new_csv_count
99
+ new_csv_count=$(grep -v '^[[:space:]]*$' "$temp_csv_file" | tail -n +2 | wc -l)
206
100
 
207
- if [[ $ai_exit_code -eq 0 ]]; then
208
- # For ideation, we don't care about output content - AI modifies files directly
209
- echo "[INFO] o3 completed successfully (exit code 0)" >&2
101
+ if [[ $new_csv_count -gt $original_csv_count ]]; then
102
+ echo "[INFO] AI completed successfully and modified CSV ($new_csv_count vs $original_csv_count rows)" >&2
210
103
  return 0
104
+ else
105
+ echo "[INFO] $model returned exit code 0 but didn't modify CSV file" >&2
106
+ echo "[DEBUG] Expected file: $temp_csv_file" >&2
107
+ echo "[DEBUG] Original count: $original_csv_count, New count: $new_csv_count" >&2
108
+ return 1
211
109
  fi
212
-
213
- elif [[ "$model" == "gemini" ]] && command -v gemini >/dev/null 2>&1; then
214
- ai_output=$(echo "$prompt" | timeout 300 gemini -y -p 2>&1)
215
- ai_exit_code=$?
216
-
217
- if [[ $ai_exit_code -eq 0 ]]; then
218
- # For ideation, we don't care about output content - AI modifies files directly
219
- echo "[INFO] gemini completed successfully (exit code 0)" >&2
220
- return 0
221
- fi
222
-
223
110
  else
224
- # Use Claude with the specified model
225
- ai_output=$(echo "$prompt" | claude --dangerously-skip-permissions --model "$model" -p 2>&1)
226
- ai_exit_code=$?
227
-
228
- if [[ $ai_exit_code -eq 0 ]]; then
229
- # Check for usage limits
230
- if echo "$ai_output" | grep -q "Claude AI usage limit reached"; then
231
- echo "[INFO] Claude hit usage limit" >&2
232
- else
233
- # For ideation, we don't care about output content - AI modifies files directly
234
- echo "[INFO] $model completed successfully (exit code 0)" >&2
235
- return 0
236
- fi
237
- fi
111
+ echo "[INFO] Exit code 0 but temp CSV file not found: $temp_csv_file" >&2
112
+ echo "[DEBUG] Current directory: $(pwd)" >&2
113
+ echo "[DEBUG] Files matching temp-csv-*.csv:" >&2
114
+ ls -la temp-csv-*.csv 2>&1 >&2
115
+ return 1
238
116
  fi
239
-
240
- echo "[WARN] $model failed or returned unusable output, trying next model..." >&2
241
- echo "[DEBUG] $model exit code: ${ai_exit_code:-unknown}" >&2
242
- echo "[DEBUG] $model output length: ${#ai_output} chars" >&2
243
- echo "[DEBUG] $model output preview: $(echo "$ai_output" | head -3 | tr '\n' ' ')" >&2
244
- done
117
+ fi
245
118
 
246
- echo "[ERROR] All AI models failed to generate usable output" >&2
119
+ echo "[INFO] No AI model successfully modified the CSV file" >&2
247
120
  return 1
248
121
  }
249
122
 
@@ -313,16 +186,15 @@ if [[ $use_strategies == true ]]; then
313
186
  fi
314
187
  fi
315
188
 
316
- # Get next generation number
189
+ # Get next generation number that doesn't have existing Python files
317
190
  get_next_generation() {
318
- if [[ ! -f "$FULL_CSV_PATH" ]]; then
319
- echo "01"
320
- return
321
- fi
191
+ # Start with generation 1 if no CSV exists
192
+ local start_gen=1
322
193
 
323
- # Use Python for proper CSV parsing
324
- local max_gen
325
- max_gen=$("$PYTHON_CMD" -c "
194
+ if [[ -f "$FULL_CSV_PATH" ]]; then
195
+ # Use Python for proper CSV parsing to find max generation
196
+ local max_gen
197
+ max_gen=$("$PYTHON_CMD" -c "
326
198
  import csv
327
199
  max_gen = 0
328
200
  with open('$FULL_CSV_PATH', 'r') as f:
@@ -340,9 +212,36 @@ with open('$FULL_CSV_PATH', 'r') as f:
340
212
  pass
341
213
  print(max_gen)
342
214
  ")
215
+ # Start checking from the next generation after max
216
+ start_gen=$((max_gen + 1))
217
+ fi
343
218
 
344
- # Increment and format with leading zero
345
- printf "%02d" $((max_gen + 1))
219
+ # Keep incrementing until we find a generation with no Python files
220
+ local candidate_gen=$start_gen
221
+ while true; do
222
+ local gen_formatted=$(printf "%02d" $candidate_gen)
223
+
224
+ # Check if any Python files exist for this generation
225
+ local py_files_exist=false
226
+ if ls "$FULL_OUTPUT_DIR"/evolution_gen${gen_formatted}-*.py >/dev/null 2>&1; then
227
+ py_files_exist=true
228
+ fi
229
+
230
+ if [[ "$py_files_exist" == "false" ]]; then
231
+ # This generation is safe to use
232
+ echo "$gen_formatted"
233
+ return
234
+ else
235
+ echo "[WARN] Generation $gen_formatted already has Python files, skipping to next generation" >&2
236
+ candidate_gen=$((candidate_gen + 1))
237
+
238
+ # Safety check to prevent infinite loop
239
+ if [[ $candidate_gen -gt 999 ]]; then
240
+ echo "[ERROR] Could not find a safe generation number (checked up to 999)" >&2
241
+ exit 1
242
+ fi
243
+ fi
244
+ done
346
245
  }
347
246
 
348
247
  # This function is no longer used with direct CSV modification approach
@@ -377,31 +276,64 @@ validate_direct_csv_modification() {
377
276
  return 1
378
277
  fi
379
278
 
380
- # Validate the modified CSV has more entries than original
381
- # Count actual data rows (excluding header and empty lines)
382
- local original_count
383
- original_count=$(grep -v '^[[:space:]]*$' "$FULL_CSV_PATH" | tail -n +2 | wc -l)
279
+ # Get the count before modification from the temp CSV (which was copied from original before AI ran)
280
+ # We need to track this before the AI runs by reading from the beginning state
281
+ # First, get a fresh count from the current main CSV (which reflects any previous operations in this session)
282
+ local current_original_count
283
+ current_original_count=$(grep -v '^[[:space:]]*$' "$FULL_CSV_PATH" | tail -n +2 | wc -l)
284
+
285
+ # Count data rows in the modified temp CSV
384
286
  local new_count
385
287
  new_count=$(grep -v '^[[:space:]]*$' "$temp_csv" | tail -n +2 | wc -l)
386
288
 
387
- echo "[DEBUG] Original CSV data rows: $original_count" >&2
388
- echo "[DEBUG] Modified CSV data rows: $new_count" >&2
289
+ echo "[DEBUG] Current main CSV data rows: $current_original_count" >&2
290
+ echo "[DEBUG] Modified temp CSV data rows: $new_count" >&2
389
291
  echo "[DEBUG] Expected to add: $expected_count ideas" >&2
390
292
 
391
- if [[ $new_count -le $original_count ]]; then
392
- echo "[ERROR] CSV file wasn't modified - same number of data rows ($new_count <= $original_count)" >&2
293
+ # Check if AI overwrote the file instead of appending
294
+ if [[ $new_count -lt $current_original_count ]]; then
295
+ echo "[ERROR] AI overwrote the CSV file instead of appending ($new_count < $current_original_count)" >&2
393
296
  echo "[DEBUG] First 10 lines of CSV after AI attempt:" >&2
394
297
  head -10 "$temp_csv" >&2
395
298
  return 1
396
299
  fi
397
300
 
398
- local added_count=$((new_count - original_count))
301
+ # Check if no changes were made
302
+ if [[ $new_count -eq $current_original_count ]]; then
303
+ echo "[ERROR] CSV file wasn't modified - same number of data rows ($new_count = $current_original_count)" >&2
304
+ echo "[DEBUG] First 10 lines of CSV after AI attempt:" >&2
305
+ head -10 "$temp_csv" >&2
306
+ return 1
307
+ fi
308
+
309
+ local added_count=$((new_count - current_original_count))
399
310
  if [[ $added_count -ne $expected_count ]]; then
400
311
  echo "[WARN] Expected to add $expected_count ideas but added $added_count" >&2
401
312
  fi
402
313
 
403
- # Replace original CSV with modified version
404
- mv "$temp_csv" "$FULL_CSV_PATH"
314
+ # Use proper locking to safely update the CSV
315
+ echo "[INFO] Acquiring CSV lock to apply changes..."
316
+
317
+ # Set the lockfile path
318
+ CSV_LOCKFILE="$FULL_EVOLUTION_DIR/.evolution.csv.lock"
319
+
320
+ if ! acquire_csv_lock; then
321
+ echo "[ERROR] Failed to acquire CSV lock for update" >&2
322
+ rm -f "$temp_csv"
323
+ return 1
324
+ fi
325
+
326
+ # Get just the new entries (skip header and existing entries)
327
+ local original_line_count=$(wc -l < "$FULL_CSV_PATH")
328
+
329
+ # Append only the new lines from temp CSV to the main CSV
330
+ tail -n +$((original_line_count + 1)) "$temp_csv" >> "$FULL_CSV_PATH"
331
+
332
+ # Clean up temp file
333
+ rm -f "$temp_csv"
334
+
335
+ # Release the lock
336
+ release_csv_lock
405
337
 
406
338
  echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
407
339
  return 0
@@ -472,8 +404,29 @@ validate_and_apply_csv_modification_old() {
472
404
  echo "[WARN] Expected to add $expected_count ideas but added $added_count" >&2
473
405
  fi
474
406
 
475
- # Replace original CSV with modified version
476
- mv "$temp_csv" "$FULL_CSV_PATH"
407
+ # Use proper locking to safely update the CSV
408
+ echo "[INFO] Acquiring CSV lock to apply changes..."
409
+
410
+ # Set the lockfile path
411
+ CSV_LOCKFILE="$FULL_EVOLUTION_DIR/.evolution.csv.lock"
412
+
413
+ if ! acquire_csv_lock; then
414
+ echo "[ERROR] Failed to acquire CSV lock for update" >&2
415
+ rm -f "$temp_csv"
416
+ return 1
417
+ fi
418
+
419
+ # Get just the new entries (skip header and existing entries)
420
+ local original_line_count=$(wc -l < "$FULL_CSV_PATH")
421
+
422
+ # Append only the new lines from temp CSV to the main CSV
423
+ tail -n +$((original_line_count + 1)) "$temp_csv" >> "$FULL_CSV_PATH"
424
+
425
+ # Clean up temp file
426
+ rm -f "$temp_csv"
427
+
428
+ # Release the lock
429
+ release_csv_lock
477
430
 
478
431
  echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
479
432
  return 0
@@ -518,8 +471,8 @@ IMPORTANT: Output the complete modified CSV file. Do not add any explanation or
518
471
 
519
472
  # Get AI to modify the CSV with fallbacks
520
473
  local modified_csv
521
- local stderr_file="/tmp/claude-evolve-stderr-$$.txt"
522
- if ! modified_csv=$(call_ai_with_fallbacks "$csv_prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
474
+ local stderr_file="$FULL_EVOLUTION_DIR/stderr-$$.txt"
475
+ if ! modified_csv=$(call_ai_for_ideation "$csv_prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
523
476
  echo "[ERROR] All AI models failed to modify CSV" >&2
524
477
  cat "$stderr_file" >&2
525
478
  rm -f "$temp_csv" "$stderr_file"
@@ -597,14 +550,72 @@ IMPORTANT: Output the complete modified CSV file. Do not add any explanation or
597
550
  echo "[WARN] Expected to add $count ideas but added $added_count" >&2
598
551
  fi
599
552
 
600
- # Replace original CSV with modified version
601
- mv "$temp_csv" "$FULL_CSV_PATH"
553
+ # Use proper locking to safely update the CSV
554
+ echo "[INFO] Acquiring CSV lock to apply changes..."
555
+
556
+ # Set the lockfile path
557
+ CSV_LOCKFILE="$FULL_EVOLUTION_DIR/.evolution.csv.lock"
558
+
559
+ if ! acquire_csv_lock; then
560
+ echo "[ERROR] Failed to acquire CSV lock for update" >&2
561
+ rm -f "$temp_csv"
562
+ return 1
563
+ fi
564
+
565
+ # Get just the new entries (skip header and existing entries)
566
+ local original_line_count=$(wc -l < "$FULL_CSV_PATH")
567
+
568
+ # Append only the new lines from temp CSV to the main CSV
569
+ tail -n +$((original_line_count + 1)) "$temp_csv" >> "$FULL_CSV_PATH"
570
+
571
+ # Clean up temp file
572
+ rm -f "$temp_csv"
573
+
574
+ # Release the lock
575
+ release_csv_lock
602
576
 
603
577
  echo "[INFO] Successfully added $added_count $idea_type ideas to CSV"
604
578
 
605
579
  return 0
606
580
  }
607
581
 
582
+ # Get list of existing Python files for a generation
583
+ get_existing_py_files_for_generation() {
584
+ local generation="$1"
585
+ local py_files=""
586
+
587
+ # List all Python files for this generation
588
+ for py_file in "$FULL_OUTPUT_DIR"/evolution_gen${generation}-*.py; do
589
+ if [[ -f "$py_file" ]]; then
590
+ local basename=$(basename "$py_file" .py)
591
+ local id="${basename#evolution_}"
592
+ if [[ -n "$py_files" ]]; then
593
+ py_files="$py_files, $id"
594
+ else
595
+ py_files="$id"
596
+ fi
597
+ fi
598
+ done
599
+
600
+ echo "$py_files"
601
+ }
602
+
603
+ # Add existing Python files warning to prompt
604
+ add_existing_files_warning() {
605
+ local prompt="$1"
606
+ local generation="$2"
607
+ local existing_py_files=$(get_existing_py_files_for_generation "$generation")
608
+
609
+ if [[ -n "$existing_py_files" ]]; then
610
+ prompt+="
611
+
612
+ WARNING: The following IDs already have Python files and MUST NOT be reused: $existing_py_files
613
+ Skip these IDs when assigning new IDs (e.g., if gen$generation-001 and gen$generation-002 exist as Python files, start with gen$generation-003)"
614
+ fi
615
+
616
+ echo "$prompt"
617
+ }
618
+
608
619
  # Get next available ID for current generation
609
620
  get_next_id() {
610
621
  local generation="$1"
@@ -734,10 +745,55 @@ ideate_ai_strategies() {
734
745
  echo " Crossover hybrid: $CROSSOVER_HYBRID"
735
746
 
736
747
  # Generate each type of idea by having Claude directly edit the CSV
737
- [[ $NOVEL_EXPLORATION -gt 0 ]] && generate_novel_ideas_direct "$NOVEL_EXPLORATION"
738
- [[ $HILL_CLIMBING -gt 0 ]] && generate_hill_climbing_direct "$HILL_CLIMBING" "$top_performers"
739
- [[ $STRUCTURAL_MUTATION -gt 0 ]] && generate_structural_mutation_direct "$STRUCTURAL_MUTATION" "$top_performers"
740
- [[ $CROSSOVER_HYBRID -gt 0 ]] && generate_crossover_direct "$CROSSOVER_HYBRID" "$top_performers"
748
+ # Track successes - continue even if some strategies fail
749
+ local strategies_attempted=0
750
+ local strategies_succeeded=0
751
+
752
+ if [[ $NOVEL_EXPLORATION -gt 0 ]]; then
753
+ ((strategies_attempted++))
754
+ if generate_novel_ideas_direct "$NOVEL_EXPLORATION"; then
755
+ ((strategies_succeeded++))
756
+ else
757
+ echo "[WARN] Novel exploration strategy failed, continuing with other strategies" >&2
758
+ fi
759
+ fi
760
+
761
+ if [[ $HILL_CLIMBING -gt 0 ]]; then
762
+ ((strategies_attempted++))
763
+ if generate_hill_climbing_direct "$HILL_CLIMBING" "$top_performers"; then
764
+ ((strategies_succeeded++))
765
+ else
766
+ echo "[WARN] Hill climbing strategy failed, continuing with other strategies" >&2
767
+ fi
768
+ fi
769
+
770
+ if [[ $STRUCTURAL_MUTATION -gt 0 ]]; then
771
+ ((strategies_attempted++))
772
+ if generate_structural_mutation_direct "$STRUCTURAL_MUTATION" "$top_performers"; then
773
+ ((strategies_succeeded++))
774
+ else
775
+ echo "[WARN] Structural mutation strategy failed, continuing with other strategies" >&2
776
+ fi
777
+ fi
778
+
779
+ if [[ $CROSSOVER_HYBRID -gt 0 ]]; then
780
+ ((strategies_attempted++))
781
+ if generate_crossover_direct "$CROSSOVER_HYBRID" "$top_performers"; then
782
+ ((strategies_succeeded++))
783
+ else
784
+ echo "[WARN] Crossover strategy failed, continuing with other strategies" >&2
785
+ fi
786
+ fi
787
+
788
+ echo "[INFO] Strategy results: $strategies_succeeded/$strategies_attempted succeeded" >&2
789
+
790
+ # Success if at least one strategy worked
791
+ if [[ $strategies_succeeded -gt 0 ]]; then
792
+ return 0
793
+ else
794
+ echo "[ERROR] All ideation strategies failed" >&2
795
+ return 1
796
+ fi
741
797
  }
742
798
 
743
799
  # Generate novel exploration ideas using direct CSV modification
@@ -755,33 +811,66 @@ generate_novel_ideas_direct() {
755
811
  # Use relative paths and change to evolution directory so AI can access files
756
812
  local temp_csv_basename=$(basename "$temp_csv")
757
813
 
758
- local prompt="I need you to use your file editing capabilities to add exactly $count novel algorithmic ideas to the CSV file: $temp_csv_basename
814
+ # Get existing Python files for this generation to avoid ID collisions
815
+ local existing_py_files=$(get_existing_py_files_for_generation "$CURRENT_GENERATION")
816
+
817
+ local prompt="I need you to use your file editing capabilities to APPEND exactly $count novel algorithmic ideas to the CSV file: $temp_csv_basename
759
818
 
760
819
  Current evolution context:
761
820
  - Generation: $CURRENT_GENERATION
762
821
  - Algorithm: algorithm.py (base algorithm)
763
- - Brief: $(head -20 "$FULL_BRIEF_PATH")
822
+ - Brief: $(head -5 "$FULL_BRIEF_PATH" 2>/dev/null | head -c 500 || echo "No brief file found")
764
823
 
765
- Instructions:
824
+ CRITICAL INSTRUCTIONS:
766
825
  1. Use the Read tool to examine the current CSV file
767
- 2. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
768
- 3. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
769
- 4. Use the Edit or MultiEdit tool to add exactly $count new rows to the CSV file
770
- 5. For each idea, create a row with: id,,description,,pending (empty parent_id for novel ideas)
771
- 6. Each description should be one clear sentence describing a novel algorithmic approach
772
- 7. Focus on creative, ambitious ideas that haven't been tried yet
773
- 8. Consider machine learning, new indicators, regime detection, risk management, etc.
774
-
775
- CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly."
826
+ 2. DO NOT DELETE OR REPLACE ANY EXISTING ROWS - YOU MUST PRESERVE ALL EXISTING DATA
827
+ 3. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
828
+ 4. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001"
829
+
830
+ if [[ -n "$existing_py_files" ]]; then
831
+ prompt+="
832
+ 5. IMPORTANT: The following IDs already have Python files and MUST NOT be reused: $existing_py_files
833
+ 6. Skip these IDs when assigning new IDs (e.g., if gen$CURRENT_GENERATION-001 and gen$CURRENT_GENERATION-002 exist as Python files, start with gen$CURRENT_GENERATION-003)"
834
+ else
835
+ prompt+="
836
+ 5. No existing Python files found for generation $CURRENT_GENERATION"
837
+ fi
838
+
839
+ prompt+="
840
+ 6. Use the Edit or MultiEdit tool to APPEND exactly $count new rows AT THE END of the CSV file
841
+ 7. For each idea, create a row with: id,,description,,pending (empty parent_id for novel ideas)
842
+ 8. Each description should be one clear sentence describing a novel algorithmic approach
843
+ 9. Focus on creative, ambitious ideas that haven't been tried yet
844
+ 10. Consider machine learning, new indicators, regime detection, risk management, etc.
845
+
846
+ IMPORTANT: You must APPEND new rows to the existing CSV file. DO NOT replace the file contents. All existing rows must remain unchanged.
847
+ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly.
848
+ CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
849
+
850
+ # Debug prompt size and context
851
+ echo "[DEBUG] Novel ideas prompt length: ${#prompt} characters" >&2
852
+ echo "[DEBUG] Working dir: $(pwd)" >&2
853
+ echo "[DEBUG] Evolution dir: $FULL_EVOLUTION_DIR" >&2
854
+ echo "[DEBUG] Temp CSV: $temp_csv" >&2
855
+ if [[ -f "$temp_csv" ]]; then
856
+ echo "[DEBUG] Temp CSV exists, size: $(wc -l < "$temp_csv") lines" >&2
857
+ else
858
+ echo "[DEBUG] Temp CSV does not exist yet" >&2
859
+ fi
776
860
 
777
861
  # Change to evolution directory so AI can access files
778
862
  local original_pwd=$(pwd)
779
863
  cd "$FULL_EVOLUTION_DIR"
780
864
 
865
+ # Debug: Show files in evolution directory
866
+ echo "[DEBUG] Current directory: $(pwd)" >&2
867
+ echo "[DEBUG] Temp CSV exists: $(ls -la "$temp_csv_basename" 2>&1)" >&2
868
+
781
869
  # Get AI to directly edit the CSV file
782
870
  local ai_response
783
871
  local stderr_file="stderr-$$.txt"
784
- if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
872
+ # Temporarily show stderr for debugging
873
+ if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
785
874
  echo "[ERROR] All AI models failed to generate novel ideas" >&2
786
875
  echo "[DEBUG] Stderr output from AI calls:" >&2
787
876
  cat "$stderr_file" >&2
@@ -821,6 +910,9 @@ generate_hill_climbing_direct() {
821
910
  local data_rows=$(grep -v '^[[:space:]]*$' "$FULL_CSV_PATH" | tail -n +2 | wc -l)
822
911
  echo "[DEBUG] Original CSV has $data_rows data rows" >&2
823
912
 
913
+ # Get existing Python files for this generation to avoid ID collisions
914
+ local existing_py_files=$(get_existing_py_files_for_generation "$CURRENT_GENERATION")
915
+
824
916
  # Extract just the IDs from top performers for clarity
825
917
  local valid_parent_ids
826
918
  valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
@@ -828,7 +920,7 @@ generate_hill_climbing_direct() {
828
920
  # Use relative paths and change to evolution directory so AI can access files
829
921
  local temp_csv_basename=$(basename "$temp_csv")
830
922
 
831
- local prompt="I need you to use your file editing capabilities to add exactly $count parameter tuning ideas to the CSV file: $temp_csv_basename
923
+ local prompt="I need you to use your file editing capabilities to APPEND exactly $count parameter tuning ideas to the CSV file: $temp_csv_basename
832
924
 
833
925
  IMPORTANT: You MUST use one of these exact parent IDs: $valid_parent_ids
834
926
 
@@ -839,17 +931,20 @@ CRITICAL INSTRUCTION: Before generating parameter tuning ideas, you MUST read th
839
931
  Algorithm source files are located at: evolution_<PARENT_ID>.py
840
932
  For example: evolution_gen01-251.py
841
933
 
842
- Instructions:
934
+ CRITICAL INSTRUCTIONS:
843
935
  1. Use the Read tool to examine the current CSV file
844
- 2. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
845
- 3. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
846
- 4. Use the Edit or MultiEdit tool to add exactly $count new rows to the CSV file
847
- 5. For each idea, create a row with: id,parent_id,description,,pending
848
- 6. Each parent_id MUST be one of: $valid_parent_ids
849
- 7. Each description should focus on adjusting specific parameters that exist in the parent's source code
850
- 8. Include current and new parameter values (e.g., \"Lower rsi_entry from 21 to 18\")
851
-
852
- CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly."
936
+ 2. DO NOT DELETE OR REPLACE ANY EXISTING ROWS - YOU MUST PRESERVE ALL EXISTING DATA
937
+ 3. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
938
+ 4. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
939
+ 5. Use the Edit or MultiEdit tool to APPEND exactly $count new rows AT THE END of the CSV file
940
+ 6. For each idea, create a row with: id,parent_id,description,,pending
941
+ 7. Each parent_id MUST be one of: $valid_parent_ids
942
+ 8. Each description should focus on adjusting specific parameters that exist in the parent's source code
943
+ 9. Include current and new parameter values (e.g., \"Lower rsi_entry from 21 to 18\")
944
+
945
+ IMPORTANT: You must APPEND new rows to the existing CSV file. DO NOT replace the file contents. All existing rows must remain unchanged.
946
+ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly.
947
+ CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
853
948
 
854
949
  # Change to evolution directory so AI can access files
855
950
  local original_pwd=$(pwd)
@@ -858,7 +953,8 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
858
953
  # Get AI to directly edit the CSV file
859
954
  local ai_response
860
955
  local stderr_file="stderr-$$.txt"
861
- if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
956
+ # Temporarily show stderr for debugging
957
+ if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
862
958
  echo "[ERROR] All AI models failed to generate hill climbing ideas" >&2
863
959
  cat "$stderr_file" >&2
864
960
  cd "$original_pwd"
@@ -895,6 +991,9 @@ generate_structural_mutation_direct() {
895
991
  local data_rows=$(grep -v '^[[:space:]]*$' "$FULL_CSV_PATH" | tail -n +2 | wc -l)
896
992
  echo "[DEBUG] Original CSV has $data_rows data rows" >&2
897
993
 
994
+ # Get existing Python files for this generation to avoid ID collisions
995
+ local existing_py_files=$(get_existing_py_files_for_generation "$CURRENT_GENERATION")
996
+
898
997
  # Extract just the IDs from top performers for clarity
899
998
  local valid_parent_ids
900
999
  valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
@@ -902,7 +1001,7 @@ generate_structural_mutation_direct() {
902
1001
  # Use relative paths and change to evolution directory so AI can access files
903
1002
  local temp_csv_basename=$(basename "$temp_csv")
904
1003
 
905
- local prompt="I need you to use your file editing capabilities to add exactly $count structural modification ideas to the CSV file: $temp_csv_basename
1004
+ local prompt="I need you to use your file editing capabilities to APPEND exactly $count structural modification ideas to the CSV file: $temp_csv_basename
906
1005
 
907
1006
  IMPORTANT: You MUST use one of these exact parent IDs: $valid_parent_ids
908
1007
 
@@ -913,17 +1012,20 @@ CRITICAL INSTRUCTION: Before generating structural modification ideas, you MUST
913
1012
  Algorithm source files are located at: evolution_<PARENT_ID>.py
914
1013
  For example: evolution_gen01-251.py
915
1014
 
916
- Instructions:
1015
+ CRITICAL INSTRUCTIONS:
917
1016
  1. Use the Read tool to examine the current CSV file
918
- 2. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
919
- 3. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
920
- 4. Use the Edit or MultiEdit tool to add exactly $count new rows to the CSV file
921
- 5. For each idea, create a row with: id,parent_id,description,,pending
922
- 6. Each parent_id MUST be one of: $valid_parent_ids
923
- 7. Each description should focus on architectural/structural changes based on the parent's actual code
924
- 8. Reference actual components/methods found in the source code
925
-
926
- CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly."
1017
+ 2. DO NOT DELETE OR REPLACE ANY EXISTING ROWS - YOU MUST PRESERVE ALL EXISTING DATA
1018
+ 3. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
1019
+ 4. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
1020
+ 5. Use the Edit or MultiEdit tool to APPEND exactly $count new rows AT THE END of the CSV file
1021
+ 6. For each idea, create a row with: id,parent_id,description,,pending
1022
+ 7. Each parent_id MUST be one of: $valid_parent_ids
1023
+ 8. Each description should focus on architectural/structural changes based on the parent's actual code
1024
+ 9. Reference actual components/methods found in the source code
1025
+
1026
+ IMPORTANT: You must APPEND new rows to the existing CSV file. DO NOT replace the file contents. All existing rows must remain unchanged.
1027
+ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly.
1028
+ CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
927
1029
 
928
1030
  # Change to evolution directory so AI can access files
929
1031
  local original_pwd=$(pwd)
@@ -932,7 +1034,8 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
932
1034
  # Get AI to directly edit the CSV file
933
1035
  local ai_response
934
1036
  local stderr_file="stderr-$$.txt"
935
- if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
1037
+ # Temporarily show stderr for debugging
1038
+ if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
936
1039
  echo "[ERROR] All AI models failed to generate structural mutation ideas" >&2
937
1040
  cat "$stderr_file" >&2
938
1041
  cd "$original_pwd"
@@ -969,6 +1072,9 @@ generate_crossover_direct() {
969
1072
  local data_rows=$(grep -v '^[[:space:]]*$' "$FULL_CSV_PATH" | tail -n +2 | wc -l)
970
1073
  echo "[DEBUG] Original CSV has $data_rows data rows" >&2
971
1074
 
1075
+ # Get existing Python files for this generation to avoid ID collisions
1076
+ local existing_py_files=$(get_existing_py_files_for_generation "$CURRENT_GENERATION")
1077
+
972
1078
  # Extract just the IDs from top performers for clarity
973
1079
  local valid_parent_ids
974
1080
  valid_parent_ids=$(echo "$top_performers" | cut -d',' -f1 | paste -sd ',' -)
@@ -976,7 +1082,7 @@ generate_crossover_direct() {
976
1082
  # Use relative paths and change to evolution directory so AI can access files
977
1083
  local temp_csv_basename=$(basename "$temp_csv")
978
1084
 
979
- local prompt="I need you to use your file editing capabilities to add exactly $count hybrid combination ideas to the CSV file: $temp_csv_basename
1085
+ local prompt="I need you to use your file editing capabilities to APPEND exactly $count hybrid combination ideas to the CSV file: $temp_csv_basename
980
1086
 
981
1087
  IMPORTANT: You MUST use ONLY these exact parent IDs: $valid_parent_ids
982
1088
 
@@ -987,17 +1093,20 @@ CRITICAL INSTRUCTION: Before generating hybrid combination ideas, you MUST read
987
1093
  Algorithm source files are located at: evolution_<PARENT_ID>.py
988
1094
  For example: evolution_gen01-251.py
989
1095
 
990
- Instructions:
1096
+ CRITICAL INSTRUCTIONS:
991
1097
  1. Use the Read tool to examine the current CSV file
992
- 2. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
993
- 3. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
994
- 4. Use the Edit or MultiEdit tool to add exactly $count new rows to the CSV file
995
- 5. For each idea, create a row with: id,parent_id,description,,pending
996
- 6. Each parent_id MUST be one of: $valid_parent_ids (choose the primary parent)
997
- 7. Each description should combine actual elements from 2+ algorithms based on their source code
998
- 8. Reference specific components/features found in the actual source code
999
-
1000
- CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly."
1098
+ 2. DO NOT DELETE OR REPLACE ANY EXISTING ROWS - YOU MUST PRESERVE ALL EXISTING DATA
1099
+ 3. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
1100
+ 4. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
1101
+ 5. Use the Edit or MultiEdit tool to APPEND exactly $count new rows AT THE END of the CSV file
1102
+ 6. For each idea, create a row with: id,parent_id,description,,pending
1103
+ 7. Each parent_id MUST be one of: $valid_parent_ids (choose the primary parent)
1104
+ 8. Each description should combine actual elements from 2+ algorithms based on their source code
1105
+ 9. Reference specific components/features found in the actual source code
1106
+
1107
+ IMPORTANT: You must APPEND new rows to the existing CSV file. DO NOT replace the file contents. All existing rows must remain unchanged.
1108
+ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly.
1109
+ CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
1001
1110
 
1002
1111
  # Change to evolution directory so AI can access files
1003
1112
  local original_pwd=$(pwd)
@@ -1006,7 +1115,8 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
1006
1115
  # Get AI to directly edit the CSV file
1007
1116
  local ai_response
1008
1117
  local stderr_file="stderr-$$.txt"
1009
- if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
1118
+ # Temporarily show stderr for debugging
1119
+ if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$count" "$temp_csv_basename"); then
1010
1120
  echo "[ERROR] All AI models failed to generate crossover hybrid ideas" >&2
1011
1121
  cat "$stderr_file" >&2
1012
1122
  cd "$original_pwd"
@@ -1078,14 +1188,15 @@ $top_performers"
1078
1188
 
1079
1189
  prompt+="
1080
1190
 
1081
- Instructions:
1191
+ CRITICAL INSTRUCTIONS:
1082
1192
  1. Use the Read tool to examine the current CSV file
1083
- 2. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
1084
- 3. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
1085
- 4. Use the Edit or MultiEdit tool to add exactly $TOTAL_IDEAS new rows to the CSV file
1086
- 5. For each idea, create a row with: id,parent_id,description,,pending
1087
- 6. Mix both parameter tuning and structural changes
1088
- 7. If building on existing algorithms, use their ID as parent_id, otherwise leave parent_id empty
1193
+ 2. DO NOT DELETE OR REPLACE ANY EXISTING ROWS - YOU MUST PRESERVE ALL EXISTING DATA
1194
+ 3. Find the highest ID number for generation $CURRENT_GENERATION (e.g., if gen$CURRENT_GENERATION-003 exists, next should be gen$CURRENT_GENERATION-004)
1195
+ 4. If no gen$CURRENT_GENERATION entries exist yet, start with gen$CURRENT_GENERATION-001
1196
+ 5. Use the Edit or MultiEdit tool to APPEND exactly $TOTAL_IDEAS new rows AT THE END of the CSV file
1197
+ 6. For each idea, create a row with: id,parent_id,description,,pending
1198
+ 7. Mix both parameter tuning and structural changes
1199
+ 8. If building on existing algorithms, use their ID as parent_id, otherwise leave parent_id empty
1089
1200
 
1090
1201
  ⚠️ AVOID ONLY: Kelly floor/cap adjustments that assume leverage > 1.0 (these get clamped and have no effect)
1091
1202
 
@@ -1099,7 +1210,9 @@ Instructions:
1099
1210
  - Time-Based Patterns: Intraday effects, calendar anomalies, volatility timing
1100
1211
  - Parameter Optimization: Entry thresholds, indicator periods, strategy weights
1101
1212
 
1102
- CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly."
1213
+ IMPORTANT: You must APPEND new rows to the existing CSV file. DO NOT replace the file contents. All existing rows must remain unchanged.
1214
+ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CSV file. DO NOT return CSV text - use your tools to edit the file directly.
1215
+ CRITICAL: Do NOT use any git commands (git add, git commit, git reset, etc.). Only modify the file directly."
1103
1216
 
1104
1217
  # Change to evolution directory so AI can access files
1105
1218
  local original_pwd=$(pwd)
@@ -1108,7 +1221,7 @@ CRITICAL: You must use your file editing tools (Edit/MultiEdit) to modify the CS
1108
1221
  # Get AI to directly edit the CSV file
1109
1222
  local ai_response
1110
1223
  local stderr_file="stderr-$$.txt"
1111
- if ! ai_response=$(call_ai_with_fallbacks "$prompt" "$CURRENT_GENERATION" 2>"$stderr_file"); then
1224
+ if ! ai_response=$(call_ai_for_ideation "$prompt" "$CURRENT_GENERATION" "$TOTAL_IDEAS" "$temp_csv_basename" 2>"$stderr_file"); then
1112
1225
  echo "[ERROR] All AI models failed to generate ideas" >&2
1113
1226
  cat "$stderr_file" >&2
1114
1227
  cd "$original_pwd"