claude-evolve 1.5.13 → 1.5.15
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.
|
@@ -7,9 +7,44 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
7
7
|
# shellcheck source=../lib/config.sh
|
|
8
8
|
source "$SCRIPT_DIR/../lib/config.sh"
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# Parse working directory before other arguments
|
|
11
|
+
WORKING_DIR=""
|
|
12
|
+
args=()
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case $1 in
|
|
15
|
+
--working-dir)
|
|
16
|
+
if [[ -z ${2:-} ]]; then
|
|
17
|
+
echo "[ERROR] --working-dir requires a directory path" >&2
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
WORKING_DIR="$2"
|
|
21
|
+
shift 2
|
|
22
|
+
;;
|
|
23
|
+
--working-dir=*)
|
|
24
|
+
WORKING_DIR="${1#*=}"
|
|
25
|
+
shift
|
|
26
|
+
;;
|
|
27
|
+
*)
|
|
28
|
+
args+=("$1")
|
|
29
|
+
shift
|
|
30
|
+
;;
|
|
31
|
+
esac
|
|
32
|
+
done
|
|
33
|
+
set -- "${args[@]}"
|
|
34
|
+
|
|
35
|
+
# Auto-detect config.yaml in current directory if --working-dir not specified
|
|
36
|
+
if [[ -z $WORKING_DIR ]] && [[ -f "config.yaml" ]]; then
|
|
37
|
+
WORKING_DIR="."
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Use CLAUDE_EVOLVE_CONFIG if set, otherwise use working dir or default
|
|
11
41
|
if [[ -n ${CLAUDE_EVOLVE_CONFIG:-} ]]; then
|
|
12
42
|
load_config "$CLAUDE_EVOLVE_CONFIG"
|
|
43
|
+
elif [[ -n $WORKING_DIR ]]; then
|
|
44
|
+
# Remove trailing slash if present
|
|
45
|
+
WORKING_DIR="${WORKING_DIR%/}"
|
|
46
|
+
CONFIG_FILE="$WORKING_DIR/config.yaml"
|
|
47
|
+
load_config "$CONFIG_FILE"
|
|
13
48
|
else
|
|
14
49
|
# Check if config.yaml exists in current directory
|
|
15
50
|
if [[ -f "config.yaml" ]]; then
|
|
@@ -33,13 +68,14 @@ while [[ $# -gt 0 ]]; do
|
|
|
33
68
|
claude-evolve analyze - Analyze evolution results
|
|
34
69
|
|
|
35
70
|
USAGE:
|
|
36
|
-
claude-evolve analyze [--open] [--csv <path>] [--output <path>]
|
|
71
|
+
claude-evolve analyze [--working-dir <path>] [--open] [--csv <path>] [--output <path>]
|
|
37
72
|
|
|
38
73
|
OPTIONS:
|
|
39
|
-
--
|
|
40
|
-
--
|
|
41
|
-
--
|
|
42
|
-
--
|
|
74
|
+
--working-dir <path> Use alternate working directory (default: current or evolution/)
|
|
75
|
+
--open Open the generated chart automatically
|
|
76
|
+
--csv <path> Path to evolution.csv (default: <working-dir>/evolution.csv)
|
|
77
|
+
--output <path> Output path for chart PNG (default: <working-dir>/performance.png)
|
|
78
|
+
--help Show this help message
|
|
43
79
|
|
|
44
80
|
DESCRIPTION:
|
|
45
81
|
Analyzes the evolution.csv file and generates a performance chart.
|
|
Binary file
|
package/lib/evolution_csv.py
CHANGED
|
@@ -133,19 +133,21 @@ class EvolutionCSV:
|
|
|
133
133
|
return False
|
|
134
134
|
|
|
135
135
|
def get_pending_candidates(self) -> List[Tuple[str, str]]:
|
|
136
|
-
"""Get list of pending candidate IDs and their current status."""
|
|
136
|
+
"""Get list of pending candidate IDs and their current status (in reverse order)."""
|
|
137
137
|
rows = self._read_csv()
|
|
138
138
|
pending = []
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
# Skip header row if it exists
|
|
141
141
|
start_idx = 1 if rows and rows[0] and rows[0][0].lower() == 'id' else 0
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
|
|
143
|
+
# Process in reverse order to match get_next_pending_candidate
|
|
144
|
+
for i in range(len(rows) - 1, start_idx - 1, -1):
|
|
145
|
+
row = rows[i]
|
|
144
146
|
if self.is_pending_candidate(row):
|
|
145
147
|
candidate_id = row[0].strip()
|
|
146
148
|
current_status = row[4].strip() if len(row) > 4 else ''
|
|
147
149
|
pending.append((candidate_id, current_status))
|
|
148
|
-
|
|
150
|
+
|
|
149
151
|
return pending
|
|
150
152
|
|
|
151
153
|
def count_pending_candidates(self) -> int:
|
|
@@ -156,33 +158,35 @@ class EvolutionCSV:
|
|
|
156
158
|
"""
|
|
157
159
|
Get the next pending candidate and mark it as 'running'.
|
|
158
160
|
Returns (candidate_id, original_status) or None if no pending work.
|
|
161
|
+
Processes candidates in REVERSE order (from end to beginning).
|
|
159
162
|
"""
|
|
160
163
|
rows = self._read_csv()
|
|
161
164
|
if not rows:
|
|
162
165
|
return None
|
|
163
|
-
|
|
166
|
+
|
|
164
167
|
# Skip header row if it exists
|
|
165
168
|
start_idx = 1 if rows and rows[0] and rows[0][0].lower() == 'id' else 0
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
|
|
170
|
+
# Process in reverse order - from last row to first data row
|
|
171
|
+
for i in range(len(rows) - 1, start_idx - 1, -1):
|
|
168
172
|
row = rows[i]
|
|
169
|
-
|
|
173
|
+
|
|
170
174
|
if self.is_pending_candidate(row):
|
|
171
175
|
candidate_id = row[0].strip()
|
|
172
176
|
original_status = row[4].strip() if len(row) > 4 else ''
|
|
173
|
-
|
|
177
|
+
|
|
174
178
|
# Ensure row has at least 5 columns
|
|
175
179
|
while len(row) < 5:
|
|
176
180
|
row.append('')
|
|
177
|
-
|
|
181
|
+
|
|
178
182
|
# Mark as running
|
|
179
183
|
row[4] = 'running'
|
|
180
|
-
|
|
184
|
+
|
|
181
185
|
# Write back to CSV
|
|
182
186
|
self._write_csv(rows)
|
|
183
|
-
|
|
187
|
+
|
|
184
188
|
return (candidate_id, original_status)
|
|
185
|
-
|
|
189
|
+
|
|
186
190
|
return None
|
|
187
191
|
|
|
188
192
|
def update_candidate_status(self, candidate_id: str, new_status: str) -> bool:
|