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
- # Use CLAUDE_EVOLVE_CONFIG if set, otherwise default
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
- --open Open the generated chart automatically
40
- --csv <path> Path to evolution.csv (default: ./evolution/evolution.csv)
41
- --output <path> Output path for chart PNG (default: ./evolution/performance.png)
42
- --help Show this help message
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.
@@ -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
- for row in rows[start_idx:]:
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
- for i in range(start_idx, len(rows)):
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:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-evolve",
3
- "version": "1.5.13",
3
+ "version": "1.5.15",
4
4
  "bin": {
5
5
  "claude-evolve": "./bin/claude-evolve",
6
6
  "claude-evolve-main": "./bin/claude-evolve-main",