prizmkit 1.1.92 → 1.1.94
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/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/.env.example +0 -4
- package/bundled/dev-pipeline/README.md +9 -39
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +0 -4
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +0 -2
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -1
- package/bundled/dev-pipeline/launch-feature-daemon.sh +2 -3
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -1
- package/bundled/dev-pipeline/lib/heartbeat.sh +4 -50
- package/bundled/dev-pipeline/run-bugfix.sh +9 -77
- package/bundled/dev-pipeline/run-feature.sh +8 -94
- package/bundled/dev-pipeline/run-recovery.sh +1 -32
- package/bundled/dev-pipeline/run-refactor.sh +8 -78
- package/bundled/dev-pipeline/tests/test-deploy-safety.sh +3 -3
- package/bundled/dev-pipeline-windows/.env.example +0 -4
- package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -4
- package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -2
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +19 -139
- package/bundled/dev-pipeline-windows/run-recovery.ps1 +4 -19
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +5 -15
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +4 -4
- package/bundled/skills/feature-pipeline-launcher/references/configuration.md +3 -13
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +3 -3
- package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +4 -14
- package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +1 -1
- package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +4 -14
- package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +4 -4
- package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +2 -12
- package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +3 -3
- package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +4 -14
- package/package.json +1 -1
- package/bundled/dev-pipeline/scripts/cleanup-logs.py +0 -192
- package/bundled/dev-pipeline-windows/scripts/cleanup-logs.py +0 -192
package/bundled/VERSION.json
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
|
|
24
24
|
# ─── Pipeline Execution ──────────────────────────────────────────────
|
|
25
25
|
# MAX_RETRIES=3 # Max retry attempts per task before marking failed
|
|
26
|
-
# SESSION_TIMEOUT=0 # Session timeout in seconds (0 = no limit)
|
|
27
26
|
# VERBOSE=1 # Verbose logging (1=on, 0=off)
|
|
28
27
|
|
|
29
28
|
# ─── Feature Pipeline Only ────────────────────────────────────────────
|
|
@@ -45,6 +44,3 @@
|
|
|
45
44
|
# CODEX_WAIT_STALE_KILL_THRESHOLD=3600 # Longer no-log window while Codex waits on subagents
|
|
46
45
|
# CODEX_SUBAGENT_TIMEOUT_SECONDS=3300 # Codex subagent max runtime; defaults to wait threshold - 300
|
|
47
46
|
# CB_SUBAGENT_STALE_KILL_THRESHOLD=3600 # Longer no-log window while CodeBuddy sub-agents are running
|
|
48
|
-
# LOG_CLEANUP_ENABLED=1 # Periodic log cleanup (1=on, 0=off)
|
|
49
|
-
# LOG_RETENTION_DAYS=14 # Delete logs older than N days
|
|
50
|
-
# LOG_MAX_TOTAL_MB=1024 # Keep total logs under N MB via oldest-first cleanup
|
|
@@ -53,7 +53,6 @@ Main entry point. Drives the full feature development pipeline.
|
|
|
53
53
|
| Option | Description |
|
|
54
54
|
|--------|-------------|
|
|
55
55
|
| `--dry-run` | Generate bootstrap prompt only, don't spawn AI session |
|
|
56
|
-
| `--timeout N` | Override `SESSION_TIMEOUT` for this run (seconds) |
|
|
57
56
|
| `--resume-phase N` | Resume from specific phase number |
|
|
58
57
|
| `--no-reset` | Don't reset feature artifacts before running |
|
|
59
58
|
|
|
@@ -71,9 +70,6 @@ Main entry point. Drives the full feature development pipeline.
|
|
|
71
70
|
|
|
72
71
|
# Resume from Phase 6 (implementation)
|
|
73
72
|
./.prizmkit/dev-pipeline/run-feature.sh run .prizmkit/plans/feature-list.json --resume-phase 6
|
|
74
|
-
|
|
75
|
-
# With timeout per session
|
|
76
|
-
SESSION_TIMEOUT=7200 ./.prizmkit/dev-pipeline/run-feature.sh run .prizmkit/plans/feature-list.json
|
|
77
73
|
```
|
|
78
74
|
|
|
79
75
|
If `.prizmkit/plans/feature-list.json` path is omitted, defaults to `.prizmkit/plans/feature-list.json` in the project root.
|
|
@@ -140,7 +136,7 @@ Manages `run-feature.sh` as a background daemon process with PID tracking and lo
|
|
|
140
136
|
```bash
|
|
141
137
|
./.prizmkit/dev-pipeline/launch-feature-daemon.sh start .prizmkit/plans/feature-list.json \
|
|
142
138
|
--mode standard \
|
|
143
|
-
--env "MAX_RETRIES=5
|
|
139
|
+
--env "MAX_RETRIES=5 MODEL=claude-sonnet-4.6"
|
|
144
140
|
```
|
|
145
141
|
|
|
146
142
|
**Output (JSON on stdout for programmatic consumption):**
|
|
@@ -177,7 +173,7 @@ Equivalent to `run-feature.sh` but for the bug-fix pipeline.
|
|
|
177
173
|
./run-bugfix.sh help
|
|
178
174
|
```
|
|
179
175
|
|
|
180
|
-
**Single-bug options:** `--dry-run
|
|
176
|
+
**Single-bug options:** `--dry-run` (same as `run-feature.sh`)
|
|
181
177
|
|
|
182
178
|
Processes bugs by: **severity** (critical > high > medium > low) then **priority** (high > medium > low).
|
|
183
179
|
|
|
@@ -342,7 +338,7 @@ python3 scripts/update-feature-status.py \
|
|
|
342
338
|
| `complete` | `--feature-id` | Shortcut for manually marking completed |
|
|
343
339
|
|
|
344
340
|
**Session status values (for `--session-status`):**
|
|
345
|
-
`success`, `partial_resumable`, `partial_not_resumable`, `failed`, `crashed`, `
|
|
341
|
+
`success`, `partial_resumable`, `partial_not_resumable`, `failed`, `crashed`, `commit_missing`, `docs_missing`, `merge_conflict`
|
|
346
342
|
|
|
347
343
|
**Output (JSON to stdout):**
|
|
348
344
|
|
|
@@ -429,26 +425,6 @@ python3 scripts/detect-stuck.py \
|
|
|
429
425
|
|
|
430
426
|
---
|
|
431
427
|
|
|
432
|
-
### `scripts/cleanup-logs.py` — Log File Cleanup
|
|
433
|
-
|
|
434
|
-
Manages log file size by age and total size thresholds.
|
|
435
|
-
|
|
436
|
-
```bash
|
|
437
|
-
python3 scripts/cleanup-logs.py \
|
|
438
|
-
--state-dir <path> \
|
|
439
|
-
[--retention-days <n>] \
|
|
440
|
-
[--max-total-mb <n>] \
|
|
441
|
-
[--dry-run]
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
| Option | Default | Description |
|
|
445
|
-
|--------|---------|-------------|
|
|
446
|
-
| `--retention-days` | 14 | Delete files older than N days |
|
|
447
|
-
| `--max-total-mb` | 1024 | If total > N MB, remove oldest first |
|
|
448
|
-
| `--dry-run` | false | Show what would be deleted without deleting |
|
|
449
|
-
|
|
450
|
-
---
|
|
451
|
-
|
|
452
428
|
### `scripts/parse-stream-progress.py` — Real-Time Progress Parser
|
|
453
429
|
|
|
454
430
|
Reads AI CLI `stream-json` output and extracts progress metrics.
|
|
@@ -533,7 +509,6 @@ Also exports: `log_info`, `log_warn`, `log_error`, `log_success` (with timestamp
|
|
|
533
509
|
| Variable | Default | Used By | Description |
|
|
534
510
|
|----------|---------|---------|-------------|
|
|
535
511
|
| `MAX_RETRIES` | `3` | run-feature.sh | Max retry attempts per feature before marking as failed |
|
|
536
|
-
| `SESSION_TIMEOUT` | `0` (none) | run-feature.sh, run-bugfix.sh | Timeout in seconds per AI CLI session. 0 = no timeout |
|
|
537
512
|
| `PIPELINE_MODE` | (auto) | run-feature.sh, launch-feature-daemon.sh | Override mode for all features: `lite\|standard\|full` |
|
|
538
513
|
| `ENABLE_CRITIC` | `false` | run-feature.sh, launch-feature-daemon.sh | Enable adversarial critic review: `true\|false` |
|
|
539
514
|
| `DEV_BRANCH` | auto-generated | run-feature.sh | Custom git branch name (default: `dev/{feature-id}-{timestamp}`) |
|
|
@@ -555,21 +530,18 @@ Also exports: `log_info`, `log_warn`, `log_error`, `log_success` (with timestamp
|
|
|
555
530
|
|----------|---------|---------|-------------|
|
|
556
531
|
| `HEARTBEAT_INTERVAL` | `30` | run-feature.sh | Seconds between heartbeat log output |
|
|
557
532
|
| `HEARTBEAT_STALE_THRESHOLD` | `600` | run-feature.sh | Seconds before a session is considered stale/stuck |
|
|
558
|
-
| `LOG_CLEANUP_ENABLED` | `1` | run-feature.sh | Run log cleanup before pipeline execution |
|
|
559
|
-
| `LOG_RETENTION_DAYS` | `14` | run-feature.sh | Delete logs older than N days |
|
|
560
|
-
| `LOG_MAX_TOTAL_MB` | `1024` | run-feature.sh | Keep total log size under N MB |
|
|
561
533
|
|
|
562
534
|
**Examples:**
|
|
563
535
|
|
|
564
536
|
```bash
|
|
565
537
|
# All env vars in one invocation
|
|
566
|
-
MAX_RETRIES=5
|
|
538
|
+
MAX_RETRIES=5 MODEL=claude-sonnet-4.6 VERBOSE=1 \
|
|
567
539
|
./.prizmkit/dev-pipeline/run-feature.sh run .prizmkit/plans/feature-list.json
|
|
568
540
|
|
|
569
541
|
# Via daemon with --env
|
|
570
542
|
./.prizmkit/dev-pipeline/launch-feature-daemon.sh start .prizmkit/plans/feature-list.json \
|
|
571
543
|
--mode standard \
|
|
572
|
-
--env "MAX_RETRIES=5
|
|
544
|
+
--env "MAX_RETRIES=5 AUTO_PUSH=1"
|
|
573
545
|
```
|
|
574
546
|
|
|
575
547
|
---
|
|
@@ -721,11 +693,10 @@ Features are executed in dependency order via DAG:
|
|
|
721
693
|
|
|
722
694
|
1. **Bootstrap prompt** generated from feature spec, context, and acceptance criteria
|
|
723
695
|
2. AI CLI spawned as background process with optional `--model` flag
|
|
724
|
-
3. **
|
|
725
|
-
4. **
|
|
726
|
-
5.
|
|
727
|
-
6.
|
|
728
|
-
7. Feature status updated; on failure, retry count increments
|
|
696
|
+
3. **Heartbeat monitor** prints progress every `HEARTBEAT_INTERVAL` seconds
|
|
697
|
+
4. **Progress parser** (if stream-json supported) extracts phase/tool metrics
|
|
698
|
+
5. On completion, `session-status.json` determines success/failure
|
|
699
|
+
6. Feature status updated; on failure, retry count increments
|
|
729
700
|
|
|
730
701
|
### Heartbeat Output
|
|
731
702
|
|
|
@@ -882,7 +853,6 @@ run-bugfix.sh main loop
|
|
|
882
853
|
| +-- update-feature-status.py # Feature state machine (8 actions)
|
|
883
854
|
| +-- update-bug-status.py # Bug state machine (6 actions)
|
|
884
855
|
| +-- detect-stuck.py # Detect stuck/stale features
|
|
885
|
-
| +-- cleanup-logs.py # Age/size-based log cleanup
|
|
886
856
|
| +-- parse-stream-progress.py # Real-time stream-json progress parser
|
|
887
857
|
|
|
|
888
858
|
+-- templates/
|
|
@@ -344,7 +344,6 @@ pending, in_progress, completed, failed, skipped
|
|
|
344
344
|
| `AI_CLI` | string | auto-detect | claude or cbc |
|
|
345
345
|
| `MODEL` | string | (unset) | AI model override (per-task overrides this) |
|
|
346
346
|
| `MAX_RETRIES` | integer | (not specified) | Retry attempts per task |
|
|
347
|
-
| `SESSION_TIMEOUT` | integer | 0 | 0 = no limit |
|
|
348
347
|
| `VERBOSE` | integer | (not specified) | 1=on, 0=off |
|
|
349
348
|
| `ENABLE_CRITIC` | boolean | false | Adversarial review enable |
|
|
350
349
|
| `PIPELINE_MODE` | string | auto-detect | lite/standard/full override |
|
|
@@ -356,9 +355,6 @@ pending, in_progress, completed, failed, skipped
|
|
|
356
355
|
| `STALE_KILL_THRESHOLD` | integer | 900 | Auto-kill after N seconds without parent log progress |
|
|
357
356
|
| `CODEX_WAIT_STALE_KILL_THRESHOLD` | integer | 3600 | Longer no-log stale window while Codex waits on subagents |
|
|
358
357
|
| `CODEX_SUBAGENT_TIMEOUT_SECONDS` | integer | 3300 | Codex subagent max runtime |
|
|
359
|
-
| `LOG_CLEANUP_ENABLED` | integer | 1 | Periodic cleanup |
|
|
360
|
-
| `LOG_RETENTION_DAYS` | integer | 14 | Delete logs older than N days |
|
|
361
|
-
| `LOG_MAX_TOTAL_MB` | integer | 1024 | Max total logs (MB) |
|
|
362
358
|
|
|
363
359
|
**Priority:** Command-line env vars > .env file > defaults
|
|
364
360
|
|
|
@@ -51,7 +51,6 @@ Located at `.prizmkit/dev-pipeline/scripts/`:
|
|
|
51
51
|
| `check-session-status.py` | Read and validate session-status.json output |
|
|
52
52
|
| `detect-stuck.py` | Detect stuck/hung pipeline sessions via heartbeat |
|
|
53
53
|
| `parse-stream-progress.py` | Parse AI CLI output stream for progress tracking |
|
|
54
|
-
| `cleanup-logs.py` | Clean up old pipeline logs and state files |
|
|
55
54
|
| `utils.py` | Shared utility functions for pipeline scripts |
|
|
56
55
|
|
|
57
56
|
## Artifact Mapping
|
|
@@ -125,7 +124,6 @@ The agent MUST write `session-status.json` before exiting:
|
|
|
125
124
|
| `status: "partial"`, `can_resume: false` | Retry from scratch |
|
|
126
125
|
| `status: "failed"` | Retry (up to MAX_RETRIES) |
|
|
127
126
|
| No status file (crash) | Treat as failed, retry |
|
|
128
|
-
| Timeout (exit 124) | Treat as timed_out, retry |
|
|
129
127
|
|
|
130
128
|
## Team Naming Convention
|
|
131
129
|
|
|
@@ -482,7 +482,6 @@ Examples:
|
|
|
482
482
|
|
|
483
483
|
Environment Variables (pass via --env):
|
|
484
484
|
MAX_RETRIES Max retries per bug (default: 3)
|
|
485
|
-
SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
486
485
|
VERBOSE Set to 1 for verbose AI CLI output
|
|
487
486
|
HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
488
487
|
DEV_BRANCH Custom dev branch name (default: auto-generated)
|
|
@@ -106,7 +106,7 @@ cmd_start() {
|
|
|
106
106
|
--env)
|
|
107
107
|
shift
|
|
108
108
|
if [[ $# -eq 0 ]]; then
|
|
109
|
-
log_error "--env requires a value (e.g. --env \"MAX_RETRIES=5
|
|
109
|
+
log_error "--env requires a value (e.g. --env \"MAX_RETRIES=5\")"
|
|
110
110
|
exit 1
|
|
111
111
|
fi
|
|
112
112
|
env_overrides="$1"
|
|
@@ -609,7 +609,7 @@ Examples:
|
|
|
609
609
|
./launch-feature-daemon.sh start --features F-001,F-003,F-007 # Run specific features
|
|
610
610
|
./launch-feature-daemon.sh start --mode full # Full mode for complex features
|
|
611
611
|
./launch-feature-daemon.sh start --critic # Enable adversarial critic review
|
|
612
|
-
./launch-feature-daemon.sh start --env "MAX_RETRIES=5
|
|
612
|
+
./launch-feature-daemon.sh start --env "MAX_RETRIES=5"
|
|
613
613
|
./launch-feature-daemon.sh start .prizmkit/plans/feature-list.json --mode full --critic --env "VERBOSE=1"
|
|
614
614
|
./launch-feature-daemon.sh status # Check if running (JSON on stdout)
|
|
615
615
|
./launch-feature-daemon.sh logs --follow # Live log tailing
|
|
@@ -619,7 +619,6 @@ Examples:
|
|
|
619
619
|
|
|
620
620
|
Environment Variables (pass via --env):
|
|
621
621
|
MAX_RETRIES Max retries per feature (default: 3)
|
|
622
|
-
SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
623
622
|
VERBOSE Set to 1 for verbose AI CLI output
|
|
624
623
|
HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
625
624
|
DEV_BRANCH Custom dev branch name (default: auto-generated)
|
|
@@ -483,7 +483,6 @@ Examples:
|
|
|
483
483
|
|
|
484
484
|
Environment Variables (pass via --env):
|
|
485
485
|
MAX_RETRIES Max retries per refactor (default: 3)
|
|
486
|
-
SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
487
486
|
VERBOSE Set to 1 for verbose AI CLI output
|
|
488
487
|
STRICT_BEHAVIOR_CHECK Force full test suite after each refactor (default: 1)
|
|
489
488
|
HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
@@ -44,7 +44,6 @@ start_heartbeat() {
|
|
|
44
44
|
local prev_max_size=0
|
|
45
45
|
local prev_child_activity_signature=""
|
|
46
46
|
local prev_progress_signature=""
|
|
47
|
-
local prev_error_loop_signature=""
|
|
48
47
|
local stale_seconds=0
|
|
49
48
|
local stale_reason="stale_session"
|
|
50
49
|
while kill -0 "$cli_pid" 2>/dev/null; do
|
|
@@ -197,64 +196,24 @@ PY
|
|
|
197
196
|
fi
|
|
198
197
|
fi
|
|
199
198
|
|
|
200
|
-
# Check for error-loop: agent is actively producing output but results are
|
|
201
|
-
# all read-offset errors or wasted calls. This is a stuck agent that appears
|
|
202
|
-
# "active" by log growth but is accomplishing nothing. Only a newly advancing
|
|
203
|
-
# error signature counts; stale historical errors must not turn later normal
|
|
204
|
-
# output into a stale kill.
|
|
205
|
-
local error_loop_detected=false
|
|
206
|
-
local error_loop_signature=""
|
|
207
|
-
if [[ $effective_stale_kill_threshold -gt 0 && $growth -gt 0 && -f "$progress_json" ]]; then
|
|
208
|
-
local error_loop_flag
|
|
209
|
-
error_loop_flag=$(python3 - "$progress_json" <<'PY' 2>/dev/null || true
|
|
210
|
-
import json, sys
|
|
211
|
-
try:
|
|
212
|
-
with open(sys.argv[1], encoding="utf-8") as fh:
|
|
213
|
-
progress = json.load(fh)
|
|
214
|
-
except Exception:
|
|
215
|
-
raise SystemExit(0)
|
|
216
|
-
errors = progress.get("errors", [])
|
|
217
|
-
if isinstance(errors, list) and len(errors) >= 5:
|
|
218
|
-
recent = errors[-5:]
|
|
219
|
-
if all(isinstance(e, dict) and e.get("type") in ("read_offset_overflow", "wasted_call") for e in recent):
|
|
220
|
-
print(json.dumps(recent, sort_keys=True, separators=(",", ":")))
|
|
221
|
-
PY
|
|
222
|
-
)
|
|
223
|
-
if [[ -n "$error_loop_flag" ]]; then
|
|
224
|
-
error_loop_signature="$error_loop_flag"
|
|
225
|
-
if [[ -n "$prev_error_loop_signature" && "$error_loop_signature" != "$prev_error_loop_signature" ]]; then
|
|
226
|
-
error_loop_detected=true
|
|
227
|
-
fi
|
|
228
|
-
fi
|
|
229
|
-
fi
|
|
230
|
-
prev_error_loop_signature="$error_loop_signature"
|
|
231
|
-
|
|
232
199
|
# Track progress staleness. Parent sessions can sit in a wait/polling
|
|
233
200
|
# tool while child transcripts or structured progress counters keep
|
|
234
201
|
# advancing, so both child activity and progress.json state changes
|
|
235
|
-
# count as progress.
|
|
236
|
-
# because the log is only growing with repeated failed reads or wasted
|
|
237
|
-
# calls.
|
|
202
|
+
# count as progress.
|
|
238
203
|
#
|
|
239
204
|
# When the main session log has been truncated (e.g. by subagent stdout
|
|
240
205
|
# redirection severing the file descriptor), use structured progress and
|
|
241
206
|
# child activity as the primary progress signals — the parent process is
|
|
242
207
|
# still running and children may still be producing output.
|
|
243
|
-
if [[ "$
|
|
244
|
-
stale_reason="error_loop"
|
|
245
|
-
stale_seconds=$effective_stale_kill_threshold
|
|
246
|
-
elif [[ "$log_truncated" == "true" ]]; then
|
|
247
|
-
stale_reason="stale_session"
|
|
208
|
+
if [[ "$log_truncated" == "true" ]]; then
|
|
248
209
|
if [[ $progress_advanced -gt 0 || $child_growth -gt 0 ]]; then
|
|
249
210
|
stale_seconds=0
|
|
250
211
|
else
|
|
251
212
|
stale_seconds=$((stale_seconds + heartbeat_interval))
|
|
252
213
|
fi
|
|
253
214
|
elif [[ $growth -le 0 && $child_growth -eq 0 && $progress_advanced -eq 0 ]]; then
|
|
254
|
-
stale_reason="stale_session"
|
|
255
215
|
stale_seconds=$((stale_seconds + heartbeat_interval))
|
|
256
216
|
else
|
|
257
|
-
stale_reason="stale_session"
|
|
258
217
|
stale_seconds=0
|
|
259
218
|
fi
|
|
260
219
|
|
|
@@ -338,13 +297,8 @@ PY
|
|
|
338
297
|
# stale window to surface stuck agents promptly.
|
|
339
298
|
if [[ $effective_stale_kill_threshold -gt 0 && $stale_seconds -ge $effective_stale_kill_threshold ]]; then
|
|
340
299
|
local stale_mins=$((stale_seconds / 60))
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
echo -e " ${RED}[HEARTBEAT]${NC} Killing AI CLI process $cli_pid (error loop)..."
|
|
344
|
-
else
|
|
345
|
-
echo -e " ${RED}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${RED}STALE-KILL: no progress for ${stale_mins}m (threshold: ${effective_stale_kill_threshold}s)${NC}"
|
|
346
|
-
echo -e " ${RED}[HEARTBEAT]${NC} Killing AI CLI process $cli_pid (stale session)..."
|
|
347
|
-
fi
|
|
300
|
+
echo -e " ${RED}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${RED}STALE-KILL: no progress for ${stale_mins}m (threshold: ${effective_stale_kill_threshold}s)${NC}"
|
|
301
|
+
echo -e " ${RED}[HEARTBEAT]${NC} Killing AI CLI process $cli_pid (stale session)..."
|
|
348
302
|
# Write the marker before killing. Some CLIs exit quickly, and the
|
|
349
303
|
# parent runner may stop this heartbeat process immediately after
|
|
350
304
|
# wait(1) returns.
|
|
@@ -16,7 +16,6 @@ set -euo pipefail
|
|
|
16
16
|
# Environment Variables:
|
|
17
17
|
# MAX_RETRIES Max code retries per bug (default: 3)
|
|
18
18
|
# MAX_INFRA_RETRIES Max infrastructure/provider retries per bug (default: 3)
|
|
19
|
-
# SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
20
19
|
# AI_CLI AI CLI command name (auto-detected: cbc, claude, or codex)
|
|
21
20
|
# CODEBUDDY_CLI Legacy alias for AI_CLI (deprecated, use AI_CLI instead)
|
|
22
21
|
# PRIZMKIT_PLATFORM Platform hint for custom AI_CLI wrappers: codebuddy, claude, or codex
|
|
@@ -24,9 +23,6 @@ set -euo pipefail
|
|
|
24
23
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
25
24
|
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
26
25
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
27
|
-
# LOG_CLEANUP_ENABLED Run periodic log cleanup (default: 1)
|
|
28
|
-
# LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
|
|
29
|
-
# LOG_MAX_TOTAL_MB Keep total logs under N MB via oldest-first cleanup (default: 1024)
|
|
30
26
|
# DEV_BRANCH Custom dev branch name (default: auto-generated bugfix/pipeline-{run_id})
|
|
31
27
|
# AUTO_PUSH Auto-push to remote after successful bug fix (default: 0). Set to 1 to enable.
|
|
32
28
|
# STOP_ON_FAILURE Stop pipeline after a task exhausts all retries (default: 0). Set to 1 to stop.
|
|
@@ -44,13 +40,9 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
|
44
40
|
# Configuration
|
|
45
41
|
MAX_RETRIES=${MAX_RETRIES:-3}
|
|
46
42
|
MAX_INFRA_RETRIES=${MAX_INFRA_RETRIES:-3}
|
|
47
|
-
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
48
43
|
HEARTBEAT_STALE_THRESHOLD=${HEARTBEAT_STALE_THRESHOLD:-600}
|
|
49
44
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
50
45
|
STALE_KILL_THRESHOLD=${STALE_KILL_THRESHOLD:-900}
|
|
51
|
-
LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
|
|
52
|
-
LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
|
|
53
|
-
LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
|
|
54
46
|
VERBOSE=${VERBOSE:-0}
|
|
55
47
|
MODEL=${MODEL:-""}
|
|
56
48
|
PRIZMKIT_EFFORT=${PRIZMKIT_EFFORT:-""}
|
|
@@ -117,13 +109,6 @@ spawn_and_wait_session() {
|
|
|
117
109
|
start_progress_parser "$session_log" "$progress_json" "$SCRIPTS_DIR"
|
|
118
110
|
local parser_pid="${_PARSER_PID:-}"
|
|
119
111
|
|
|
120
|
-
# Timeout watchdog
|
|
121
|
-
local watcher_pid=""
|
|
122
|
-
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
123
|
-
( sleep "$SESSION_TIMEOUT" && kill -TERM "$cli_pid" 2>/dev/null ) &
|
|
124
|
-
watcher_pid=$!
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
112
|
# Heartbeat monitor (with stale-kill protection)
|
|
128
113
|
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL" "$STALE_KILL_THRESHOLD"
|
|
129
114
|
local heartbeat_pid="${_HEARTBEAT_PID:-}"
|
|
@@ -136,16 +121,13 @@ spawn_and_wait_session() {
|
|
|
136
121
|
exit_code=$?
|
|
137
122
|
fi
|
|
138
123
|
|
|
139
|
-
#
|
|
140
|
-
[[ -n "$watcher_pid" ]] && kill "$watcher_pid" 2>/dev/null || true
|
|
124
|
+
# Clean up heartbeat and parser
|
|
141
125
|
stop_heartbeat "$heartbeat_pid"
|
|
142
126
|
stop_progress_parser "$parser_pid"
|
|
143
|
-
[[ -n "$watcher_pid" ]] && wait "$watcher_pid" 2>/dev/null || true
|
|
144
127
|
|
|
145
128
|
# Recover session log from backup if truncated by subagent stdout redirection
|
|
146
129
|
prizm_recover_session_log "$session_log"
|
|
147
130
|
|
|
148
|
-
[[ $exit_code -eq 143 ]] && exit_code=124
|
|
149
131
|
|
|
150
132
|
# Check for stale-kill marker (heartbeat killed the process due to no progress)
|
|
151
133
|
local stale_kill_marker="$session_dir/logs/stale-kill.json"
|
|
@@ -162,11 +144,7 @@ except Exception:
|
|
|
162
144
|
pass
|
|
163
145
|
PY
|
|
164
146
|
)
|
|
165
|
-
|
|
166
|
-
log_warn "Session was killed by heartbeat monitor due to repeated read-offset/wasted-call errors"
|
|
167
|
-
else
|
|
168
|
-
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
169
|
-
fi
|
|
147
|
+
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
170
148
|
fi
|
|
171
149
|
|
|
172
150
|
local was_infra_error=false
|
|
@@ -192,19 +170,12 @@ PY
|
|
|
192
170
|
project_root="$PROJECT_ROOT"
|
|
193
171
|
local default_branch="$base_branch"
|
|
194
172
|
|
|
195
|
-
if [[ $
|
|
196
|
-
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
197
|
-
session_status="timed_out"
|
|
198
|
-
elif [[ "$was_infra_error" == true ]]; then
|
|
173
|
+
if [[ "$was_infra_error" == true ]]; then
|
|
199
174
|
log_warn "Session failed due to AI CLI/provider infrastructure error"
|
|
200
175
|
log_warn "Infrastructure errors are retried without consuming code retry budget"
|
|
201
176
|
session_status="infra_error"
|
|
202
177
|
elif [[ "$was_stale_killed" == true ]]; then
|
|
203
|
-
|
|
204
|
-
log_warn "Session killed due to repeated read-offset/wasted-call error loop"
|
|
205
|
-
else
|
|
206
|
-
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
207
|
-
fi
|
|
178
|
+
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
208
179
|
log_warn "Stale-killed sessions are treated as failed; dev branch is preserved for inspection"
|
|
209
180
|
session_status="crashed"
|
|
210
181
|
elif [[ $exit_code -ne 0 ]]; then
|
|
@@ -399,28 +370,6 @@ check_dependencies() {
|
|
|
399
370
|
prizm_ensure_git_repo "$_project_root"
|
|
400
371
|
}
|
|
401
372
|
|
|
402
|
-
run_log_cleanup() {
|
|
403
|
-
if [[ "$LOG_CLEANUP_ENABLED" != "1" ]]; then
|
|
404
|
-
return 0
|
|
405
|
-
fi
|
|
406
|
-
|
|
407
|
-
local cleanup_result
|
|
408
|
-
cleanup_result=$(python3 "$SCRIPTS_DIR/cleanup-logs.py" \
|
|
409
|
-
--state-dir "$STATE_DIR" \
|
|
410
|
-
--retention-days "$LOG_RETENTION_DAYS" \
|
|
411
|
-
--max-total-mb "$LOG_MAX_TOTAL_MB" 2>/dev/null) || {
|
|
412
|
-
log_warn "Log cleanup failed (continuing)"
|
|
413
|
-
return 0
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
local deleted reclaimed_kb
|
|
417
|
-
deleted=$(echo "$cleanup_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('deleted_files', 0))" 2>/dev/null || echo "0")
|
|
418
|
-
reclaimed_kb=$(echo "$cleanup_result" | python3 -c "import sys,json; print(int(json.load(sys.stdin).get('reclaimed_bytes', 0)/1024))" 2>/dev/null || echo "0")
|
|
419
|
-
|
|
420
|
-
if [[ "$deleted" -gt 0 ]]; then
|
|
421
|
-
log_info "Log cleanup: deleted $deleted files, reclaimed ${reclaimed_kb}KB"
|
|
422
|
-
fi
|
|
423
|
-
}
|
|
424
373
|
|
|
425
374
|
# ============================================================
|
|
426
375
|
# run-one: Run a single bug fix
|
|
@@ -440,7 +389,6 @@ run_one() {
|
|
|
440
389
|
--dry-run) dry_run=true; shift ;;
|
|
441
390
|
--clean) do_clean=true; shift ;;
|
|
442
391
|
--no-reset) no_reset=true; shift ;;
|
|
443
|
-
--timeout) shift; SESSION_TIMEOUT="${1:-0}"; shift ;;
|
|
444
392
|
--max-infra-retries)
|
|
445
393
|
shift
|
|
446
394
|
if [[ $# -eq 0 ]]; then
|
|
@@ -491,7 +439,6 @@ run_one() {
|
|
|
491
439
|
fi
|
|
492
440
|
|
|
493
441
|
check_dependencies
|
|
494
|
-
run_log_cleanup
|
|
495
442
|
|
|
496
443
|
# Initialize state if needed
|
|
497
444
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
@@ -877,7 +824,6 @@ main() {
|
|
|
877
824
|
fi
|
|
878
825
|
|
|
879
826
|
check_dependencies
|
|
880
|
-
run_log_cleanup
|
|
881
827
|
|
|
882
828
|
# Initialize pipeline state if needed
|
|
883
829
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
@@ -926,11 +872,6 @@ main() {
|
|
|
926
872
|
log_info "Bug fix list: $bug_list"
|
|
927
873
|
log_info "Max code retries per bug: $MAX_RETRIES"
|
|
928
874
|
log_info "Max infrastructure retries per bug: $MAX_INFRA_RETRIES"
|
|
929
|
-
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
930
|
-
log_info "Session timeout: ${SESSION_TIMEOUT}s"
|
|
931
|
-
else
|
|
932
|
-
log_info "Session timeout: none"
|
|
933
|
-
fi
|
|
934
875
|
log_info "AI CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
935
876
|
if [[ -n "${MODEL:-}" ]]; then
|
|
936
877
|
log_info "Default Model: $MODEL"
|
|
@@ -1077,17 +1018,14 @@ DEPLOY_PROMPT_EOF
|
|
|
1077
1018
|
fi
|
|
1078
1019
|
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
1079
1020
|
|
|
1080
|
-
#
|
|
1081
|
-
#
|
|
1082
|
-
# submodule dirt, specs, and root-level hidden tool temporary worktrees
|
|
1083
|
-
# must never be swept into main by a broad git add.
|
|
1021
|
+
# Auto-commit any uncommitted workspace changes before starting the pipeline.
|
|
1022
|
+
# This ensures a clean baseline without blocking execution.
|
|
1084
1023
|
local _dirty_files=""
|
|
1085
1024
|
_dirty_files=$(prizm_git_status_non_bookkeeping "$_proj_root" "$STATE_DIR" "$bug_list" || true)
|
|
1086
1025
|
if [[ -n "$_dirty_files" ]]; then
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
break
|
|
1026
|
+
log_info "Auto-committing workspace changes before $bug_id..."
|
|
1027
|
+
prizm_git_add_all_safe "$_proj_root"
|
|
1028
|
+
git -C "$_proj_root" commit --no-verify -m "chore: workspace snapshot ready for run $bug_id" 2>/dev/null || true
|
|
1091
1029
|
fi
|
|
1092
1030
|
|
|
1093
1031
|
local _bookkeeping_dirty=""
|
|
@@ -1280,7 +1218,6 @@ show_help() {
|
|
|
1280
1218
|
echo " --dry-run Generate bootstrap prompt only, don't spawn session"
|
|
1281
1219
|
echo " --clean Delete artifacts and reset before running"
|
|
1282
1220
|
echo " --no-reset Skip status reset (preserve retry count)"
|
|
1283
|
-
echo " --timeout N Session timeout in seconds (default: 0 = no limit)"
|
|
1284
1221
|
echo " --max-infra-retries N Max infrastructure/provider retries (default: 3)"
|
|
1285
1222
|
echo " --mode <lite|standard|full> Override pipeline mode"
|
|
1286
1223
|
echo " --critic Enable adversarial critic review"
|
|
@@ -1292,7 +1229,6 @@ show_help() {
|
|
|
1292
1229
|
echo "Environment Variables:"
|
|
1293
1230
|
echo " MAX_RETRIES Max code retries per bug (default: 3)"
|
|
1294
1231
|
echo " MAX_INFRA_RETRIES Max infrastructure/provider retries per bug (default: 3)"
|
|
1295
|
-
echo " SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)"
|
|
1296
1232
|
echo " MODEL Default AI model (overridden by per-bug model in bug list)"
|
|
1297
1233
|
echo " PRIZMKIT_EFFORT AI reasoning effort (low|medium|high|xhigh|max; max is Claude Code only)"
|
|
1298
1234
|
echo " PIPELINE_MODE Default pipeline mode: lite|standard|full (overridden by --mode)"
|
|
@@ -1302,9 +1238,6 @@ show_help() {
|
|
|
1302
1238
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1303
1239
|
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1304
1240
|
echo " STOP_ON_FAILURE Stop pipeline when a task exhausts retries: 0|1 (default: 0)"
|
|
1305
|
-
echo " LOG_CLEANUP_ENABLED Run log cleanup before execution (default: 1)"
|
|
1306
|
-
echo " LOG_RETENTION_DAYS Delete logs older than N days (default: 14)"
|
|
1307
|
-
echo " LOG_MAX_TOTAL_MB Keep total logs under N MB (default: 1024)"
|
|
1308
1241
|
echo ""
|
|
1309
1242
|
echo "Examples:"
|
|
1310
1243
|
echo " ./run-bugfix.sh run # Run all bugs"
|
|
@@ -1312,7 +1245,6 @@ show_help() {
|
|
|
1312
1245
|
echo " ./run-bugfix.sh run B-001 --dry-run # Inspect generated prompt"
|
|
1313
1246
|
echo " ./run-bugfix.sh run B-001 --clean # Clean artifacts + reset + run"
|
|
1314
1247
|
echo " ./run-bugfix.sh run B-001 --no-reset # Retry without resetting status"
|
|
1315
|
-
echo " ./run-bugfix.sh run B-001 --timeout 3600 # 1h timeout"
|
|
1316
1248
|
echo " ./run-bugfix.sh status # Show status"
|
|
1317
1249
|
echo " MAX_RETRIES=5 ./run-bugfix.sh run # Custom retries"
|
|
1318
1250
|
}
|