claude-evolve 1.8.42 → 1.8.44

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.
@@ -236,10 +236,11 @@ if [[ $use_strategies == true ]]; then
236
236
  fi
237
237
 
238
238
  # Get next generation number that doesn't have existing Python files
239
+ # AIDEV-NOTE: Returns zero-padded generation number (e.g., "02" not "2")
239
240
  get_next_generation() {
240
241
  # Start with generation 1 if no CSV exists
241
242
  local start_gen=1
242
-
243
+
243
244
  if [[ -f "$FULL_CSV_PATH" ]]; then
244
245
  # Use Python for proper CSV parsing to find max generation
245
246
  local max_gen
@@ -264,21 +265,25 @@ print(max_gen)
264
265
  # Start checking from the next generation after max
265
266
  start_gen=$((max_gen + 1))
266
267
  fi
267
-
268
+
268
269
  # Keep incrementing until we find a generation with no Python files
269
270
  local candidate_gen=$start_gen
270
271
  while true; do
271
- # No padding - generation numbers are used as-is in filenames
272
- local gen_formatted="$candidate_gen"
272
+ # Zero-pad to 2 digits for consistency (gen01, gen02, etc.)
273
+ local gen_formatted
274
+ gen_formatted=$(printf "%02d" "$candidate_gen")
273
275
 
274
- # Check if any Python files exist for this generation
276
+ # Check if any Python files exist for this generation (check both padded and unpadded)
275
277
  local py_files_exist=false
276
278
  if ls "$FULL_OUTPUT_DIR"/evolution_gen${gen_formatted}-*.py >/dev/null 2>&1; then
277
279
  py_files_exist=true
280
+ elif ls "$FULL_OUTPUT_DIR"/evolution_gen${candidate_gen}-*.py >/dev/null 2>&1; then
281
+ # Also check unpadded format for legacy compatibility
282
+ py_files_exist=true
278
283
  fi
279
284
 
280
285
  if [[ "$py_files_exist" == "false" ]]; then
281
- # This generation is safe to use
286
+ # This generation is safe to use - return padded format
282
287
  echo "$gen_formatted"
283
288
  return
284
289
  else
@@ -1710,30 +1715,44 @@ count_generation_pending() {
1710
1715
  }
1711
1716
 
1712
1717
  # Find the right generation to use
1718
+ # AIDEV-NOTE: Generation numbers must be zero-padded to 2 digits (gen01, gen02, etc.)
1719
+ # to maintain consistency with existing CSV data format
1713
1720
  highest_gen=$(get_highest_generation)
1714
1721
  if [[ $highest_gen -eq 0 ]]; then
1715
- # No generations yet, start with 1
1716
- CURRENT_GENERATION=1
1717
- echo "[INFO] No existing generations, starting with generation 1"
1722
+ # No generations yet, start with 01
1723
+ CURRENT_GENERATION="01"
1724
+ echo "[INFO] No existing generations, starting with generation 01"
1718
1725
  else
1719
1726
  # Check if highest generation needs more ideas
1727
+ # Use unpadded for grep patterns (matches both gen1- and gen01-)
1720
1728
  existing_ideas=$(count_generation_ideas "$highest_gen")
1721
1729
  pending_ideas=$(count_generation_pending "$highest_gen")
1730
+ # Also check padded format
1731
+ padded_gen=$(printf "%02d" "$highest_gen")
1732
+ existing_ideas_padded=$(count_generation_ideas "$padded_gen")
1733
+ pending_ideas_padded=$(count_generation_pending "$padded_gen")
1734
+ # Use whichever found more (handles both gen1 and gen01 formats)
1735
+ if [[ $existing_ideas_padded -gt $existing_ideas ]]; then
1736
+ existing_ideas=$existing_ideas_padded
1737
+ pending_ideas=$pending_ideas_padded
1738
+ fi
1722
1739
 
1723
1740
  echo "[INFO] Highest generation: $highest_gen with $existing_ideas total ideas ($pending_ideas pending)"
1724
1741
 
1725
1742
  if [[ $existing_ideas -ge $TOTAL_IDEAS ]]; then
1726
1743
  # Highest generation is full, create a new one
1727
1744
  CURRENT_GENERATION=$(get_next_generation)
1745
+ # Ensure it's zero-padded
1746
+ CURRENT_GENERATION=$(printf "%02d" "$CURRENT_GENERATION")
1728
1747
  echo "[INFO] Generation $highest_gen is full ($existing_ideas >= $TOTAL_IDEAS), creating generation $CURRENT_GENERATION"
1729
1748
  elif [[ $pending_ideas -ge $TOTAL_IDEAS ]]; then
1730
1749
  # Already have enough pending, skip ideation
1731
- echo "[INFO] Generation $highest_gen already has $pending_ideas pending ideas (target: $TOTAL_IDEAS)"
1750
+ echo "[INFO] Generation $padded_gen already has $pending_ideas pending ideas (target: $TOTAL_IDEAS)"
1732
1751
  echo "[INFO] Skipping ideation - workers will process existing ideas"
1733
1752
  exit 0
1734
1753
  else
1735
- # Continue filling the current highest generation
1736
- CURRENT_GENERATION=$highest_gen
1754
+ # Continue filling the current highest generation - use padded format
1755
+ CURRENT_GENERATION=$(printf "%02d" "$highest_gen")
1737
1756
  echo "[INFO] Continuing generation $CURRENT_GENERATION (need $((TOTAL_IDEAS - existing_ideas)) more ideas)"
1738
1757
  fi
1739
1758
  fi
@@ -111,6 +111,8 @@ else
111
111
  fi
112
112
 
113
113
  # AI random selection function for code evolution
114
+ # AIDEV-NOTE: This function reads the model name from a temp file written by call_ai_random
115
+ # because exports don't propagate from subshells. The model is stored in SUCCESSFUL_RUN_MODEL.
114
116
  call_ai_for_evolution() {
115
117
  local prompt="$1"
116
118
  local candidate_id="$2"
@@ -131,6 +133,17 @@ call_ai_for_evolution() {
131
133
  ai_output=$(call_ai_random "$prompt" "run")
132
134
  local ai_exit_code=$?
133
135
 
136
+ # Read the model name from temp file (written by call_ai_random in subshell)
137
+ local model_file="/tmp/.claude-evolve-model-$$"
138
+ if [[ -f "$model_file" ]]; then
139
+ SUCCESSFUL_RUN_MODEL=$(cat "$model_file")
140
+ rm -f "$model_file"
141
+ echo "[WORKER-$$] AI model used: $SUCCESSFUL_RUN_MODEL" >&2
142
+ else
143
+ echo "[WORKER-$$] Warning: Could not determine which AI model was used" >&2
144
+ SUCCESSFUL_RUN_MODEL=""
145
+ fi
146
+
134
147
  # Check if the target file was actually modified
135
148
  local file_was_modified=false
136
149
  if [[ -f "$target_file" ]]; then
@@ -310,20 +323,48 @@ CRITICAL: If you do not know how to implement what was asked for, or if the requ
310
323
  return 1
311
324
  }
312
325
 
313
- # Call AI with random model selection
314
- if ! call_ai_for_evolution "$evolution_prompt" "$candidate_id"; then
315
- echo "[WORKER-$$] ERROR: AI model failed to generate code - leaving as pending for retry" >&2
326
+ # AIDEV-NOTE: Retry logic for AI code generation
327
+ # Try up to 3 times with different random models before giving up
328
+ # This handles transient failures like rate limits or capacity issues
329
+ local max_retries=3
330
+ local retry_count=0
331
+ local ai_success=false
332
+
333
+ while [[ $retry_count -lt $max_retries ]]; do
334
+ ((retry_count++))
335
+ echo "[WORKER-$$] AI attempt $retry_count/$max_retries for $candidate_id" >&2
336
+
337
+ # Re-copy source file if this is a retry (previous attempt may have corrupted it)
338
+ if [[ $retry_count -gt 1 ]]; then
339
+ echo "[WORKER-$$] Re-copying source file for retry attempt" >&2
340
+ cp "$source_file" "$target_file"
341
+ fi
342
+
343
+ if call_ai_for_evolution "$evolution_prompt" "$candidate_id"; then
344
+ ai_success=true
345
+ break
346
+ else
347
+ echo "[WORKER-$$] AI attempt $retry_count failed" >&2
348
+ if [[ $retry_count -lt $max_retries ]]; then
349
+ echo "[WORKER-$$] Will retry with a different model..." >&2
350
+ sleep 2 # Brief pause before retry
351
+ fi
352
+ fi
353
+ done
354
+
355
+ if [[ "$ai_success" != "true" ]]; then
356
+ echo "[WORKER-$$] ERROR: All $max_retries AI attempts failed for $candidate_id" >&2
316
357
  safe_popd
317
358
  rm -f "$target_file" # Clean up on failure
318
- # Return with special code to indicate AI failure (should remain pending)
359
+ # Return with special code to indicate AI failure after all retries exhausted
319
360
  return 77
320
361
  fi
321
362
 
322
363
  # Restore working directory
323
364
  safe_popd
324
-
325
- echo "[WORKER-$$] Evolution applied successfully"
326
-
365
+
366
+ echo "[WORKER-$$] Evolution applied successfully (attempt $retry_count/$max_retries)"
367
+
327
368
  # Record which AI model generated the code (regardless of evaluation outcome)
328
369
  if [[ -n "${SUCCESSFUL_RUN_MODEL:-}" ]]; then
329
370
  echo "[WORKER-$$] Recording that $SUCCESSFUL_RUN_MODEL generated the code" >&2
package/lib/ai-cli.sh CHANGED
@@ -302,6 +302,9 @@ get_models_for_command() {
302
302
  # Usage: call_ai_random <prompt> <command>
303
303
  # command: "run" or "ideate"
304
304
  # Picks one random model from the list and uses it
305
+ # AIDEV-NOTE: This function writes the selected model to a temp file because
306
+ # export doesn't work from subshells (command substitution creates a subshell).
307
+ # The parent process should read /tmp/.claude-evolve-model-$$ to get the model name.
305
308
  call_ai_random() {
306
309
  local prompt="$1"
307
310
  local command="$2"
@@ -330,6 +333,11 @@ call_ai_random() {
330
333
 
331
334
  echo "[AI] Selected $model for $command (random from $num_models models)" >&2
332
335
 
336
+ # Write model to temp file so parent can read it
337
+ # (exports don't propagate from subshells created by $(...) command substitution)
338
+ local model_file="/tmp/.claude-evolve-model-$$"
339
+ echo "$model" > "$model_file"
340
+
333
341
  # Call the AI model
334
342
  local ai_output
335
343
  ai_output=$(call_ai_model_configured "$model" "$prompt")
@@ -338,9 +346,6 @@ call_ai_random() {
338
346
  # Clean output if needed
339
347
  ai_output=$(clean_ai_output "$ai_output" "$model")
340
348
 
341
- # Export the model used for tracking (used by worker)
342
- export SUCCESSFUL_RUN_MODEL="$model"
343
-
344
349
  # Log result
345
350
  if [[ $ai_exit_code -eq 0 ]]; then
346
351
  echo "[AI] $model returned exit code 0" >&2
package/lib/config.sh CHANGED
@@ -58,9 +58,9 @@ DEFAULT_MEMORY_LIMIT_MB=12288
58
58
  DEFAULT_WORKER_MAX_CANDIDATES=3
59
59
 
60
60
  # Default LLM CLI configuration
61
- DEFAULT_LLM_RUN="glm-zai kimi-coder glm-zai kimi-coder glm-zai kimi-coder codex-oss-local haiku"
61
+ DEFAULT_LLM_RUN="glm-zai glm-zai glm-zai glm-zai glm-zai kimi-coder codex-oss-local haiku"
62
62
  # Ideate: Commercial models for idea generation + local fallback
63
- DEFAULT_LLM_IDEATE="opus-think kimi-k2-openrouter gemini-3-pro-preview gpt5high grok-4-openrouter deepseek-openrouter glm-zai kimi-coder"
63
+ DEFAULT_LLM_IDEATE="opus-think kimi-k2-openrouter gemini-3-pro-preview gpt5high grok-4-openrouter deepseek-openrouter glm-zai"
64
64
 
65
65
  # Load configuration from a YAML file and update variables
66
66
  _load_yaml_config() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.8.42",
3
+ "version": "1.8.44",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",