prizmkit 1.1.8 → 1.1.10
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/adapters/codebuddy/skill-adapter.js +21 -7
- package/bundled/agents/prizm-dev-team-reviewer.md +53 -173
- package/bundled/dev-pipeline/.env.example +45 -0
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +535 -0
- package/bundled/dev-pipeline/assets/feature-list-example.json +0 -1
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +57 -12
- package/bundled/dev-pipeline/launch-feature-daemon.sh +3 -1
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +57 -12
- package/bundled/dev-pipeline/lib/branch.sh +6 -1
- package/bundled/dev-pipeline/lib/common.sh +71 -0
- package/bundled/dev-pipeline/lib/heartbeat.sh +2 -2
- package/bundled/dev-pipeline/retry-bugfix.sh +60 -23
- package/bundled/dev-pipeline/retry-feature.sh +47 -12
- package/bundled/dev-pipeline/retry-refactor.sh +105 -23
- package/bundled/dev-pipeline/run-bugfix.sh +265 -44
- package/bundled/dev-pipeline/run-feature.sh +35 -1
- package/bundled/dev-pipeline/run-refactor.sh +376 -51
- package/bundled/dev-pipeline/scripts/check-session-status.py +24 -1
- package/bundled/dev-pipeline/scripts/detect-stuck.py +195 -85
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +31 -19
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +19 -3
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +98 -11
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +30 -5
- package/bundled/dev-pipeline/scripts/init-pipeline.py +3 -3
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +15 -4
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +1 -5
- package/bundled/dev-pipeline/scripts/patch-completion-notes.py +191 -0
- package/bundled/dev-pipeline/scripts/update-bug-status.py +159 -14
- package/bundled/dev-pipeline/scripts/update-feature-status.py +79 -37
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +343 -13
- package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +1 -1
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +7 -11
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +41 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +27 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +43 -19
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +54 -26
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +5 -14
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +36 -25
- package/bundled/dev-pipeline/templates/feature-list-schema.json +23 -11
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +270 -0
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +10 -2
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +3 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +1 -0
- package/bundled/dev-pipeline/templates/sections/feature-context.md +2 -0
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +29 -2
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +22 -0
- package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +8 -6
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +7 -5
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -3
- package/bundled/skills/_metadata.json +5 -22
- package/bundled/skills/app-planner/SKILL.md +92 -66
- package/bundled/skills/app-planner/assets/app-design-guide.md +1 -1
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -1
- package/bundled/skills/app-planner/references/project-brief-guide.md +69 -66
- package/bundled/skills/bug-fix-workflow/SKILL.md +47 -4
- package/bundled/skills/bug-planner/SKILL.md +130 -188
- package/bundled/skills/bug-planner/assets/bug-confirmation-template.md +43 -0
- package/bundled/skills/bug-planner/references/critic-and-verification.md +44 -0
- package/bundled/skills/bug-planner/references/error-recovery.md +73 -0
- package/bundled/skills/bug-planner/references/input-formats.md +53 -0
- package/bundled/skills/bug-planner/references/schema-validation.md +25 -0
- package/bundled/skills/bug-planner/references/severity-rules.md +16 -0
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +1 -5
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +5 -10
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +16 -3
- package/bundled/skills/feature-planner/SKILL.md +33 -122
- package/bundled/skills/feature-planner/assets/evaluation-guide.md +1 -1
- package/bundled/skills/feature-planner/assets/planning-guide.md +21 -5
- package/bundled/skills/feature-planner/references/browser-interaction.md +2 -4
- package/bundled/skills/feature-planner/references/completeness-review.md +57 -0
- package/bundled/skills/feature-planner/references/error-recovery.md +15 -34
- package/bundled/skills/feature-planner/references/incremental-feature-planning.md +1 -1
- package/bundled/skills/feature-planner/references/new-project-planning.md +2 -2
- package/bundled/skills/feature-planner/scripts/validate-and-generate.py +1 -2
- package/bundled/skills/feature-workflow/SKILL.md +3 -4
- package/bundled/skills/prizm-kit/SKILL.md +39 -49
- package/bundled/skills/prizmkit-code-review/SKILL.md +51 -64
- package/bundled/skills/prizmkit-code-review/rules/dimensions.md +85 -0
- package/bundled/skills/prizmkit-code-review/rules/fix-strategy.md +11 -11
- package/bundled/skills/prizmkit-committer/SKILL.md +3 -31
- package/bundled/skills/prizmkit-deploy/SKILL.md +34 -31
- package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +1 -1
- package/bundled/skills/prizmkit-implement/SKILL.md +35 -68
- package/bundled/skills/prizmkit-init/SKILL.md +112 -65
- package/bundled/skills/prizmkit-init/assets/project-brief-template.md +82 -0
- package/bundled/skills/prizmkit-plan/SKILL.md +120 -79
- package/bundled/skills/prizmkit-plan/assets/plan-template.md +28 -18
- package/bundled/skills/prizmkit-plan/assets/spec-template.md +28 -11
- package/bundled/skills/prizmkit-plan/references/clarify-guide.md +3 -3
- package/bundled/skills/prizmkit-plan/references/verification-checklist.md +60 -0
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +10 -81
- package/bundled/skills/prizmkit-prizm-docs/assets/{PRIZM-SPEC.md → prizm-docs-format.md} +41 -526
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +46 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +16 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +14 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +19 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +17 -0
- package/bundled/skills/prizmkit-retrospective/SKILL.md +27 -65
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -4
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +7 -25
- package/bundled/skills/recovery-workflow/SKILL.md +8 -8
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +17 -9
- package/bundled/skills/refactor-planner/SKILL.md +23 -41
- package/bundled/skills/refactor-workflow/SKILL.md +1 -2
- package/bundled/team/prizm-dev-team.json +1 -1
- package/bundled/{skills/prizm-kit/assets → templates}/project-memory-template.md +1 -1
- package/package.json +1 -1
- package/src/clean.js +0 -1
- package/src/gitignore-template.js +0 -1
- package/src/scaffold.js +10 -3
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-analyze.md +0 -5
- package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +0 -19
- package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +0 -19
- package/bundled/skills/app-planner/references/project-conventions.md +0 -93
- package/bundled/skills/prizmkit-analyze/SKILL.md +0 -207
- package/bundled/skills/prizmkit-code-review/rules/dimensions-bugfix.md +0 -25
- package/bundled/skills/prizmkit-code-review/rules/dimensions-feature.md +0 -43
- package/bundled/skills/prizmkit-code-review/rules/dimensions-refactor.md +0 -25
- package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +0 -69
- package/bundled/skills/prizmkit-verify/SKILL.md +0 -281
- package/bundled/skills/prizmkit-verify/scripts/verify-light.py +0 -402
|
@@ -8,11 +8,11 @@ set -euo pipefail
|
|
|
8
8
|
# log consolidation, and lifecycle commands.
|
|
9
9
|
#
|
|
10
10
|
# Usage:
|
|
11
|
-
# ./launch-bugfix-daemon.sh start [.prizmkit/plans/bug-fix-list.json] [--env "KEY=VAL ..."]
|
|
11
|
+
# ./launch-bugfix-daemon.sh start [.prizmkit/plans/bug-fix-list.json] [--mode <mode>] [--critic] [--env "KEY=VAL ..."]
|
|
12
12
|
# ./launch-bugfix-daemon.sh stop
|
|
13
13
|
# ./launch-bugfix-daemon.sh status
|
|
14
14
|
# ./launch-bugfix-daemon.sh logs [--lines N] [--follow]
|
|
15
|
-
# ./launch-bugfix-daemon.sh restart [.prizmkit/plans/bug-fix-list.json] [--env "KEY=VAL ..."]
|
|
15
|
+
# ./launch-bugfix-daemon.sh restart [.prizmkit/plans/bug-fix-list.json] [--mode <mode>] [--critic] [--env "KEY=VAL ..."]
|
|
16
16
|
#
|
|
17
17
|
# NOTE:
|
|
18
18
|
# In AI skill sessions, always use this daemon wrapper.
|
|
@@ -93,6 +93,31 @@ cmd_start() {
|
|
|
93
93
|
while [[ $# -gt 0 ]]; do
|
|
94
94
|
case "$1" in
|
|
95
95
|
--env) shift; env_overrides="${1:-}"; shift ;;
|
|
96
|
+
--mode)
|
|
97
|
+
shift
|
|
98
|
+
if [[ $# -eq 0 ]]; then
|
|
99
|
+
log_error "--mode requires a value (lite|standard|full)"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
case "$1" in
|
|
103
|
+
lite|standard|full)
|
|
104
|
+
PIPELINE_MODE="$1"
|
|
105
|
+
;;
|
|
106
|
+
*)
|
|
107
|
+
log_error "Invalid mode: $1 (must be lite, standard, or full)"
|
|
108
|
+
exit 1
|
|
109
|
+
;;
|
|
110
|
+
esac
|
|
111
|
+
shift
|
|
112
|
+
;;
|
|
113
|
+
--critic)
|
|
114
|
+
ENABLE_CRITIC=true
|
|
115
|
+
shift
|
|
116
|
+
;;
|
|
117
|
+
--no-critic)
|
|
118
|
+
ENABLE_CRITIC=false
|
|
119
|
+
shift
|
|
120
|
+
;;
|
|
96
121
|
*) bug_list="$1"; shift ;;
|
|
97
122
|
esac
|
|
98
123
|
done
|
|
@@ -166,6 +191,9 @@ cmd_start() {
|
|
|
166
191
|
echo ""
|
|
167
192
|
} >> "$LOG_FILE"
|
|
168
193
|
|
|
194
|
+
[[ -n "${PIPELINE_MODE:-}" ]] && export PIPELINE_MODE
|
|
195
|
+
[[ -n "${ENABLE_CRITIC:-}" ]] && export ENABLE_CRITIC
|
|
196
|
+
|
|
169
197
|
if [[ -n "$env_cmd" ]]; then
|
|
170
198
|
nohup $env_cmd "$RUN_SCRIPT" run "$bug_list" >> "$LOG_FILE" 2>&1 &
|
|
171
199
|
else
|
|
@@ -174,11 +202,12 @@ cmd_start() {
|
|
|
174
202
|
local pipeline_pid=$!
|
|
175
203
|
disown "$pipeline_pid" 2>/dev/null || true
|
|
176
204
|
|
|
177
|
-
echo "$pipeline_pid" > "$PID_FILE"
|
|
205
|
+
echo "$pipeline_pid" > "${PID_FILE}.tmp"
|
|
206
|
+
mv "${PID_FILE}.tmp" "$PID_FILE"
|
|
178
207
|
|
|
208
|
+
# Write start metadata (atomic)
|
|
179
209
|
python3 -c "
|
|
180
|
-
import json
|
|
181
|
-
from datetime import datetime
|
|
210
|
+
import json, os
|
|
182
211
|
data = {
|
|
183
212
|
'pid': $pipeline_pid,
|
|
184
213
|
'pipeline_type': 'bugfix',
|
|
@@ -187,8 +216,11 @@ data = {
|
|
|
187
216
|
'env_overrides': '$env_overrides',
|
|
188
217
|
'log_file': '$LOG_FILE'
|
|
189
218
|
}
|
|
190
|
-
|
|
219
|
+
target = os.path.join('$STATE_DIR', '.pipeline-meta.json')
|
|
220
|
+
tmp = target + '.tmp'
|
|
221
|
+
with open(tmp, 'w') as f:
|
|
191
222
|
json.dump(data, f, indent=2)
|
|
223
|
+
os.replace(tmp, target)
|
|
192
224
|
" 2>/dev/null || true
|
|
193
225
|
|
|
194
226
|
sleep 2
|
|
@@ -234,7 +266,10 @@ cmd_stop() {
|
|
|
234
266
|
fi
|
|
235
267
|
|
|
236
268
|
log_info "Stopping bugfix pipeline (PID: $pid)..."
|
|
237
|
-
|
|
269
|
+
|
|
270
|
+
# Kill the entire process group to include child processes (claude-internal, etc.)
|
|
271
|
+
# First try SIGTERM to the process group (negative PID)
|
|
272
|
+
kill -TERM -- -"$pid" 2>/dev/null || kill -TERM "$pid" 2>/dev/null || true
|
|
238
273
|
|
|
239
274
|
local waited=0
|
|
240
275
|
while [[ $waited -lt 30 ]]; do
|
|
@@ -245,9 +280,10 @@ cmd_stop() {
|
|
|
245
280
|
waited=$((waited + 1))
|
|
246
281
|
done
|
|
247
282
|
|
|
283
|
+
# Force kill if still alive (process group first, then individual)
|
|
248
284
|
if kill -0 "$pid" 2>/dev/null; then
|
|
249
285
|
log_warn "Process did not exit after 30s, sending SIGKILL..."
|
|
250
|
-
kill -9 "$pid" 2>/dev/null || true
|
|
286
|
+
kill -9 -- -"$pid" 2>/dev/null || kill -9 "$pid" 2>/dev/null || true
|
|
251
287
|
sleep 1
|
|
252
288
|
fi
|
|
253
289
|
|
|
@@ -342,7 +378,7 @@ import json, os
|
|
|
342
378
|
bl = json.load(open('$bug_list_path'))
|
|
343
379
|
bugs = bl.get('bugs', [])
|
|
344
380
|
total = len(bugs)
|
|
345
|
-
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, 'needs_info': 0}
|
|
381
|
+
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, 'needs_info': 0, 'skipped': 0}
|
|
346
382
|
for bug in bugs:
|
|
347
383
|
bid = bug.get('id', '')
|
|
348
384
|
sp = os.path.join('$STATE_DIR', 'bugs', bid, 'status.json')
|
|
@@ -356,7 +392,7 @@ for bug in bugs:
|
|
|
356
392
|
else:
|
|
357
393
|
counts['pending'] += 1
|
|
358
394
|
pct = round(counts['completed'] / total * 100, 1) if total > 0 else 0
|
|
359
|
-
print(json.dumps({'total': total, 'completed': counts['completed'], 'in_progress': counts['in_progress'], 'failed': counts['failed'], 'pending': counts['pending'], 'needs_info': counts['needs_info'], 'percent': pct}))
|
|
395
|
+
print(json.dumps({'total': total, 'completed': counts['completed'], 'in_progress': counts['in_progress'], 'failed': counts['failed'], 'pending': counts['pending'], 'needs_info': counts['needs_info'], 'skipped': counts['skipped'], 'percent': pct}))
|
|
360
396
|
" 2>/dev/null || echo "")
|
|
361
397
|
fi
|
|
362
398
|
|
|
@@ -416,17 +452,26 @@ show_help() {
|
|
|
416
452
|
Usage: launch-bugfix-daemon.sh <command> [options]
|
|
417
453
|
|
|
418
454
|
Commands:
|
|
419
|
-
start [.prizmkit/plans/bug-fix-list.json] [--env "K=V ..."] Start bugfix pipeline in background
|
|
455
|
+
start [.prizmkit/plans/bug-fix-list.json] [--mode <mode>] [--critic] [--env "K=V ..."] Start bugfix pipeline in background
|
|
420
456
|
stop Gracefully stop pipeline
|
|
421
457
|
status Check if pipeline is running
|
|
422
458
|
logs [--lines N] [--follow] View pipeline logs
|
|
423
|
-
restart [.prizmkit/plans/bug-fix-list.json] [--env "K=V ..."] Stop + start pipeline
|
|
459
|
+
restart [.prizmkit/plans/bug-fix-list.json] [--mode <mode>] [--critic] [--env "K=V ..."] Stop + start pipeline
|
|
424
460
|
help Show this help
|
|
425
461
|
|
|
462
|
+
Options:
|
|
463
|
+
--mode <lite|standard|full> Override pipeline mode for all bugs
|
|
464
|
+
--critic Enable adversarial critic review for all bugs
|
|
465
|
+
--no-critic Disable adversarial critic review for all bugs
|
|
466
|
+
--env "KEY=VAL ..." Set environment variables
|
|
467
|
+
|
|
426
468
|
Examples:
|
|
427
469
|
./launch-bugfix-daemon.sh start # Start with default .prizmkit/plans/bug-fix-list.json
|
|
428
470
|
./launch-bugfix-daemon.sh start my-bugs.json # Start with custom bug list
|
|
471
|
+
./launch-bugfix-daemon.sh start --mode full # Full mode for complex bugs
|
|
472
|
+
./launch-bugfix-daemon.sh start --critic # Enable adversarial critic review
|
|
429
473
|
./launch-bugfix-daemon.sh start --env "MAX_RETRIES=5"
|
|
474
|
+
./launch-bugfix-daemon.sh start .prizmkit/plans/bug-fix-list.json --mode full --critic --env "VERBOSE=1"
|
|
430
475
|
./launch-bugfix-daemon.sh status # Check if running (JSON on stdout)
|
|
431
476
|
./launch-bugfix-daemon.sh logs --follow # Live log tailing
|
|
432
477
|
./launch-bugfix-daemon.sh stop # Graceful shutdown
|
|
@@ -481,7 +481,7 @@ feature_list_path, state_dir = sys.argv[1], sys.argv[2]
|
|
|
481
481
|
fl = load_json(feature_list_path)
|
|
482
482
|
features = fl.get('features', [])
|
|
483
483
|
total = len(features)
|
|
484
|
-
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, 'skipped': 0}
|
|
484
|
+
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, 'skipped': 0, 'auto_skipped': 0}
|
|
485
485
|
for feat in features:
|
|
486
486
|
fid = feat.get('id', '')
|
|
487
487
|
sp = os.path.join(state_dir, 'features', fid, 'status.json')
|
|
@@ -502,6 +502,8 @@ print(json.dumps({
|
|
|
502
502
|
'in_progress': counts['in_progress'],
|
|
503
503
|
'failed': counts['failed'],
|
|
504
504
|
'pending': counts['pending'],
|
|
505
|
+
'skipped': counts['skipped'],
|
|
506
|
+
'auto_skipped': counts['auto_skipped'],
|
|
505
507
|
'percent': pct
|
|
506
508
|
}))
|
|
507
509
|
" "$feature_list_path" "$STATE_DIR" 2>/dev/null || echo "")
|
|
@@ -8,11 +8,11 @@ set -euo pipefail
|
|
|
8
8
|
# log consolidation, and lifecycle commands.
|
|
9
9
|
#
|
|
10
10
|
# Usage:
|
|
11
|
-
# ./launch-refactor-daemon.sh start [.prizmkit/plans/refactor-list.json] [--env "KEY=VAL ..."]
|
|
11
|
+
# ./launch-refactor-daemon.sh start [.prizmkit/plans/refactor-list.json] [--mode <mode>] [--critic] [--env "KEY=VAL ..."]
|
|
12
12
|
# ./launch-refactor-daemon.sh stop
|
|
13
13
|
# ./launch-refactor-daemon.sh status
|
|
14
14
|
# ./launch-refactor-daemon.sh logs [--lines N] [--follow]
|
|
15
|
-
# ./launch-refactor-daemon.sh restart [.prizmkit/plans/refactor-list.json] [--env "KEY=VAL ..."]
|
|
15
|
+
# ./launch-refactor-daemon.sh restart [.prizmkit/plans/refactor-list.json] [--mode <mode>] [--critic] [--env "KEY=VAL ..."]
|
|
16
16
|
#
|
|
17
17
|
# NOTE:
|
|
18
18
|
# In AI skill sessions, always use this daemon wrapper.
|
|
@@ -93,6 +93,31 @@ cmd_start() {
|
|
|
93
93
|
while [[ $# -gt 0 ]]; do
|
|
94
94
|
case "$1" in
|
|
95
95
|
--env) shift; env_overrides="${1:-}"; shift ;;
|
|
96
|
+
--mode)
|
|
97
|
+
shift
|
|
98
|
+
if [[ $# -eq 0 ]]; then
|
|
99
|
+
log_error "--mode requires a value (lite|standard|full)"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
case "$1" in
|
|
103
|
+
lite|standard|full)
|
|
104
|
+
PIPELINE_MODE="$1"
|
|
105
|
+
;;
|
|
106
|
+
*)
|
|
107
|
+
log_error "Invalid mode: $1 (must be lite, standard, or full)"
|
|
108
|
+
exit 1
|
|
109
|
+
;;
|
|
110
|
+
esac
|
|
111
|
+
shift
|
|
112
|
+
;;
|
|
113
|
+
--critic)
|
|
114
|
+
ENABLE_CRITIC=true
|
|
115
|
+
shift
|
|
116
|
+
;;
|
|
117
|
+
--no-critic)
|
|
118
|
+
ENABLE_CRITIC=false
|
|
119
|
+
shift
|
|
120
|
+
;;
|
|
96
121
|
*) refactor_list="$1"; shift ;;
|
|
97
122
|
esac
|
|
98
123
|
done
|
|
@@ -166,6 +191,9 @@ cmd_start() {
|
|
|
166
191
|
echo ""
|
|
167
192
|
} >> "$LOG_FILE"
|
|
168
193
|
|
|
194
|
+
[[ -n "${PIPELINE_MODE:-}" ]] && export PIPELINE_MODE
|
|
195
|
+
[[ -n "${ENABLE_CRITIC:-}" ]] && export ENABLE_CRITIC
|
|
196
|
+
|
|
169
197
|
if [[ -n "$env_cmd" ]]; then
|
|
170
198
|
nohup $env_cmd "$RUN_SCRIPT" run "$refactor_list" >> "$LOG_FILE" 2>&1 &
|
|
171
199
|
else
|
|
@@ -174,11 +202,12 @@ cmd_start() {
|
|
|
174
202
|
local pipeline_pid=$!
|
|
175
203
|
disown "$pipeline_pid" 2>/dev/null || true
|
|
176
204
|
|
|
177
|
-
echo "$pipeline_pid" > "$PID_FILE"
|
|
205
|
+
echo "$pipeline_pid" > "${PID_FILE}.tmp"
|
|
206
|
+
mv "${PID_FILE}.tmp" "$PID_FILE"
|
|
178
207
|
|
|
208
|
+
# Write start metadata (atomic)
|
|
179
209
|
python3 -c "
|
|
180
|
-
import json
|
|
181
|
-
from datetime import datetime
|
|
210
|
+
import json, os
|
|
182
211
|
data = {
|
|
183
212
|
'pid': $pipeline_pid,
|
|
184
213
|
'pipeline_type': 'refactor',
|
|
@@ -187,8 +216,11 @@ data = {
|
|
|
187
216
|
'env_overrides': '$env_overrides',
|
|
188
217
|
'log_file': '$LOG_FILE'
|
|
189
218
|
}
|
|
190
|
-
|
|
219
|
+
target = os.path.join('$STATE_DIR', '.pipeline-meta.json')
|
|
220
|
+
tmp = target + '.tmp'
|
|
221
|
+
with open(tmp, 'w') as f:
|
|
191
222
|
json.dump(data, f, indent=2)
|
|
223
|
+
os.replace(tmp, target)
|
|
192
224
|
" 2>/dev/null || true
|
|
193
225
|
|
|
194
226
|
sleep 2
|
|
@@ -234,7 +266,10 @@ cmd_stop() {
|
|
|
234
266
|
fi
|
|
235
267
|
|
|
236
268
|
log_info "Stopping refactor pipeline (PID: $pid)..."
|
|
237
|
-
|
|
269
|
+
|
|
270
|
+
# Kill the entire process group to include child processes (claude-internal, etc.)
|
|
271
|
+
# First try SIGTERM to the process group (negative PID)
|
|
272
|
+
kill -TERM -- -"$pid" 2>/dev/null || kill -TERM "$pid" 2>/dev/null || true
|
|
238
273
|
|
|
239
274
|
local waited=0
|
|
240
275
|
while [[ $waited -lt 30 ]]; do
|
|
@@ -245,9 +280,10 @@ cmd_stop() {
|
|
|
245
280
|
waited=$((waited + 1))
|
|
246
281
|
done
|
|
247
282
|
|
|
283
|
+
# Force kill if still alive (process group first, then individual)
|
|
248
284
|
if kill -0 "$pid" 2>/dev/null; then
|
|
249
285
|
log_warn "Process did not exit after 30s, sending SIGKILL..."
|
|
250
|
-
kill -9 "$pid" 2>/dev/null || true
|
|
286
|
+
kill -9 -- -"$pid" 2>/dev/null || kill -9 "$pid" 2>/dev/null || true
|
|
251
287
|
sleep 1
|
|
252
288
|
fi
|
|
253
289
|
|
|
@@ -342,7 +378,7 @@ import json, os
|
|
|
342
378
|
bl = json.load(open('$refactor_list_path'))
|
|
343
379
|
items = bl.get('refactors', [])
|
|
344
380
|
total = len(items)
|
|
345
|
-
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, '
|
|
381
|
+
counts = {'completed': 0, 'in_progress': 0, 'failed': 0, 'pending': 0, 'skipped': 0, 'auto_skipped': 0}
|
|
346
382
|
for item in items:
|
|
347
383
|
rid = item.get('id', '')
|
|
348
384
|
sp = os.path.join('$STATE_DIR', 'refactors', rid, 'status.json')
|
|
@@ -356,7 +392,7 @@ for item in items:
|
|
|
356
392
|
else:
|
|
357
393
|
counts['pending'] += 1
|
|
358
394
|
pct = round(counts['completed'] / total * 100, 1) if total > 0 else 0
|
|
359
|
-
print(json.dumps({'total': total, 'completed': counts['completed'], 'in_progress': counts['in_progress'], 'failed': counts['failed'], 'pending': counts['pending'], '
|
|
395
|
+
print(json.dumps({'total': total, 'completed': counts['completed'], 'in_progress': counts['in_progress'], 'failed': counts['failed'], 'pending': counts['pending'], 'skipped': counts['skipped'], 'auto_skipped': counts['auto_skipped'], 'percent': pct}))
|
|
360
396
|
" 2>/dev/null || echo "")
|
|
361
397
|
fi
|
|
362
398
|
|
|
@@ -416,18 +452,27 @@ show_help() {
|
|
|
416
452
|
Usage: launch-refactor-daemon.sh <command> [options]
|
|
417
453
|
|
|
418
454
|
Commands:
|
|
419
|
-
start [.prizmkit/plans/refactor-list.json] [--env "K=V ..."] Start refactor pipeline in background
|
|
455
|
+
start [.prizmkit/plans/refactor-list.json] [--mode <mode>] [--critic] [--env "K=V ..."] Start refactor pipeline in background
|
|
420
456
|
stop Gracefully stop pipeline
|
|
421
457
|
status Check if pipeline is running
|
|
422
458
|
logs [--lines N] [--follow] View pipeline logs
|
|
423
|
-
restart [.prizmkit/plans/refactor-list.json] [--env "K=V ..."] Stop + start pipeline
|
|
459
|
+
restart [.prizmkit/plans/refactor-list.json] [--mode <mode>] [--critic] [--env "K=V ..."] Stop + start pipeline
|
|
424
460
|
help Show this help
|
|
425
461
|
|
|
462
|
+
Options:
|
|
463
|
+
--mode <lite|standard|full> Override pipeline mode for all refactors
|
|
464
|
+
--critic Enable adversarial critic review for all refactors
|
|
465
|
+
--no-critic Disable adversarial critic review for all refactors
|
|
466
|
+
--env "KEY=VAL ..." Set environment variables
|
|
467
|
+
|
|
426
468
|
Examples:
|
|
427
469
|
./launch-refactor-daemon.sh start # Start with default .prizmkit/plans/refactor-list.json
|
|
428
470
|
./launch-refactor-daemon.sh start my-refactors.json # Start with custom refactor list
|
|
471
|
+
./launch-refactor-daemon.sh start --mode full # Full mode for complex refactors
|
|
472
|
+
./launch-refactor-daemon.sh start --critic # Enable adversarial critic review
|
|
429
473
|
./launch-refactor-daemon.sh start --env "MAX_RETRIES=5"
|
|
430
474
|
./launch-refactor-daemon.sh start --env "STRICT_BEHAVIOR_CHECK=0"
|
|
475
|
+
./launch-refactor-daemon.sh start .prizmkit/plans/refactor-list.json --mode full --critic --env "VERBOSE=1"
|
|
431
476
|
./launch-refactor-daemon.sh status # Check if running (JSON on stdout)
|
|
432
477
|
./launch-refactor-daemon.sh logs --follow # Live log tailing
|
|
433
478
|
./launch-refactor-daemon.sh stop # Graceful shutdown
|
|
@@ -99,7 +99,12 @@ branch_merge() {
|
|
|
99
99
|
local remaining_dirty
|
|
100
100
|
remaining_dirty=$(git -C "$project_root" status --porcelain 2>/dev/null || true)
|
|
101
101
|
if [[ -n "$remaining_dirty" ]]; then
|
|
102
|
-
git -C "$project_root" stash push --include-untracked -m "pipeline-merge-stash" 2>/dev/null
|
|
102
|
+
if git -C "$project_root" stash push --include-untracked -m "pipeline-merge-stash" 2>/dev/null; then
|
|
103
|
+
had_stash=true
|
|
104
|
+
else
|
|
105
|
+
log_warn "git stash failed — uncommitted changes may not be preserved during merge"
|
|
106
|
+
had_stash=false
|
|
107
|
+
fi
|
|
103
108
|
fi
|
|
104
109
|
|
|
105
110
|
# Step 2: Rebase dev branch onto original to make it fast-forwardable.
|
|
@@ -23,6 +23,70 @@ log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*
|
|
|
23
23
|
log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
24
24
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
25
25
|
|
|
26
|
+
# ============================================================
|
|
27
|
+
# .env file loading
|
|
28
|
+
# ============================================================
|
|
29
|
+
|
|
30
|
+
# Load .env file if it exists. Does NOT override already-set env vars.
|
|
31
|
+
# Supports: KEY=VALUE, KEY="VALUE", KEY='VALUE', comments (#), empty lines.
|
|
32
|
+
# If the file does not exist, silently continues (no error).
|
|
33
|
+
prizm_load_env() {
|
|
34
|
+
local env_file="${1:-.env}"
|
|
35
|
+
[[ -f "$env_file" ]] || return 0
|
|
36
|
+
|
|
37
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
38
|
+
# Skip empty lines and comments
|
|
39
|
+
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
|
40
|
+
# Remove inline comments (not inside quotes)
|
|
41
|
+
line="${line%%#*}"
|
|
42
|
+
# Trim whitespace
|
|
43
|
+
line="$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
44
|
+
[[ -z "$line" ]] && continue
|
|
45
|
+
# Parse KEY=VALUE
|
|
46
|
+
if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
|
|
47
|
+
local key="${BASH_REMATCH[1]}"
|
|
48
|
+
local val="${BASH_REMATCH[2]}"
|
|
49
|
+
# Strip surrounding quotes
|
|
50
|
+
val="${val#\"}" ; val="${val%\"}"
|
|
51
|
+
val="${val#\'}" ; val="${val%\'}"
|
|
52
|
+
# Only set if not already defined in environment
|
|
53
|
+
if [[ -z "${!key+x}" ]]; then
|
|
54
|
+
export "$key=$val"
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
done < "$env_file"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# ============================================================
|
|
61
|
+
# Test mode: bootstrap prompt logging
|
|
62
|
+
# ============================================================
|
|
63
|
+
|
|
64
|
+
# Log bootstrap prompt content when PRIZMKIT_ENV=test.
|
|
65
|
+
# Called after prompt generation, before AI CLI session spawn.
|
|
66
|
+
# Usage: prizm_log_bootstrap_prompt <prompt_path> <item_id>
|
|
67
|
+
prizm_log_bootstrap_prompt() {
|
|
68
|
+
local prompt_path="$1"
|
|
69
|
+
local item_id="$2"
|
|
70
|
+
|
|
71
|
+
[[ "${PRIZMKIT_ENV:-}" == "test" ]] || return 0
|
|
72
|
+
[[ -f "$prompt_path" ]] || return 0
|
|
73
|
+
|
|
74
|
+
local lines size
|
|
75
|
+
lines=$(wc -l < "$prompt_path" 2>/dev/null | tr -d ' ')
|
|
76
|
+
size=$(wc -c < "$prompt_path" 2>/dev/null | tr -d ' ')
|
|
77
|
+
|
|
78
|
+
echo ""
|
|
79
|
+
echo -e "${MAGENTA}[TEST]${NC} ════════════════════════════════════════════════════"
|
|
80
|
+
echo -e "${MAGENTA}[TEST]${NC} Bootstrap Prompt for $item_id"
|
|
81
|
+
echo -e "${MAGENTA}[TEST]${NC} Lines: $lines | Size: $((size / 1024))KB"
|
|
82
|
+
echo -e "${MAGENTA}[TEST]${NC} Path: $prompt_path"
|
|
83
|
+
echo -e "${MAGENTA}[TEST]${NC} ════════════════════════════════════════════════════"
|
|
84
|
+
cat "$prompt_path"
|
|
85
|
+
echo ""
|
|
86
|
+
echo -e "${MAGENTA}[TEST]${NC} ════════════════════════ END ═══════════════════════"
|
|
87
|
+
echo ""
|
|
88
|
+
}
|
|
89
|
+
|
|
26
90
|
# Detect AI CLI + platform.
|
|
27
91
|
# Priority:
|
|
28
92
|
# AI_CLI env > .prizmkit/config.json > CODEBUDDY_CLI > auto-detect(cbc/claude) > error
|
|
@@ -32,6 +96,13 @@ log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"
|
|
|
32
96
|
# PLATFORM
|
|
33
97
|
# PRIZMKIT_PLATFORM
|
|
34
98
|
prizm_detect_cli_and_platform() {
|
|
99
|
+
# Load .env from project root if it exists (does not override existing env vars)
|
|
100
|
+
local _env_root
|
|
101
|
+
_env_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." 2>/dev/null && pwd)" || true
|
|
102
|
+
if [[ -n "$_env_root" ]]; then
|
|
103
|
+
prizm_load_env "$_env_root/.env"
|
|
104
|
+
fi
|
|
105
|
+
|
|
35
106
|
local _raw_cli=""
|
|
36
107
|
|
|
37
108
|
if [[ -n "${AI_CLI:-}" ]]; then
|
|
@@ -73,7 +73,7 @@ start_heartbeat() {
|
|
|
73
73
|
phase=$(python3 -c "
|
|
74
74
|
import json, sys
|
|
75
75
|
try:
|
|
76
|
-
with open(
|
|
76
|
+
with open(sys.argv[1]) as f:
|
|
77
77
|
d = json.load(f)
|
|
78
78
|
parts = []
|
|
79
79
|
if d.get('current_phase'):
|
|
@@ -85,7 +85,7 @@ try:
|
|
|
85
85
|
print(' | '.join(parts))
|
|
86
86
|
except Exception:
|
|
87
87
|
sys.exit(1)
|
|
88
|
-
" 2>/dev/null) && {
|
|
88
|
+
" "$progress_json" 2>/dev/null) && {
|
|
89
89
|
echo -e " ${status_icon} ${BLUE}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${phase}"
|
|
90
90
|
continue
|
|
91
91
|
}
|
|
@@ -127,15 +127,28 @@ ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null
|
|
|
127
127
|
# Branch tracking (for cleanup on interrupt)
|
|
128
128
|
_DEV_BRANCH_NAME=""
|
|
129
129
|
|
|
130
|
-
log_info "
|
|
131
|
-
python3
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
log_info "Reading retry state for $BUG_ID..."
|
|
131
|
+
RETRY_COUNT=$(python3 -c "
|
|
132
|
+
import json, os
|
|
133
|
+
status_path = os.path.join('$STATE_DIR', 'bugs', '$BUG_ID', 'status.json')
|
|
134
|
+
if os.path.isfile(status_path):
|
|
135
|
+
with open(status_path) as f:
|
|
136
|
+
d = json.load(f)
|
|
137
|
+
print(d.get('retry_count', 0))
|
|
138
|
+
else:
|
|
139
|
+
print(0)
|
|
140
|
+
" 2>/dev/null || echo "0")
|
|
141
|
+
RESUME_PHASE=$(python3 -c "
|
|
142
|
+
import json, os
|
|
143
|
+
status_path = os.path.join('$STATE_DIR', 'bugs', '$BUG_ID', 'status.json')
|
|
144
|
+
if os.path.isfile(status_path):
|
|
145
|
+
with open(status_path) as f:
|
|
146
|
+
d = json.load(f)
|
|
147
|
+
print(d.get('resume_from_phase') or 'null')
|
|
148
|
+
else:
|
|
149
|
+
print('null')
|
|
150
|
+
" 2>/dev/null || echo "null")
|
|
151
|
+
log_info "Retry count: $RETRY_COUNT, Resume phase: $RESUME_PHASE"
|
|
139
152
|
|
|
140
153
|
# ============================================================
|
|
141
154
|
# Generate bootstrap prompt
|
|
@@ -149,15 +162,34 @@ mkdir -p "$SESSION_DIR/logs"
|
|
|
149
162
|
BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
|
|
150
163
|
|
|
151
164
|
log_info "Generating bugfix bootstrap prompt..."
|
|
152
|
-
|
|
153
|
-
--bug-list "$BUG_LIST"
|
|
154
|
-
--bug-id "$BUG_ID"
|
|
155
|
-
--session-id "$SESSION_ID"
|
|
156
|
-
--run-id "$RUN_ID"
|
|
157
|
-
--retry-count
|
|
158
|
-
--resume-phase "
|
|
159
|
-
--state-dir "$STATE_DIR"
|
|
160
|
-
--output "$BOOTSTRAP_PROMPT"
|
|
165
|
+
GEN_ARGS=(
|
|
166
|
+
--bug-list "$BUG_LIST"
|
|
167
|
+
--bug-id "$BUG_ID"
|
|
168
|
+
--session-id "$SESSION_ID"
|
|
169
|
+
--run-id "$RUN_ID"
|
|
170
|
+
--retry-count "$RETRY_COUNT"
|
|
171
|
+
--resume-phase "$RESUME_PHASE"
|
|
172
|
+
--state-dir "$STATE_DIR"
|
|
173
|
+
--output "$BOOTSTRAP_PROMPT"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Support PIPELINE_MODE env var
|
|
177
|
+
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
178
|
+
GEN_ARGS+=(--mode "$PIPELINE_MODE")
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
# Support ENABLE_CRITIC env var
|
|
182
|
+
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
183
|
+
GEN_ARGS+=(--critic "true")
|
|
184
|
+
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
185
|
+
GEN_ARGS+=(--critic "false")
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
GEN_OUTPUT=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${GEN_ARGS[@]}" 2>/dev/null) || {
|
|
189
|
+
log_error "Failed to generate bootstrap prompt"
|
|
190
|
+
exit 1
|
|
191
|
+
}
|
|
192
|
+
BUG_MODEL=$(echo "$GEN_OUTPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
161
193
|
|
|
162
194
|
# ============================================================
|
|
163
195
|
# Run single AI CLI session
|
|
@@ -178,8 +210,9 @@ echo -e "${BOLD} Retry Bug Fix: $BUG_ID — $BUG_TITLE${NC}"
|
|
|
178
210
|
echo -e "${BOLD} Severity: $BUG_SEVERITY${NC}"
|
|
179
211
|
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
180
212
|
log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
181
|
-
|
|
182
|
-
|
|
213
|
+
EFFECTIVE_MODEL="${BUG_MODEL:-${MODEL:-}}"
|
|
214
|
+
if [[ -n "$EFFECTIVE_MODEL" ]]; then
|
|
215
|
+
log_info "Model: $EFFECTIVE_MODEL"
|
|
183
216
|
else
|
|
184
217
|
log_info "Model: (CLI default)"
|
|
185
218
|
fi
|
|
@@ -208,14 +241,18 @@ if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
|
208
241
|
VERBOSE_FLAG="--verbose"
|
|
209
242
|
fi
|
|
210
243
|
|
|
211
|
-
# Spawn AI CLI session
|
|
244
|
+
# Spawn AI CLI session — model priority: bug.model > $MODEL env > none
|
|
245
|
+
EFFECTIVE_MODEL="${BUG_MODEL:-${MODEL:-}}"
|
|
212
246
|
MODEL_FLAG=""
|
|
213
|
-
if [[ -n "$
|
|
214
|
-
MODEL_FLAG="--model $
|
|
247
|
+
if [[ -n "$EFFECTIVE_MODEL" ]]; then
|
|
248
|
+
MODEL_FLAG="--model $EFFECTIVE_MODEL"
|
|
215
249
|
fi
|
|
216
250
|
|
|
217
251
|
unset CLAUDECODE 2>/dev/null || true
|
|
218
252
|
|
|
253
|
+
# Log bootstrap prompt in test mode
|
|
254
|
+
prizm_log_bootstrap_prompt "$BOOTSTRAP_PROMPT" "$BUG_ID"
|
|
255
|
+
|
|
219
256
|
case "$CLI_CMD" in
|
|
220
257
|
*claude*)
|
|
221
258
|
# Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
|
|
@@ -119,16 +119,28 @@ title = re.sub(r'-+', '-', title).strip('-') or 'feature'
|
|
|
119
119
|
print(f'{fid}-{title}')
|
|
120
120
|
" 2>/dev/null)
|
|
121
121
|
|
|
122
|
-
log_info "
|
|
123
|
-
python3
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
log_info "Reading retry state for $FEATURE_ID..."
|
|
123
|
+
RETRY_COUNT=$(python3 -c "
|
|
124
|
+
import json, os
|
|
125
|
+
status_path = os.path.join('$STATE_DIR', 'features', '$FEATURE_ID', 'status.json')
|
|
126
|
+
if os.path.isfile(status_path):
|
|
127
|
+
with open(status_path) as f:
|
|
128
|
+
d = json.load(f)
|
|
129
|
+
print(d.get('retry_count', 0))
|
|
130
|
+
else:
|
|
131
|
+
print(0)
|
|
132
|
+
" 2>/dev/null || echo "0")
|
|
133
|
+
RESUME_PHASE=$(python3 -c "
|
|
134
|
+
import json, os
|
|
135
|
+
status_path = os.path.join('$STATE_DIR', 'features', '$FEATURE_ID', 'status.json')
|
|
136
|
+
if os.path.isfile(status_path):
|
|
137
|
+
with open(status_path) as f:
|
|
138
|
+
d = json.load(f)
|
|
139
|
+
print(d.get('resume_from_phase') or 'null')
|
|
140
|
+
else:
|
|
141
|
+
print('null')
|
|
142
|
+
" 2>/dev/null || echo "null")
|
|
143
|
+
log_info "Retry count: $RETRY_COUNT, Resume phase: $RESUME_PHASE"
|
|
132
144
|
|
|
133
145
|
# ============================================================
|
|
134
146
|
# Generate bootstrap prompt
|
|
@@ -147,12 +159,17 @@ GEN_ARGS=(
|
|
|
147
159
|
--feature-id "$FEATURE_ID"
|
|
148
160
|
--session-id "$SESSION_ID"
|
|
149
161
|
--run-id "$RUN_ID"
|
|
150
|
-
--retry-count
|
|
151
|
-
--resume-phase "
|
|
162
|
+
--retry-count "$RETRY_COUNT"
|
|
163
|
+
--resume-phase "$RESUME_PHASE"
|
|
152
164
|
--state-dir "$STATE_DIR"
|
|
153
165
|
--output "$BOOTSTRAP_PROMPT"
|
|
154
166
|
)
|
|
155
167
|
|
|
168
|
+
# Support PIPELINE_MODE env var
|
|
169
|
+
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
170
|
+
GEN_ARGS+=(--mode "$PIPELINE_MODE")
|
|
171
|
+
fi
|
|
172
|
+
|
|
156
173
|
# Support ENABLE_CRITIC env var
|
|
157
174
|
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
158
175
|
GEN_ARGS+=(--critic "true")
|
|
@@ -233,6 +250,9 @@ fi
|
|
|
233
250
|
|
|
234
251
|
unset CLAUDECODE 2>/dev/null || true
|
|
235
252
|
|
|
253
|
+
# Log bootstrap prompt in test mode
|
|
254
|
+
prizm_log_bootstrap_prompt "$BOOTSTRAP_PROMPT" "$FEATURE_ID"
|
|
255
|
+
|
|
236
256
|
case "$CLI_CMD" in
|
|
237
257
|
*claude*)
|
|
238
258
|
# Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
|
|
@@ -367,6 +387,21 @@ if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
|
367
387
|
fi
|
|
368
388
|
fi
|
|
369
389
|
|
|
390
|
+
# ── Propagate completion notes for dependency context ─────────────────
|
|
391
|
+
if [[ "$SESSION_STATUS" == "success" && -n "$FEATURE_SLUG" ]]; then
|
|
392
|
+
SUMMARY_PATH="$PROJECT_ROOT/.prizmkit/specs/$FEATURE_SLUG/completion-summary.json"
|
|
393
|
+
if [[ -f "$SUMMARY_PATH" ]]; then
|
|
394
|
+
python3 "$SCRIPTS_DIR/patch-completion-notes.py" \
|
|
395
|
+
--feature-list "$FEATURE_LIST" \
|
|
396
|
+
--feature-id "$FEATURE_ID" \
|
|
397
|
+
--summary "$SUMMARY_PATH" >/dev/null 2>&1 && {
|
|
398
|
+
log_info "Propagated completion notes for $FEATURE_ID"
|
|
399
|
+
} || {
|
|
400
|
+
log_warn "Failed to propagate completion notes for $FEATURE_ID"
|
|
401
|
+
}
|
|
402
|
+
fi
|
|
403
|
+
fi
|
|
404
|
+
|
|
370
405
|
# Update feature status
|
|
371
406
|
python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
372
407
|
--feature-list "$FEATURE_LIST" \
|