claude-evolve 1.5.34 → 1.6.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.
@@ -0,0 +1,178 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ # Function to show help
6
+ show_help() {
7
+ cat <<EOF
8
+ claude-evolve clean-corrupted - Remove corrupted records from evolution CSV
9
+
10
+ USAGE:
11
+ claude-evolve clean-corrupted [OPTIONS]
12
+
13
+ OPTIONS:
14
+ --dry-run Show what would be removed without modifying the CSV
15
+ --help Show this help message
16
+
17
+ DESCRIPTION:
18
+ Removes corrupted records with invalid ID formats, such as:
19
+ - IDs with line numbers and pipe characters (e.g., "00648| gen43-001")
20
+ - IDs with leading digits followed by spaces
21
+ - Any ID containing pipe (|) characters
22
+
23
+ Creates a backup before modifying the CSV.
24
+
25
+ EXAMPLES:
26
+ claude-evolve clean-corrupted # Remove corrupted records
27
+ claude-evolve clean-corrupted --dry-run # Preview what would be removed
28
+ EOF
29
+ }
30
+
31
+ # Parse arguments
32
+ DRY_RUN=false
33
+
34
+ while [[ $# -gt 0 ]]; do
35
+ case $1 in
36
+ --dry-run)
37
+ DRY_RUN=true
38
+ shift
39
+ ;;
40
+ --help)
41
+ show_help
42
+ exit 0
43
+ ;;
44
+ *)
45
+ echo "[ERROR] Unknown option: $1" >&2
46
+ exit 1
47
+ ;;
48
+ esac
49
+ done
50
+
51
+ # Load configuration
52
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
53
+ # shellcheck source=../lib/config.sh
54
+ source "$SCRIPT_DIR/../lib/config.sh"
55
+
56
+ # Use CLAUDE_EVOLVE_CONFIG if set, otherwise default
57
+ if [[ -n ${CLAUDE_EVOLVE_CONFIG:-} ]]; then
58
+ load_config "$CLAUDE_EVOLVE_CONFIG"
59
+ else
60
+ # Check if config.yaml exists in current directory
61
+ if [[ -f "config.yaml" ]]; then
62
+ # Don't export to avoid collision with parallel runs
63
+ CONFIG_FILE="$(pwd)/config.yaml"
64
+ load_config "$CONFIG_FILE"
65
+ else
66
+ load_config
67
+ fi
68
+ fi
69
+
70
+ # Validate configuration
71
+ if ! validate_config; then
72
+ echo "[ERROR] Configuration validation failed" >&2
73
+ exit 1
74
+ fi
75
+
76
+ # Check if CSV exists
77
+ if [[ ! -f "$FULL_CSV_PATH" ]]; then
78
+ echo "[ERROR] Evolution CSV not found: $FULL_CSV_PATH" >&2
79
+ echo "Run 'claude-evolve setup' first or navigate to the correct directory" >&2
80
+ exit 1
81
+ fi
82
+
83
+ echo "Checking for corrupted records in: $FULL_CSV_PATH"
84
+
85
+ # Use Python to identify and optionally remove corrupted records
86
+ "$PYTHON_CMD" - <<EOF
87
+ import csv
88
+ import sys
89
+ import re
90
+ import shutil
91
+ from datetime import datetime
92
+
93
+ csv_path = "$FULL_CSV_PATH"
94
+ dry_run = $DRY_RUN
95
+
96
+ def is_valid_candidate_id(candidate_id):
97
+ """Check if a candidate ID is valid."""
98
+ if not candidate_id or candidate_id == "id":
99
+ return True # Header row
100
+
101
+ # Reject IDs containing pipe characters (line number artifacts)
102
+ if '|' in candidate_id:
103
+ return False
104
+
105
+ # Valid ID should match: baseline-NNN or genNN-NNN format
106
+ # Also accept special IDs like "000", "0", etc.
107
+ if re.match(r'^(baseline|gen\d{2})-\d{3}$', candidate_id):
108
+ return True
109
+ if re.match(r'^(000|0|gen00-000)$', candidate_id):
110
+ return True
111
+
112
+ # Reject anything with leading digits followed by non-standard format
113
+ if re.match(r'^\d+\s', candidate_id):
114
+ return False
115
+
116
+ return True
117
+
118
+ # Read CSV
119
+ with open(csv_path, 'r') as f:
120
+ reader = csv.reader(f)
121
+ rows = list(reader)
122
+
123
+ # Identify corrupted records
124
+ corrupted_records = []
125
+ valid_rows = [rows[0]] # Keep header
126
+
127
+ for i, row in enumerate(rows[1:], start=1):
128
+ if not row or len(row) == 0:
129
+ continue
130
+
131
+ candidate_id = row[0] if len(row) > 0 else ""
132
+
133
+ if not is_valid_candidate_id(candidate_id):
134
+ corrupted_records.append((i, candidate_id, row))
135
+ else:
136
+ valid_rows.append(row)
137
+
138
+ # Report findings
139
+ total_records = len(rows) - 1 # Exclude header
140
+ corrupted_count = len(corrupted_records)
141
+
142
+ print(f"\\nTotal records: {total_records}")
143
+ print(f"Corrupted records: {corrupted_count}")
144
+ print(f"Valid records: {len(valid_rows) - 1}") # Exclude header
145
+
146
+ if corrupted_count > 0:
147
+ print("\\n🔍 Corrupted records found:")
148
+ for line_num, candidate_id, row in corrupted_records[:20]:
149
+ status = row[4] if len(row) > 4 else "unknown"
150
+ print(f" Line {line_num}: {candidate_id} (status: {status})")
151
+
152
+ if len(corrupted_records) > 20:
153
+ print(f" ... and {len(corrupted_records) - 20} more")
154
+
155
+ if not dry_run:
156
+ # Create backup
157
+ backup_path = f"{csv_path}.backup.{datetime.now().strftime('%Y%m%d-%H%M%S')}"
158
+ shutil.copy2(csv_path, backup_path)
159
+ print(f"\\n✅ Created backup: {backup_path}")
160
+
161
+ # Write cleaned CSV
162
+ with open(csv_path, 'w', newline='') as f:
163
+ writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
164
+ for row in valid_rows:
165
+ writer.writerow(row)
166
+
167
+ print(f"✅ Removed {corrupted_count} corrupted records from CSV")
168
+ print(f"✅ Cleaned CSV saved to: {csv_path}")
169
+ else:
170
+ print("\\n[DRY RUN] No changes made. Run without --dry-run to remove corrupted records.")
171
+ else:
172
+ print("\\n✅ No corrupted records found!")
173
+
174
+ sys.exit(0)
175
+ EOF
176
+
177
+ echo ""
178
+ echo "Done!"
@@ -66,6 +66,7 @@ COMMANDS:
66
66
  status Show evolution progress and current leader
67
67
  autostatus Auto-updating status display (real-time)
68
68
  cleanup Clean up unchanged algorithms and descendants
69
+ clean-corrupted Remove corrupted records from evolution CSV
69
70
  cleanup-duplicates Alias for cleanup (deprecated)
70
71
  help Show this help message
71
72
 
@@ -92,16 +93,17 @@ show_menu() {
92
93
  echo
93
94
  echo "What would you like to do?"
94
95
  echo
95
- echo " 1) setup - Initialize evolution workspace"
96
- echo " 2) ideate - Generate new algorithm ideas"
97
- echo " 3) run - Execute evolution candidates"
98
- echo " 4) analyze - Analyze evolution results"
99
- echo " 5) edit - Manage candidate statuses by generation"
100
- echo " 6) status - Show evolution progress and current leader"
101
- echo " 7) autostatus - Auto-updating status display (real-time)"
102
- echo " 8) config - Manage configuration settings"
103
- echo " 9) help - Show help message"
104
- echo " 0) exit - Exit"
96
+ echo " 1) setup - Initialize evolution workspace"
97
+ echo " 2) ideate - Generate new algorithm ideas"
98
+ echo " 3) run - Execute evolution candidates"
99
+ echo " 4) analyze - Analyze evolution results"
100
+ echo " 5) edit - Manage candidate statuses by generation"
101
+ echo " 6) status - Show evolution progress and current leader"
102
+ echo " 7) autostatus - Auto-updating status display (real-time)"
103
+ echo " 8) clean-corrupted - Remove corrupted records from CSV"
104
+ echo " 9) config - Manage configuration settings"
105
+ echo " h) help - Show help message"
106
+ echo " 0) exit - Exit"
105
107
  echo
106
108
 
107
109
  # Show workspace status
@@ -152,7 +154,7 @@ check_for_updates
152
154
  # Main logic
153
155
  if [[ $# -eq 0 ]]; then
154
156
  show_menu
155
- read -r -p "Enter your choice (1-9, 0): " choice
157
+ read -r -p "Enter your choice (1-9, h, 0): " choice
156
158
 
157
159
  case $choice in
158
160
  1) exec "$SCRIPT_DIR/claude-evolve-setup" ;;
@@ -162,14 +164,15 @@ if [[ $# -eq 0 ]]; then
162
164
  5) exec "$SCRIPT_DIR/claude-evolve-edit" ;;
163
165
  6) exec "$SCRIPT_DIR/claude-evolve-status" ;;
164
166
  7) exec "$SCRIPT_DIR/claude-evolve-autostatus" ;;
165
- 8) exec "$SCRIPT_DIR/claude-evolve-config" ;;
166
- 9) show_help ;;
167
+ 8) exec "$SCRIPT_DIR/claude-evolve-clean-corrupted" ;;
168
+ 9) exec "$SCRIPT_DIR/claude-evolve-config" ;;
169
+ h|H) show_help ;;
167
170
  0)
168
171
  echo "Goodbye!"
169
172
  exit 0
170
173
  ;;
171
174
  *)
172
- echo -e "${RED}Invalid choice. Please select 1-9 or 0.${NC}"
175
+ echo -e "${RED}Invalid choice. Please select 1-9, h, or 0.${NC}"
173
176
  exit 1
174
177
  ;;
175
178
  esac
@@ -214,6 +217,10 @@ cleanup-duplicates|cleanup)
214
217
  shift
215
218
  exec "$SCRIPT_DIR/claude-evolve-cleanup" "$@"
216
219
  ;;
220
+ clean-corrupted)
221
+ shift
222
+ exec "$SCRIPT_DIR/claude-evolve-clean-corrupted" "$@"
223
+ ;;
217
224
  config)
218
225
  shift
219
226
  exec "$SCRIPT_DIR/claude-evolve-config" "$@"
package/lib/ai-cli.sh CHANGED
@@ -96,6 +96,29 @@ $prompt"
96
96
  ai_output=$(timeout 300 opencode -m openrouter/x-ai/grok-4 run "$prompt" 2>&1)
97
97
  local ai_exit_code=$?
98
98
  ;;
99
+ aider-qwen3)
100
+ # Aider with Qwen3-Coder via Ollama
101
+ # Aider edits files in place, so we need to create a temp file
102
+ local temp_file=$(mktemp /tmp/aider-edit-XXXXXX.py)
103
+
104
+ # Extract current algorithm from prompt if present, or create empty file
105
+ # The prompt usually contains the algorithm to improve
106
+ echo "# Algorithm to improve" > "$temp_file"
107
+
108
+ # Run aider with the prompt
109
+ local ai_output
110
+ ai_output=$(timeout 600 aider --yes --no-git --no-show-model-warnings --model ollama/qwen3-coder:30b --message "$prompt" "$temp_file" 2>&1)
111
+ local ai_exit_code=$?
112
+
113
+ # If successful, output the modified file content
114
+ if [[ $ai_exit_code -eq 0 ]]; then
115
+ cat "$temp_file"
116
+ ai_exit_code=$?
117
+ fi
118
+
119
+ # Clean up
120
+ rm -f "$temp_file"
121
+ ;;
99
122
  *)
100
123
  echo "[ERROR] Unknown model: $model_name" >&2
101
124
  return 1
package/lib/csv_fixer.py CHANGED
@@ -2,25 +2,87 @@
2
2
  """
3
3
  CSV format fixer for claude-evolve
4
4
  Ensures proper quoting of CSV fields, especially descriptions
5
+ Also filters out corrupted records with invalid ID formats
5
6
  """
6
7
 
7
8
  import csv
8
9
  import sys
10
+ import re
11
+
12
+ def is_valid_candidate_id(candidate_id):
13
+ """
14
+ Check if a candidate ID is valid.
15
+ Valid formats:
16
+ - baseline-000
17
+ - gen00-000
18
+ - gen01-001, gen02-042, etc.
19
+
20
+ Invalid formats (to reject):
21
+ - 00648| gen43-001 (line numbers with pipes)
22
+ - Any ID containing | character
23
+ - Any ID with leading numbers followed by |
24
+ """
25
+ if not candidate_id or candidate_id == "id":
26
+ return True # Header row
27
+
28
+ # Reject IDs containing pipe characters (line number artifacts)
29
+ if '|' in candidate_id:
30
+ return False
31
+
32
+ # Valid ID should match: baseline-NNN or genNN-NNN format
33
+ # Also accept special IDs like "000", "0", etc.
34
+ if re.match(r'^(baseline|gen\d{2})-\d{3}$', candidate_id):
35
+ return True
36
+ if re.match(r'^(000|0|gen00-000)$', candidate_id):
37
+ return True
38
+
39
+ # Reject anything with leading digits followed by non-standard format
40
+ if re.match(r'^\d+\s', candidate_id):
41
+ return False
42
+
43
+ return True
9
44
 
10
45
  def fix_csv_format(input_file, output_file):
11
46
  """
12
47
  Read a CSV file and ensure all fields are properly quoted.
13
48
  The csv module handles quoting automatically based on content.
49
+ Also filters out rows with invalid candidate IDs.
14
50
  """
15
51
  with open(input_file, 'r') as infile:
16
52
  reader = csv.reader(infile)
17
53
  rows = list(reader)
18
-
54
+
55
+ rejected_count = 0
56
+ filtered_rows = []
57
+
58
+ for i, row in enumerate(rows):
59
+ # Always keep header
60
+ if i == 0:
61
+ filtered_rows.append(row)
62
+ continue
63
+
64
+ # Skip empty rows
65
+ if not row or len(row) == 0:
66
+ continue
67
+
68
+ candidate_id = row[0] if len(row) > 0 else ""
69
+
70
+ # Check if candidate ID is valid
71
+ if not is_valid_candidate_id(candidate_id):
72
+ rejected_count += 1
73
+ print(f"[WARN] Rejecting corrupted record with invalid ID: {candidate_id}", file=sys.stderr)
74
+ continue
75
+
76
+ filtered_rows.append(row)
77
+
78
+ if rejected_count > 0:
79
+ print(f"[INFO] Filtered out {rejected_count} corrupted records", file=sys.stderr)
80
+
19
81
  with open(output_file, 'w', newline='') as outfile:
20
82
  writer = csv.writer(outfile, quoting=csv.QUOTE_NONNUMERIC)
21
-
83
+
22
84
  # Write all rows - csv.writer handles quoting automatically
23
- for row in rows:
85
+ for row in filtered_rows:
24
86
  writer.writerow(row)
25
87
 
26
88
  if __name__ == "__main__":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.5.34",
3
+ "version": "1.6.1",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",
@@ -89,3 +89,4 @@ llm_cli:
89
89
  # - glm: GLM-4.6 via OpenCode CLI
90
90
  # - grok-code-fast: Grok Code Fast 1 via OpenRouter
91
91
  # - grok-4: Grok 4 via OpenRouter
92
+ # - aider-qwen3: Qwen3-Coder via Aider + Ollama (local, free)