claude-evolve 1.7.5 → 1.7.7
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/bin/claude-evolve-ideate +1 -1
- package/bin/claude-evolve-run +5 -1
- package/lib/config.sh +2 -2
- package/lib/evolution_csv.py +51 -5
- package/package.json +1 -1
package/bin/claude-evolve-ideate
CHANGED
|
@@ -421,7 +421,7 @@ validate_and_apply_csv_modification_old() {
|
|
|
421
421
|
|
|
422
422
|
# Check if the response looks like an error message (but not if it's just CSV data containing these words)
|
|
423
423
|
if echo "$modified_csv" | head -1 | grep -q "id,basedOnId,description,performance,status"; then
|
|
424
|
-
# This looks like a CSV file, not an error message
|
|
424
|
+
: # This looks like a CSV file, not an error message - continue
|
|
425
425
|
elif echo "$modified_csv" | grep -qi "error\|failed\|limit\|exceeded\|sorry\|cannot\|unable"; then
|
|
426
426
|
echo "[ERROR] AI failed to modify CSV and returned an error message:" >&2
|
|
427
427
|
echo "$modified_csv" | head -200 >&2
|
package/bin/claude-evolve-run
CHANGED
|
@@ -409,8 +409,12 @@ try:
|
|
|
409
409
|
from lib.evolution_csv import EvolutionCSV
|
|
410
410
|
|
|
411
411
|
with EvolutionCSV(csv_file) as csv_ops:
|
|
412
|
+
# Auto-fix any corrupted status fields before counting
|
|
413
|
+
fixed = csv_ops.cleanup_corrupted_status_fields()
|
|
414
|
+
if fixed > 0:
|
|
415
|
+
print(f'[INFO] Auto-fixed {fixed} corrupted status field(s)', file=sys.stderr)
|
|
412
416
|
pending = csv_ops.count_pending_candidates()
|
|
413
|
-
|
|
417
|
+
|
|
414
418
|
print(f'[INFO] CSV loaded: {len(rows)-1} total candidates, {pending} pending')
|
|
415
419
|
|
|
416
420
|
except csv.Error as e:
|
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 glm-zai glm-zai glm-zai glm-zai codex-oss-local gemini-flash haiku"
|
|
61
|
+
DEFAULT_LLM_RUN="glm-zai glm-zai glm-zai glm-zai glm-zai codex-oss-local gemini-flash haiku haiku haiku haiku haiku"
|
|
62
62
|
# Ideate: Commercial models for idea generation + local fallback
|
|
63
|
-
DEFAULT_LLM_IDEATE="gemini-pro sonnet-think gpt5high glm-openrouter grok-4-openrouter deepseek-openrouter glm-zai
|
|
63
|
+
DEFAULT_LLM_IDEATE="gemini-pro sonnet-think gpt5high glm-openrouter 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/lib/evolution_csv.py
CHANGED
|
@@ -119,17 +119,26 @@ class EvolutionCSV:
|
|
|
119
119
|
return True # Incomplete row is pending
|
|
120
120
|
|
|
121
121
|
# Check status field (5th column, index 4)
|
|
122
|
-
status
|
|
123
|
-
|
|
122
|
+
# Clean status: remove newlines and control characters, then normalize
|
|
123
|
+
status = row[4].strip() if row[4] else ''
|
|
124
|
+
# Remove any embedded newlines or control characters (CSV corruption)
|
|
125
|
+
status = status.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ')
|
|
126
|
+
status = ' '.join(status.split()).lower() # Normalize whitespace and lowercase
|
|
127
|
+
|
|
124
128
|
# Only blank, missing, or "pending" mean pending
|
|
125
129
|
# "running" should NOT be considered pending to avoid duplicate processing
|
|
126
130
|
if not status or status == 'pending':
|
|
127
131
|
return True
|
|
128
|
-
|
|
132
|
+
|
|
133
|
+
# Handle corrupted status fields that start with "pending"
|
|
134
|
+
# e.g., "pending gen08-013" from CSV corruption
|
|
135
|
+
if status.startswith('pending '):
|
|
136
|
+
return True
|
|
137
|
+
|
|
129
138
|
# Check for retry statuses
|
|
130
139
|
if status.startswith('failed-retry'):
|
|
131
140
|
return True
|
|
132
|
-
|
|
141
|
+
|
|
133
142
|
return False
|
|
134
143
|
|
|
135
144
|
def get_pending_candidates(self) -> List[Tuple[str, str]]:
|
|
@@ -367,7 +376,44 @@ class EvolutionCSV:
|
|
|
367
376
|
self._write_csv(new_rows)
|
|
368
377
|
|
|
369
378
|
return deleted
|
|
370
|
-
|
|
379
|
+
|
|
380
|
+
def cleanup_corrupted_status_fields(self) -> int:
|
|
381
|
+
"""
|
|
382
|
+
Detect and fix corrupted status fields (e.g., with embedded newlines).
|
|
383
|
+
Returns the number of corrupted fields fixed.
|
|
384
|
+
"""
|
|
385
|
+
rows = self._read_csv()
|
|
386
|
+
if not rows:
|
|
387
|
+
return 0
|
|
388
|
+
|
|
389
|
+
fixed_count = 0
|
|
390
|
+
has_header = rows and rows[0] and rows[0][0].lower() == 'id'
|
|
391
|
+
start_idx = 1 if has_header else 0
|
|
392
|
+
|
|
393
|
+
for i in range(start_idx, len(rows)):
|
|
394
|
+
row = rows[i]
|
|
395
|
+
if len(row) >= 5 and row[4]:
|
|
396
|
+
original_status = row[4]
|
|
397
|
+
# Apply the same cleaning logic as is_pending_candidate
|
|
398
|
+
cleaned_status = original_status.strip()
|
|
399
|
+
cleaned_status = cleaned_status.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ')
|
|
400
|
+
cleaned_status = ' '.join(cleaned_status.split())
|
|
401
|
+
|
|
402
|
+
# If status starts with a known status but has garbage after it, fix it
|
|
403
|
+
for valid_status in ['pending', 'running', 'complete', 'failed', 'skipped']:
|
|
404
|
+
if cleaned_status.lower().startswith(valid_status + ' '):
|
|
405
|
+
# Corrupted status found - extract just the valid part
|
|
406
|
+
row[4] = valid_status
|
|
407
|
+
fixed_count += 1
|
|
408
|
+
print(f"[WARN] Fixed corrupted status in row {i}: '{original_status}' -> '{valid_status}'", file=sys.stderr)
|
|
409
|
+
break
|
|
410
|
+
|
|
411
|
+
if fixed_count > 0:
|
|
412
|
+
self._write_csv(rows)
|
|
413
|
+
print(f"[INFO] Fixed {fixed_count} corrupted status field(s)", file=sys.stderr)
|
|
414
|
+
|
|
415
|
+
return fixed_count
|
|
416
|
+
|
|
371
417
|
def has_pending_work(self) -> bool:
|
|
372
418
|
"""Check if there are any pending candidates. Used by dispatcher."""
|
|
373
419
|
return self.count_pending_candidates() > 0
|