claude-evolve 1.3.11 → 1.3.12

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.
@@ -63,7 +63,18 @@ count_pending() {
63
63
  return
64
64
  fi
65
65
 
66
- echo "$csv_content" | awk -F',' 'NR>1 && ($5 == "pending" || $5 == "") { count++ } END { print count+0 }'
66
+ # Use Python for proper CSV parsing with quoted fields
67
+ echo "$csv_content" | "$PYTHON_CMD" -c "
68
+ import csv
69
+ import sys
70
+ reader = csv.reader(sys.stdin)
71
+ next(reader) # Skip header
72
+ count = 0
73
+ for row in reader:
74
+ if len(row) >= 5 and (row[4] == 'pending' or row[4] == ''):
75
+ count += 1
76
+ print(count)
77
+ "
67
78
  }
68
79
 
69
80
  # Start a worker
@@ -198,20 +209,42 @@ trap 'echo "[DISPATCHER] Exiting with code $?" >&2' EXIT
198
209
  # Check for stuck "running" candidates from previous runs
199
210
  check_stuck_candidates() {
200
211
  if read_csv_with_lock csv_content; then
201
- local stuck_count=$(echo "$csv_content" | awk -F',' 'NR>1 && $5 == "running" { count++ } END { print count+0 }')
212
+ local stuck_count=$(echo "$csv_content" | "$PYTHON_CMD" -c "
213
+ import csv
214
+ import sys
215
+ reader = csv.reader(sys.stdin)
216
+ next(reader) # Skip header
217
+ count = 0
218
+ for row in reader:
219
+ if len(row) >= 5 and row[4] == 'running':
220
+ count += 1
221
+ print(count)
222
+ ")
202
223
  if [[ $stuck_count -gt 0 ]]; then
203
224
  echo "[DISPATCHER] Found $stuck_count candidates stuck in 'running' status"
204
225
  echo "[DISPATCHER] Resetting them to 'pending' for retry..."
205
226
 
206
227
  # Reset stuck candidates
207
228
  if acquire_csv_lock; then
208
- awk -F',' -v OFS=',' '
209
- NR==1 { print }
210
- NR>1 {
211
- if ($5 == "running") $5 = "pending"
212
- print
213
- }
214
- ' "$FULL_CSV_PATH" > "${FULL_CSV_PATH}.tmp" && mv -f "${FULL_CSV_PATH}.tmp" "$FULL_CSV_PATH"
229
+ "$PYTHON_CMD" -c "
230
+ import csv
231
+ import sys
232
+
233
+ # Read CSV
234
+ with open('$FULL_CSV_PATH', 'r') as f:
235
+ reader = csv.reader(f)
236
+ rows = list(reader)
237
+
238
+ # Reset running to pending
239
+ for i in range(1, len(rows)):
240
+ if len(rows[i]) >= 5 and rows[i][4] == 'running':
241
+ rows[i][4] = 'pending'
242
+
243
+ # Write back
244
+ with open('${FULL_CSV_PATH}.tmp', 'w', newline='') as f:
245
+ writer = csv.writer(f)
246
+ writer.writerows(rows)
247
+ " && mv -f "${FULL_CSV_PATH}.tmp" "$FULL_CSV_PATH"
215
248
  release_csv_lock
216
249
  fi
217
250
  fi
@@ -247,7 +280,17 @@ while true; do
247
280
  # Debug: Show CSV status if no pending
248
281
  if [[ $pending_count -eq 0 ]]; then
249
282
  total_rows=$(read_csv_with_lock csv_content && echo "$csv_content" | wc -l | xargs)
250
- complete_count=$(read_csv_with_lock csv_content && echo "$csv_content" | awk -F',' 'NR>1 && $5 == "complete" { count++ } END { print count+0 }')
283
+ complete_count=$(read_csv_with_lock csv_content && echo "$csv_content" | "$PYTHON_CMD" -c "
284
+ import csv
285
+ import sys
286
+ reader = csv.reader(sys.stdin)
287
+ next(reader) # Skip header
288
+ count = 0
289
+ for row in reader:
290
+ if len(row) >= 5 and row[4] == 'complete':
291
+ count += 1
292
+ print(count)
293
+ ")
251
294
  echo "[DISPATCHER] CSV has $((total_rows-1)) total candidates, $complete_count complete"
252
295
  fi
253
296
 
@@ -74,29 +74,39 @@ if ! read_csv_with_lock csv_content; then
74
74
  exit 1
75
75
  fi
76
76
 
77
- # Extract candidate data
78
- found=false
79
- while IFS=, read -r csv_id csv_based_on csv_desc csv_perf csv_stat; do
80
- if [[ $csv_id == "$candidate_id" ]]; then
81
- id="$csv_id"
82
- based_on_id="$csv_based_on"
83
- description="$csv_desc"
84
- performance="$csv_perf"
85
- status="$csv_stat"
86
- found=true
87
- break
88
- fi
89
- done <<< "$csv_content"
77
+ # Extract candidate data using Python
78
+ eval "$("$PYTHON_CMD" -c "
79
+ import csv
80
+ import sys
81
+ import io
82
+
83
+ csv_content = '''$csv_content'''
84
+ reader = csv.reader(io.StringIO(csv_content))
85
+ next(reader) # Skip header
86
+
87
+ found = False
88
+ for row in reader:
89
+ if len(row) >= 5 and row[0] == '$candidate_id':
90
+ # Escape special characters for shell
91
+ desc = row[2].replace('\\\\', '\\\\\\\\').replace('\"', '\\\\\"').replace('\$', '\\\\\$').replace('\`', '\\\\\`')
92
+ print(f'id=\"{row[0]}\"')
93
+ print(f'based_on_id=\"{row[1]}\"')
94
+ print(f'description=\"{desc}\"')
95
+ print(f'performance=\"{row[3]}\"')
96
+ print(f'status=\"{row[4]}\"')
97
+ print('found=true')
98
+ found = True
99
+ break
100
+
101
+ if not found:
102
+ print('found=false')
103
+ ")"
90
104
 
91
105
  if [[ $found == false ]]; then
92
106
  echo "[ERROR] Candidate ID not found: $candidate_id" >&2
93
107
  exit 1
94
108
  fi
95
109
 
96
- # Clean up description
97
- description=${description#\"}
98
- description=${description%\"}
99
-
100
110
  echo "[WORKER-$$] Description: $description"
101
111
  echo "[WORKER-$$] Based on ID: $based_on_id"
102
112
 
package/lib/csv-lock.sh CHANGED
@@ -94,19 +94,19 @@ update_csv_row_with_lock() {
94
94
  local target_id="$1"
95
95
  local field="$2"
96
96
  local value="$3"
97
- local csv_file="${EVOLUTION_DIR:-evolution}/evolution.csv"
97
+ local csv_file="${FULL_CSV_PATH:-${EVOLUTION_DIR:-evolution}/evolution.csv}"
98
98
 
99
99
  if ! acquire_csv_lock; then
100
100
  return 1
101
101
  fi
102
102
 
103
- # Determine field position
103
+ # Determine field position (0-based for Python)
104
104
  local field_pos
105
105
  case "$field" in
106
- "status") field_pos=5 ;;
107
- "performance") field_pos=4 ;;
108
- "description") field_pos=3 ;;
109
- "basedOnId") field_pos=2 ;;
106
+ "status") field_pos=4 ;;
107
+ "performance") field_pos=3 ;;
108
+ "description") field_pos=2 ;;
109
+ "basedOnId") field_pos=1 ;;
110
110
  *)
111
111
  echo "ERROR: Unknown field: $field" >&2
112
112
  release_csv_lock
@@ -114,11 +114,27 @@ update_csv_row_with_lock() {
114
114
  ;;
115
115
  esac
116
116
 
117
- # Update CSV using awk
118
- awk -F',' -v OFS=',' -v id="$target_id" -v pos="$field_pos" -v val="$value" '
119
- NR==1 || $1 != id { print }
120
- $1 == id { $pos = val; print }
121
- ' "$csv_file" > "${csv_file}.tmp" && mv -f "${csv_file}.tmp" "$csv_file"
117
+ # Update CSV using Python
118
+ "$PYTHON_CMD" -c "
119
+ import csv
120
+ import sys
121
+
122
+ # Read CSV
123
+ with open('$csv_file', 'r') as f:
124
+ reader = csv.reader(f)
125
+ rows = list(reader)
126
+
127
+ # Update the specific field
128
+ for i in range(1, len(rows)):
129
+ if rows[i][0] == '$target_id':
130
+ rows[i][$field_pos] = '$value'
131
+ break
132
+
133
+ # Write back
134
+ with open('${csv_file}.tmp', 'w', newline='') as f:
135
+ writer = csv.writer(f)
136
+ writer.writerows(rows)
137
+ " && mv -f "${csv_file}.tmp" "$csv_file"
122
138
 
123
139
  release_csv_lock
124
140
  return 0
@@ -127,27 +143,40 @@ update_csv_row_with_lock() {
127
143
  # Find next pending candidate with lock
128
144
  # Usage: next_pending=$(find_next_pending_with_lock)
129
145
  find_next_pending_with_lock() {
130
- local csv_file="${EVOLUTION_DIR:-evolution}/evolution.csv"
146
+ local csv_file="${FULL_CSV_PATH:-${EVOLUTION_DIR:-evolution}/evolution.csv}"
131
147
 
132
148
  if ! acquire_csv_lock; then
133
149
  return 1
134
150
  fi
135
151
 
136
- # Find oldest pending candidate and update to running
137
- local candidate=$(awk -F',' '
138
- NR>1 && ($5 == "pending" || $5 == "") { print $1; exit }
139
- ' "$csv_file")
152
+ # Find oldest pending candidate and update to running using Python
153
+ local candidate=$("$PYTHON_CMD" -c "
154
+ import csv
155
+ import sys
156
+
157
+ # Read CSV
158
+ with open('$csv_file', 'r') as f:
159
+ reader = csv.reader(f)
160
+ rows = list(reader)
161
+
162
+ # Find first pending candidate
163
+ candidate_id = None
164
+ for i in range(1, len(rows)):
165
+ if len(rows[i]) >= 5 and (rows[i][4] == 'pending' or rows[i][4] == ''):
166
+ candidate_id = rows[i][0]
167
+ rows[i][4] = 'running' # Update status
168
+ break
169
+
170
+ # Write back if we found a candidate
171
+ if candidate_id:
172
+ with open('${csv_file}.tmp', 'w', newline='') as f:
173
+ writer = csv.writer(f)
174
+ writer.writerows(rows)
175
+ print(candidate_id)
176
+ ")
140
177
 
141
178
  if [ -n "$candidate" ]; then
142
- # Update status to running while we have the lock
143
- awk -F',' -v OFS=',' -v id="$candidate" '
144
- NR==1 || $1 != id { print }
145
- $1 == id {
146
- # Preserve existing fields but set status to running
147
- if ($5 == "" || $5 == "pending") $5 = "running"
148
- print
149
- }
150
- ' "$csv_file" > "${csv_file}.tmp" && mv -f "${csv_file}.tmp" "$csv_file"
179
+ mv -f "${csv_file}.tmp" "$csv_file"
151
180
  fi
152
181
 
153
182
  release_csv_lock
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.3.11",
3
+ "version": "1.3.12",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",