prizmkit 1.1.6 → 1.1.8
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/README.md +65 -65
- package/bundled/dev-pipeline/assets/feature-list-example.json +2 -2
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +11 -10
- package/bundled/dev-pipeline/launch-feature-daemon.sh +12 -11
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +11 -10
- package/bundled/dev-pipeline/reset-bug.sh +305 -0
- package/bundled/dev-pipeline/reset-feature.sh +9 -8
- package/bundled/dev-pipeline/reset-refactor.sh +10 -9
- package/bundled/dev-pipeline/retry-bugfix.sh +7 -6
- package/bundled/dev-pipeline/retry-feature.sh +7 -6
- package/bundled/dev-pipeline/retry-refactor.sh +7 -6
- package/bundled/dev-pipeline/run-bugfix.sh +71 -23
- package/bundled/dev-pipeline/run-feature.sh +30 -21
- package/bundled/dev-pipeline/run-refactor.sh +21 -17
- package/bundled/dev-pipeline/scripts/cleanup-logs.py +2 -2
- package/bundled/dev-pipeline/scripts/detect-stuck.py +3 -3
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +26 -14
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +6 -6
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +6 -6
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +4 -4
- package/bundled/dev-pipeline/scripts/init-pipeline.py +26 -12
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +4 -4
- package/bundled/dev-pipeline/scripts/update-bug-status.py +10 -10
- package/bundled/dev-pipeline/scripts/update-feature-status.py +31 -31
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +8 -8
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +111 -31
- package/bundled/dev-pipeline/templates/feature-list-schema.json +91 -25
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +107 -28
- package/bundled/dev-pipeline/tests/test_auto_skip.py +1 -1
- package/bundled/skills/_metadata.json +10 -2
- package/bundled/skills/app-planner/SKILL.md +24 -13
- package/bundled/skills/app-planner/references/project-brief-guide.md +1 -1
- package/bundled/skills/bug-fix-workflow/SKILL.md +7 -5
- package/bundled/skills/bug-planner/SKILL.md +80 -25
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +3 -3
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +38 -33
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +33 -33
- package/bundled/skills/feature-pipeline-launcher/scripts/preflight-check.py +3 -3
- package/bundled/skills/feature-planner/SKILL.md +96 -24
- package/bundled/skills/feature-planner/references/error-recovery.md +9 -9
- package/bundled/skills/feature-planner/scripts/validate-and-generate.py +25 -24
- package/bundled/skills/feature-workflow/SKILL.md +23 -20
- package/bundled/skills/prizmkit-committer/SKILL.md +1 -0
- package/bundled/skills/prizmkit-deploy/SKILL.md +1 -0
- package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +1 -1
- package/bundled/skills/prizmkit-implement/SKILL.md +1 -1
- package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +4 -4
- package/bundled/skills/prizmkit-plan/SKILL.md +3 -3
- package/bundled/skills/prizmkit-retrospective/SKILL.md +40 -3
- package/bundled/skills/prizmkit-verify/SKILL.md +281 -0
- package/bundled/skills/prizmkit-verify/scripts/verify-light.py +402 -0
- package/bundled/skills/recovery-workflow/SKILL.md +15 -14
- package/bundled/skills/recovery-workflow/evals/evals.json +5 -5
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +43 -10
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +38 -34
- package/bundled/skills/refactor-planner/SKILL.md +74 -24
- package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +17 -17
- package/bundled/skills/refactor-workflow/SKILL.md +24 -20
- package/package.json +1 -1
- package/src/clean.js +4 -4
- package/src/gitignore-template.js +7 -8
- package/src/scaffold.js +4 -2
|
@@ -5,12 +5,12 @@ set -euo pipefail
|
|
|
5
5
|
# dev-pipeline/run-bugfix.sh - Autonomous Bug Fix Pipeline Runner
|
|
6
6
|
#
|
|
7
7
|
# Drives the prizm-dev-team through iterative AI CLI sessions to
|
|
8
|
-
# fix bugs from a bug-fix-list.json specification.
|
|
8
|
+
# fix bugs from a .prizmkit/plans/bug-fix-list.json specification.
|
|
9
9
|
#
|
|
10
10
|
# Usage:
|
|
11
|
-
# ./run-bugfix.sh run [bug-fix-list.json] Run all bugs
|
|
11
|
+
# ./run-bugfix.sh run [.prizmkit/plans/bug-fix-list.json] Run all bugs
|
|
12
12
|
# ./run-bugfix.sh run <bug-id> [options] Run a single bug
|
|
13
|
-
# ./run-bugfix.sh status [bug-fix-list.json] Show pipeline status
|
|
13
|
+
# ./run-bugfix.sh status [.prizmkit/plans/bug-fix-list.json] Show pipeline status
|
|
14
14
|
# ./run-bugfix.sh reset Clear all state
|
|
15
15
|
#
|
|
16
16
|
# Environment Variables:
|
|
@@ -30,7 +30,8 @@ set -euo pipefail
|
|
|
30
30
|
# ============================================================
|
|
31
31
|
|
|
32
32
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
|
-
|
|
33
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
34
|
+
STATE_DIR="${PROJECT_ROOT}/.prizmkit/state/bugfix"
|
|
34
35
|
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
35
36
|
|
|
36
37
|
# Configuration
|
|
@@ -272,7 +273,7 @@ sys.exit(0)
|
|
|
272
273
|
--max-retries "$max_retries" \
|
|
273
274
|
--action update >/dev/null 2>&1 || true
|
|
274
275
|
|
|
275
|
-
# Commit bug-fix-list.json status update (pipeline management commit)
|
|
276
|
+
# Commit .prizmkit/plans/bug-fix-list.json status update (pipeline management commit)
|
|
276
277
|
if ! git -C "$project_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
277
278
|
git -C "$project_root" add "$bug_list"
|
|
278
279
|
git -C "$project_root" commit --no-verify -m "chore($bug_id): update bug status" 2>/dev/null || true
|
|
@@ -352,10 +353,14 @@ run_one() {
|
|
|
352
353
|
local bug_id=""
|
|
353
354
|
local bug_list=""
|
|
354
355
|
local dry_run=false
|
|
356
|
+
local do_clean=false
|
|
357
|
+
local no_reset=false
|
|
355
358
|
|
|
356
359
|
while [[ $# -gt 0 ]]; do
|
|
357
360
|
case "$1" in
|
|
358
361
|
--dry-run) dry_run=true; shift ;;
|
|
362
|
+
--clean) do_clean=true; shift ;;
|
|
363
|
+
--no-reset) no_reset=true; shift ;;
|
|
359
364
|
--timeout) shift; SESSION_TIMEOUT="${1:-0}"; shift ;;
|
|
360
365
|
B-*|b-*) bug_id="$1"; shift ;;
|
|
361
366
|
*) bug_list="$1"; shift ;;
|
|
@@ -370,7 +375,7 @@ run_one() {
|
|
|
370
375
|
fi
|
|
371
376
|
|
|
372
377
|
if [[ -z "$bug_list" ]]; then
|
|
373
|
-
bug_list="bug-fix-list.json"
|
|
378
|
+
bug_list=".prizmkit/plans/bug-fix-list.json"
|
|
374
379
|
fi
|
|
375
380
|
if [[ ! "$bug_list" = /* ]]; then
|
|
376
381
|
bug_list="$(pwd)/$bug_list"
|
|
@@ -399,7 +404,7 @@ run_one() {
|
|
|
399
404
|
local _gitignore_path
|
|
400
405
|
_gitignore_path="$(cd "$SCRIPT_DIR/.." && pwd)/.gitignore"
|
|
401
406
|
local _state_rel
|
|
402
|
-
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo "
|
|
407
|
+
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo ".prizmkit/state/bugfix")
|
|
403
408
|
if [[ -f "$_gitignore_path" ]]; then
|
|
404
409
|
if ! grep -qF "$_state_rel" "$_gitignore_path" 2>/dev/null; then
|
|
405
410
|
printf '\n# Pipeline runtime state (auto-added by dev-pipeline)\n%s/\n' "$_state_rel" >> "$_gitignore_path"
|
|
@@ -437,12 +442,48 @@ for bug in data.get('bugs', []):
|
|
|
437
442
|
sys.exit(1)
|
|
438
443
|
" "$bug_list" "$bug_id" 2>/dev/null) || bug_severity="medium"
|
|
439
444
|
|
|
440
|
-
#
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
445
|
+
# Optional Clean
|
|
446
|
+
if [[ "$do_clean" == true ]]; then
|
|
447
|
+
if [[ "$dry_run" == true ]]; then
|
|
448
|
+
log_warn "Dry-run mode: --clean ignored (no artifacts will be deleted)"
|
|
449
|
+
else
|
|
450
|
+
log_info "Cleaning artifacts for $bug_id..."
|
|
451
|
+
|
|
452
|
+
local project_root
|
|
453
|
+
project_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
454
|
+
|
|
455
|
+
local bugfix_dir="$project_root/.prizmkit/bugfix/$bug_id"
|
|
456
|
+
if [[ -d "$bugfix_dir" ]]; then
|
|
457
|
+
rm -rf "$bugfix_dir"
|
|
458
|
+
log_info "Removed $bugfix_dir"
|
|
459
|
+
fi
|
|
460
|
+
|
|
461
|
+
local dev_team_dir="$project_root/.dev-team"
|
|
462
|
+
if [[ -d "$dev_team_dir" ]]; then
|
|
463
|
+
rm -rf "$dev_team_dir"
|
|
464
|
+
log_info "Removed $dev_team_dir"
|
|
465
|
+
fi
|
|
466
|
+
|
|
467
|
+
local bug_state_dir="$STATE_DIR/bugs/$bug_id"
|
|
468
|
+
if [[ -d "$bug_state_dir" ]]; then
|
|
469
|
+
rm -rf "$bug_state_dir"
|
|
470
|
+
log_info "Removed $bug_state_dir"
|
|
471
|
+
fi
|
|
472
|
+
fi
|
|
473
|
+
fi
|
|
474
|
+
|
|
475
|
+
# Reset bug status (conditional)
|
|
476
|
+
if [[ "$no_reset" == false && "$dry_run" == false ]]; then
|
|
477
|
+
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
478
|
+
--bug-list "$bug_list" \
|
|
479
|
+
--state-dir "$STATE_DIR" \
|
|
480
|
+
--bug-id "$bug_id" \
|
|
481
|
+
--action reset >/dev/null 2>&1 || {
|
|
482
|
+
log_warn "Failed to reset bug status (may already be pending)"
|
|
483
|
+
}
|
|
484
|
+
elif [[ "$dry_run" == true && "$no_reset" == false ]]; then
|
|
485
|
+
log_info "Dry-run mode: skipping status reset"
|
|
486
|
+
fi
|
|
446
487
|
|
|
447
488
|
# Generate bootstrap prompt
|
|
448
489
|
local run_id session_id session_dir bootstrap_prompt
|
|
@@ -551,7 +592,7 @@ sys.exit(1)
|
|
|
551
592
|
# ============================================================
|
|
552
593
|
|
|
553
594
|
main() {
|
|
554
|
-
local bug_list="${1
|
|
595
|
+
local bug_list="${1:-.prizmkit/plans/bug-fix-list.json}"
|
|
555
596
|
|
|
556
597
|
if [[ ! "$bug_list" = /* ]]; then
|
|
557
598
|
bug_list="$(pwd)/$bug_list"
|
|
@@ -561,7 +602,7 @@ main() {
|
|
|
561
602
|
if [[ ! -f "$bug_list" ]]; then
|
|
562
603
|
log_error "Bug fix list not found: $bug_list"
|
|
563
604
|
log_info "Create a bug fix list first using the bug-planner skill,"
|
|
564
|
-
log_info "or provide a path: ./run-bugfix.sh run <path-to
|
|
605
|
+
log_info "or provide a path: ./run-bugfix.sh run <path-to-.prizmkit/plans/bug-fix-list.json>"
|
|
565
606
|
exit 1
|
|
566
607
|
fi
|
|
567
608
|
|
|
@@ -593,7 +634,7 @@ main() {
|
|
|
593
634
|
local _gitignore_path
|
|
594
635
|
_gitignore_path="$(cd "$SCRIPT_DIR/.." && pwd)/.gitignore"
|
|
595
636
|
local _state_rel
|
|
596
|
-
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo "
|
|
637
|
+
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo ".prizmkit/state/bugfix")
|
|
597
638
|
if [[ -f "$_gitignore_path" ]]; then
|
|
598
639
|
if ! grep -qF "$_state_rel" "$_gitignore_path" 2>/dev/null; then
|
|
599
640
|
printf '\n# Pipeline runtime state (auto-added by dev-pipeline)\n%s/\n' "$_state_rel" >> "$_gitignore_path"
|
|
@@ -647,11 +688,14 @@ main() {
|
|
|
647
688
|
while true; do
|
|
648
689
|
# Find next bug to process
|
|
649
690
|
local next_bug
|
|
650
|
-
next_bug=$(python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
691
|
+
if ! next_bug=$(python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
651
692
|
--bug-list "$bug_list" \
|
|
652
693
|
--state-dir "$STATE_DIR" \
|
|
653
694
|
--max-retries "$MAX_RETRIES" \
|
|
654
|
-
--action get_next 2>/dev/null)
|
|
695
|
+
--action get_next 2>/dev/null); then
|
|
696
|
+
log_error "Failed to get next bug"
|
|
697
|
+
break
|
|
698
|
+
fi
|
|
655
699
|
|
|
656
700
|
if [[ "$next_bug" == "PIPELINE_COMPLETE" ]]; then
|
|
657
701
|
echo ""
|
|
@@ -745,14 +789,16 @@ show_help() {
|
|
|
745
789
|
echo "Usage: $0 <command> [options]"
|
|
746
790
|
echo ""
|
|
747
791
|
echo "Commands:"
|
|
748
|
-
echo " run [bug-fix-list.json] Run all bugs by severity/priority order"
|
|
792
|
+
echo " run [.prizmkit/plans/bug-fix-list.json] Run all bugs by severity/priority order"
|
|
749
793
|
echo " run <bug-id> [options] Run a single bug fix"
|
|
750
|
-
echo " status [bug-fix-list.json] Show bug fix pipeline status"
|
|
794
|
+
echo " status [.prizmkit/plans/bug-fix-list.json] Show bug fix pipeline status"
|
|
751
795
|
echo " reset Clear all bugfix state"
|
|
752
796
|
echo " help Show this help message"
|
|
753
797
|
echo ""
|
|
754
798
|
echo "Single Bug Options (run <bug-id>):"
|
|
755
799
|
echo " --dry-run Generate bootstrap prompt only, don't spawn session"
|
|
800
|
+
echo " --clean Delete artifacts and reset before running"
|
|
801
|
+
echo " --no-reset Skip status reset (preserve retry count)"
|
|
756
802
|
echo " --timeout N Session timeout in seconds (default: 0 = no limit)"
|
|
757
803
|
echo ""
|
|
758
804
|
echo "Environment Variables:"
|
|
@@ -767,8 +813,10 @@ show_help() {
|
|
|
767
813
|
echo ""
|
|
768
814
|
echo "Examples:"
|
|
769
815
|
echo " ./run-bugfix.sh run # Run all bugs"
|
|
770
|
-
echo " ./run-bugfix.sh run bug-fix-list.json # Custom bug list"
|
|
816
|
+
echo " ./run-bugfix.sh run .prizmkit/plans/bug-fix-list.json # Custom bug list"
|
|
771
817
|
echo " ./run-bugfix.sh run B-001 --dry-run # Inspect generated prompt"
|
|
818
|
+
echo " ./run-bugfix.sh run B-001 --clean # Clean artifacts + reset + run"
|
|
819
|
+
echo " ./run-bugfix.sh run B-001 --no-reset # Retry without resetting status"
|
|
772
820
|
echo " ./run-bugfix.sh run B-001 --timeout 3600 # 1h timeout"
|
|
773
821
|
echo " ./run-bugfix.sh status # Show status"
|
|
774
822
|
echo " MAX_RETRIES=5 ./run-bugfix.sh run # Custom retries"
|
|
@@ -780,7 +828,7 @@ case "${1:-run}" in
|
|
|
780
828
|
if [[ "${1:-}" =~ ^[Bb]-[0-9]+ ]]; then
|
|
781
829
|
run_one "$@"
|
|
782
830
|
else
|
|
783
|
-
main "${1
|
|
831
|
+
main "${1:-.prizmkit/plans/bug-fix-list.json}"
|
|
784
832
|
fi
|
|
785
833
|
;;
|
|
786
834
|
status)
|
|
@@ -790,7 +838,7 @@ case "${1:-run}" in
|
|
|
790
838
|
exit 1
|
|
791
839
|
fi
|
|
792
840
|
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
793
|
-
--bug-list "${2
|
|
841
|
+
--bug-list "${2:-.prizmkit/plans/bug-fix-list.json}" \
|
|
794
842
|
--state-dir "$STATE_DIR" \
|
|
795
843
|
--action status
|
|
796
844
|
;;
|
|
@@ -9,9 +9,9 @@ set -euo pipefail
|
|
|
9
9
|
# from a feature list.
|
|
10
10
|
#
|
|
11
11
|
# Usage:
|
|
12
|
-
# ./run-feature.sh run [feature-list.json] Run all features
|
|
12
|
+
# ./run-feature.sh run [.prizmkit/plans/feature-list.json] Run all features
|
|
13
13
|
# ./run-feature.sh run <feature-id> [options] Run a single feature
|
|
14
|
-
# ./run-feature.sh status [feature-list.json] Show pipeline status
|
|
14
|
+
# ./run-feature.sh status [.prizmkit/plans/feature-list.json] Show pipeline status
|
|
15
15
|
# ./run-feature.sh reset Clear all state
|
|
16
16
|
#
|
|
17
17
|
# Environment Variables:
|
|
@@ -33,7 +33,8 @@ set -euo pipefail
|
|
|
33
33
|
# ============================================================
|
|
34
34
|
|
|
35
35
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
36
|
-
|
|
36
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
37
|
+
STATE_DIR="${PROJECT_ROOT}/.prizmkit/state/features"
|
|
37
38
|
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
38
39
|
|
|
39
40
|
# Configuration (override via environment variables)
|
|
@@ -345,7 +346,7 @@ sys.exit(0)
|
|
|
345
346
|
--max-retries "$max_retries" \
|
|
346
347
|
--action update 2>&1) || {
|
|
347
348
|
log_error "Failed to update feature status: $update_output"
|
|
348
|
-
log_error "feature-list.json may be out of sync. Manual intervention needed."
|
|
349
|
+
log_error ".prizmkit/plans/feature-list.json may be out of sync. Manual intervention needed."
|
|
349
350
|
}
|
|
350
351
|
|
|
351
352
|
# Commit feature status update (pipeline management commit)
|
|
@@ -514,7 +515,7 @@ run_one() {
|
|
|
514
515
|
|
|
515
516
|
# Default feature list
|
|
516
517
|
if [[ -z "$feature_list" ]]; then
|
|
517
|
-
feature_list="feature-list.json"
|
|
518
|
+
feature_list=".prizmkit/plans/feature-list.json"
|
|
518
519
|
fi
|
|
519
520
|
|
|
520
521
|
# Resolve to absolute path
|
|
@@ -542,9 +543,12 @@ run_one() {
|
|
|
542
543
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
543
544
|
log_info "Initializing pipeline state for single-feature run..."
|
|
544
545
|
local init_result
|
|
545
|
-
init_result=$(python3 "$SCRIPTS_DIR/init-pipeline.py" \
|
|
546
|
+
if ! init_result=$(python3 "$SCRIPTS_DIR/init-pipeline.py" \
|
|
546
547
|
--feature-list "$feature_list" \
|
|
547
|
-
--state-dir "$STATE_DIR" 2>&1)
|
|
548
|
+
--state-dir "$STATE_DIR" 2>&1); then
|
|
549
|
+
log_error "Pipeline initialization failed (script error)"
|
|
550
|
+
exit 1
|
|
551
|
+
fi
|
|
548
552
|
|
|
549
553
|
local init_valid
|
|
550
554
|
init_valid=$(echo "$init_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('valid', False))" 2>/dev/null || echo "False")
|
|
@@ -829,7 +833,7 @@ sys.exit(1)
|
|
|
829
833
|
# ============================================================
|
|
830
834
|
|
|
831
835
|
main() {
|
|
832
|
-
local feature_list="${1
|
|
836
|
+
local feature_list="${1:-.prizmkit/plans/feature-list.json}"
|
|
833
837
|
local features_filter="${2:-}"
|
|
834
838
|
|
|
835
839
|
# Resolve to absolute path
|
|
@@ -843,18 +847,18 @@ main() {
|
|
|
843
847
|
if [[ ! -f "$feature_list" ]]; then
|
|
844
848
|
log_error "Feature list not found: $feature_list"
|
|
845
849
|
log_info "Create a feature list first using the feature-planner skill,"
|
|
846
|
-
log_info "or provide a path: ./run-feature.sh run <path-to
|
|
850
|
+
log_info "or provide a path: ./run-feature.sh run <path-to-.prizmkit/plans/feature-list.json>"
|
|
847
851
|
exit 1
|
|
848
852
|
fi
|
|
849
853
|
|
|
850
|
-
# Validate feature-list.json is at project root
|
|
854
|
+
# Validate .prizmkit/plans/feature-list.json is at project root
|
|
851
855
|
local fl_dir
|
|
852
856
|
fl_dir="$(cd "$(dirname "$feature_list")" && pwd)"
|
|
853
857
|
local project_root
|
|
854
858
|
project_root="$(pwd)"
|
|
855
859
|
if [[ "$fl_dir" != "$project_root" ]]; then
|
|
856
|
-
log_warn "feature-list.json is not at project root ($project_root), found at $fl_dir"
|
|
857
|
-
log_warn "Pipeline expects feature-list.json at project root. Proceeding but results may be unstable."
|
|
860
|
+
log_warn ".prizmkit/plans/feature-list.json is not at project root ($project_root), found at $fl_dir"
|
|
861
|
+
log_warn "Pipeline expects .prizmkit/plans/feature-list.json at project root. Proceeding but results may be unstable."
|
|
858
862
|
fi
|
|
859
863
|
|
|
860
864
|
check_dependencies
|
|
@@ -885,7 +889,7 @@ main() {
|
|
|
885
889
|
local _gitignore_path
|
|
886
890
|
_gitignore_path="$(cd "$SCRIPT_DIR/.." && pwd)/.gitignore"
|
|
887
891
|
local _state_rel
|
|
888
|
-
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo "
|
|
892
|
+
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo ".prizmkit/state/features")
|
|
889
893
|
if [[ -f "$_gitignore_path" ]]; then
|
|
890
894
|
if ! grep -qF "$_state_rel" "$_gitignore_path" 2>/dev/null; then
|
|
891
895
|
printf '\n# Pipeline runtime state (auto-added by dev-pipeline)\n%s/\n' "$_state_rel" >> "$_gitignore_path"
|
|
@@ -965,8 +969,13 @@ for f in data.get('stuck_features', []):
|
|
|
965
969
|
if [[ -n "$features_filter" ]]; then
|
|
966
970
|
_get_next_args+=(--features "$features_filter")
|
|
967
971
|
fi
|
|
968
|
-
next_feature=$(python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
969
|
-
"${_get_next_args[@]}" 2>/dev/null)
|
|
972
|
+
if ! next_feature=$(python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
973
|
+
"${_get_next_args[@]}" 2>/dev/null); then
|
|
974
|
+
|
|
975
|
+
log_error "Failed to get next feature"
|
|
976
|
+
break
|
|
977
|
+
fi
|
|
978
|
+
|
|
970
979
|
|
|
971
980
|
if [[ "$next_feature" == "PIPELINE_COMPLETE" ]]; then
|
|
972
981
|
echo ""
|
|
@@ -1150,10 +1159,10 @@ show_help() {
|
|
|
1150
1159
|
echo "Usage: $0 <command> [options]"
|
|
1151
1160
|
echo ""
|
|
1152
1161
|
echo "Commands:"
|
|
1153
|
-
echo " run [feature-list.json] [--features <filter>] Run features (all or filtered subset)"
|
|
1162
|
+
echo " run [.prizmkit/plans/feature-list.json] [--features <filter>] Run features (all or filtered subset)"
|
|
1154
1163
|
echo " run <feature-id> [options] Run a single feature"
|
|
1155
|
-
echo " status [feature-list.json] Show pipeline status"
|
|
1156
|
-
echo " unskip [feature-id] [feature-list.json] Reset auto-skipped/failed features"
|
|
1164
|
+
echo " status [.prizmkit/plans/feature-list.json] Show pipeline status"
|
|
1165
|
+
echo " unskip [feature-id] [.prizmkit/plans/feature-list.json] Reset auto-skipped/failed features"
|
|
1157
1166
|
echo " test-cli Test AI CLI: show detected CLI, version, and model"
|
|
1158
1167
|
echo " reset Clear all state and start fresh"
|
|
1159
1168
|
echo " help Show this help message"
|
|
@@ -1209,7 +1218,7 @@ case "${1:-run}" in
|
|
|
1209
1218
|
run_one "$@"
|
|
1210
1219
|
else
|
|
1211
1220
|
# Parse positional and --features flag
|
|
1212
|
-
_run_feature_list="feature-list.json"
|
|
1221
|
+
_run_feature_list=".prizmkit/plans/feature-list.json"
|
|
1213
1222
|
_run_features_filter=""
|
|
1214
1223
|
while [[ $# -gt 0 ]]; do
|
|
1215
1224
|
case "$1" in
|
|
@@ -1238,7 +1247,7 @@ case "${1:-run}" in
|
|
|
1238
1247
|
exit 1
|
|
1239
1248
|
fi
|
|
1240
1249
|
python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
1241
|
-
--feature-list "${2
|
|
1250
|
+
--feature-list "${2:-.prizmkit/plans/feature-list.json}" \
|
|
1242
1251
|
--state-dir "$STATE_DIR" \
|
|
1243
1252
|
--action status
|
|
1244
1253
|
;;
|
|
@@ -1311,7 +1320,7 @@ case "${1:-run}" in
|
|
|
1311
1320
|
log_error "No pipeline state found. Run './run-feature.sh run' first."
|
|
1312
1321
|
exit 1
|
|
1313
1322
|
fi
|
|
1314
|
-
_unskip_feature_list="feature-list.json"
|
|
1323
|
+
_unskip_feature_list=".prizmkit/plans/feature-list.json"
|
|
1315
1324
|
_unskip_feature_id=""
|
|
1316
1325
|
shift || true
|
|
1317
1326
|
# Parse arguments: optional feature-id and feature-list path
|
|
@@ -5,12 +5,12 @@ set -euo pipefail
|
|
|
5
5
|
# dev-pipeline/run-refactor.sh - Autonomous Refactor Pipeline Runner
|
|
6
6
|
#
|
|
7
7
|
# Drives the prizm-dev-team through iterative AI CLI sessions to
|
|
8
|
-
# execute refactors from a refactor-list.json specification.
|
|
8
|
+
# execute refactors from a .prizmkit/plans/refactor-list.json specification.
|
|
9
9
|
#
|
|
10
10
|
# Usage:
|
|
11
|
-
# ./run-refactor.sh run [refactor-list.json] Run all refactors
|
|
11
|
+
# ./run-refactor.sh run [.prizmkit/plans/refactor-list.json] Run all refactors
|
|
12
12
|
# ./run-refactor.sh run <refactor-id> [options] Run a single refactor
|
|
13
|
-
# ./run-refactor.sh status [refactor-list.json] Show pipeline status
|
|
13
|
+
# ./run-refactor.sh status [.prizmkit/plans/refactor-list.json] Show pipeline status
|
|
14
14
|
# ./run-refactor.sh reset Clear all state
|
|
15
15
|
#
|
|
16
16
|
# Environment Variables:
|
|
@@ -31,7 +31,8 @@ set -euo pipefail
|
|
|
31
31
|
# ============================================================
|
|
32
32
|
|
|
33
33
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
34
|
-
|
|
34
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
35
|
+
STATE_DIR="${PROJECT_ROOT}/.prizmkit/state/refactor"
|
|
35
36
|
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
36
37
|
|
|
37
38
|
# Configuration
|
|
@@ -239,7 +240,7 @@ spawn_and_wait_session() {
|
|
|
239
240
|
--max-retries "$max_retries" \
|
|
240
241
|
--action update >/dev/null 2>&1 || true
|
|
241
242
|
|
|
242
|
-
# Commit refactor-list.json status update (pipeline management commit)
|
|
243
|
+
# Commit .prizmkit/plans/refactor-list.json status update (pipeline management commit)
|
|
243
244
|
if ! git -C "$project_root" diff --quiet "$refactor_list" 2>/dev/null; then
|
|
244
245
|
git -C "$project_root" add "$refactor_list"
|
|
245
246
|
git -C "$project_root" commit --no-verify -m "chore($refactor_id): update refactor status" 2>/dev/null || true
|
|
@@ -337,7 +338,7 @@ run_one() {
|
|
|
337
338
|
fi
|
|
338
339
|
|
|
339
340
|
if [[ -z "$refactor_list" ]]; then
|
|
340
|
-
refactor_list="refactor-list.json"
|
|
341
|
+
refactor_list=".prizmkit/plans/refactor-list.json"
|
|
341
342
|
fi
|
|
342
343
|
if [[ ! "$refactor_list" = /* ]]; then
|
|
343
344
|
refactor_list="$(pwd)/$refactor_list"
|
|
@@ -366,7 +367,7 @@ run_one() {
|
|
|
366
367
|
local _gitignore_path
|
|
367
368
|
_gitignore_path="$(cd "$SCRIPT_DIR/.." && pwd)/.gitignore"
|
|
368
369
|
local _state_rel
|
|
369
|
-
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo "
|
|
370
|
+
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo ".prizmkit/state/refactor")
|
|
370
371
|
if [[ -f "$_gitignore_path" ]]; then
|
|
371
372
|
if ! grep -qF "$_state_rel" "$_gitignore_path" 2>/dev/null; then
|
|
372
373
|
printf '\n# Pipeline runtime state (auto-added by dev-pipeline)\n%s/\n' "$_state_rel" >> "$_gitignore_path"
|
|
@@ -521,7 +522,7 @@ sys.exit(1)
|
|
|
521
522
|
# ============================================================
|
|
522
523
|
|
|
523
524
|
main() {
|
|
524
|
-
local refactor_list="${1
|
|
525
|
+
local refactor_list="${1:-.prizmkit/plans/refactor-list.json}"
|
|
525
526
|
|
|
526
527
|
if [[ ! "$refactor_list" = /* ]]; then
|
|
527
528
|
refactor_list="$(pwd)/$refactor_list"
|
|
@@ -531,7 +532,7 @@ main() {
|
|
|
531
532
|
if [[ ! -f "$refactor_list" ]]; then
|
|
532
533
|
log_error "Refactor list not found: $refactor_list"
|
|
533
534
|
log_info "Create a refactor list first using the refactor-planner skill,"
|
|
534
|
-
log_info "or provide a path: ./run-refactor.sh run <path-to
|
|
535
|
+
log_info "or provide a path: ./run-refactor.sh run <path-to-.prizmkit/plans/refactor-list.json>"
|
|
535
536
|
exit 1
|
|
536
537
|
fi
|
|
537
538
|
|
|
@@ -563,7 +564,7 @@ main() {
|
|
|
563
564
|
local _gitignore_path
|
|
564
565
|
_gitignore_path="$(cd "$SCRIPT_DIR/.." && pwd)/.gitignore"
|
|
565
566
|
local _state_rel
|
|
566
|
-
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo "
|
|
567
|
+
_state_rel=$(python3 -c "import os; print(os.path.relpath('$STATE_DIR', '$(cd "$SCRIPT_DIR/.." && pwd)'))" 2>/dev/null || echo ".prizmkit/state/refactor")
|
|
567
568
|
if [[ -f "$_gitignore_path" ]]; then
|
|
568
569
|
if ! grep -qF "$_state_rel" "$_gitignore_path" 2>/dev/null; then
|
|
569
570
|
printf '\n# Pipeline runtime state (auto-added by dev-pipeline)\n%s/\n' "$_state_rel" >> "$_gitignore_path"
|
|
@@ -622,11 +623,14 @@ main() {
|
|
|
622
623
|
while true; do
|
|
623
624
|
# Find next refactor to process (dependency-topological order)
|
|
624
625
|
local next_refactor
|
|
625
|
-
next_refactor=$(python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
626
|
+
if ! next_refactor=$(python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
626
627
|
--refactor-list "$refactor_list" \
|
|
627
628
|
--state-dir "$STATE_DIR" \
|
|
628
629
|
--max-retries "$MAX_RETRIES" \
|
|
629
|
-
--action get_next 2>/dev/null)
|
|
630
|
+
--action get_next 2>/dev/null); then
|
|
631
|
+
log_error "Failed to get next refactor"
|
|
632
|
+
break
|
|
633
|
+
fi
|
|
630
634
|
|
|
631
635
|
if [[ "$next_refactor" == "PIPELINE_COMPLETE" ]]; then
|
|
632
636
|
echo ""
|
|
@@ -720,9 +724,9 @@ show_help() {
|
|
|
720
724
|
echo "Usage: $0 <command> [options]"
|
|
721
725
|
echo ""
|
|
722
726
|
echo "Commands:"
|
|
723
|
-
echo " run [refactor-list.json] Run all refactors in dependency-topological order"
|
|
727
|
+
echo " run [.prizmkit/plans/refactor-list.json] Run all refactors in dependency-topological order"
|
|
724
728
|
echo " run <refactor-id> [options] Run a single refactor"
|
|
725
|
-
echo " status [refactor-list.json] Show refactor pipeline status"
|
|
729
|
+
echo " status [.prizmkit/plans/refactor-list.json] Show refactor pipeline status"
|
|
726
730
|
echo " reset Clear all refactor state"
|
|
727
731
|
echo " help Show this help message"
|
|
728
732
|
echo ""
|
|
@@ -743,7 +747,7 @@ show_help() {
|
|
|
743
747
|
echo ""
|
|
744
748
|
echo "Examples:"
|
|
745
749
|
echo " ./run-refactor.sh run # Run all refactors"
|
|
746
|
-
echo " ./run-refactor.sh run refactor-list.json # Custom refactor list"
|
|
750
|
+
echo " ./run-refactor.sh run .prizmkit/plans/refactor-list.json # Custom refactor list"
|
|
747
751
|
echo " ./run-refactor.sh run R-001 --dry-run # Inspect generated prompt"
|
|
748
752
|
echo " ./run-refactor.sh run R-001 --timeout 3600 # 1h timeout"
|
|
749
753
|
echo " ./run-refactor.sh status # Show status"
|
|
@@ -757,7 +761,7 @@ case "${1:-run}" in
|
|
|
757
761
|
if [[ "${1:-}" =~ ^[Rr]-[0-9]+ ]]; then
|
|
758
762
|
run_one "$@"
|
|
759
763
|
else
|
|
760
|
-
main "${1
|
|
764
|
+
main "${1:-.prizmkit/plans/refactor-list.json}"
|
|
761
765
|
fi
|
|
762
766
|
;;
|
|
763
767
|
status)
|
|
@@ -767,7 +771,7 @@ case "${1:-run}" in
|
|
|
767
771
|
exit 1
|
|
768
772
|
fi
|
|
769
773
|
python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
770
|
-
--refactor-list "${2
|
|
774
|
+
--refactor-list "${2:-.prizmkit/plans/refactor-list.json}" \
|
|
771
775
|
--state-dir "$STATE_DIR" \
|
|
772
776
|
--action status
|
|
773
777
|
;;
|
|
@@ -9,8 +9,8 @@ Policies:
|
|
|
9
9
|
until within threshold.
|
|
10
10
|
|
|
11
11
|
Usage:
|
|
12
|
-
python3 cleanup-logs.py --state-dir
|
|
13
|
-
python3 cleanup-logs.py --state-dir
|
|
12
|
+
python3 cleanup-logs.py --state-dir .prizmkit/state/features
|
|
13
|
+
python3 cleanup-logs.py --state-dir .prizmkit/state/bugfix --retention-days 30 --max-total-mb 2048
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
import argparse
|
|
@@ -35,7 +35,7 @@ def parse_args():
|
|
|
35
35
|
parser.add_argument(
|
|
36
36
|
"--state-dir",
|
|
37
37
|
required=True,
|
|
38
|
-
help="Path to the state
|
|
38
|
+
help="Path to the state directory (default: .prizmkit/state/features)",
|
|
39
39
|
)
|
|
40
40
|
parser.add_argument(
|
|
41
41
|
"--feature-id",
|
|
@@ -57,7 +57,7 @@ def parse_args():
|
|
|
57
57
|
parser.add_argument(
|
|
58
58
|
"--feature-list",
|
|
59
59
|
default=None,
|
|
60
|
-
help="Path to feature-list.json (overrides pipeline.json reference)",
|
|
60
|
+
help="Path to .prizmkit/plans/feature-list.json (overrides pipeline.json reference)",
|
|
61
61
|
)
|
|
62
62
|
return parser.parse_args()
|
|
63
63
|
|
|
@@ -285,7 +285,7 @@ def check_dependency_deadlock(feature_id, feature_list_data, state_dir):
|
|
|
285
285
|
|
|
286
286
|
|
|
287
287
|
def find_feature_list(state_dir):
|
|
288
|
-
"""Attempt to locate and load feature-list.json via pipeline.json reference.
|
|
288
|
+
"""Attempt to locate and load .prizmkit/plans/feature-list.json via pipeline.json reference.
|
|
289
289
|
|
|
290
290
|
Resolves feature_list_path relative to state_dir when it is a relative path,
|
|
291
291
|
so that pipeline.json is portable across machines and directory structures.
|
|
@@ -38,13 +38,13 @@ def parse_args():
|
|
|
38
38
|
parser = argparse.ArgumentParser(
|
|
39
39
|
description=(
|
|
40
40
|
"Generate a session-specific bootstrap prompt from a template "
|
|
41
|
-
"and feature-list.json."
|
|
41
|
+
"and .prizmkit/plans/feature-list.json."
|
|
42
42
|
)
|
|
43
43
|
)
|
|
44
44
|
parser.add_argument(
|
|
45
45
|
"--feature-list",
|
|
46
46
|
required=True,
|
|
47
|
-
help="Path to feature-list.json",
|
|
47
|
+
help="Path to .prizmkit/plans/feature-list.json",
|
|
48
48
|
)
|
|
49
49
|
parser.add_argument(
|
|
50
50
|
"--feature-id",
|
|
@@ -348,7 +348,7 @@ def get_prev_session_status(state_dir, feature_id):
|
|
|
348
348
|
|
|
349
349
|
|
|
350
350
|
def _read_project_brief(project_root):
|
|
351
|
-
"""Read project-brief.md from
|
|
351
|
+
"""Read project-brief.md from new or old location with fallback.
|
|
352
352
|
|
|
353
353
|
Returns the file content as a string, or a fallback message if absent.
|
|
354
354
|
This brief is generated by app-planner during interactive planning and
|
|
@@ -356,13 +356,25 @@ def _read_project_brief(project_root):
|
|
|
356
356
|
marked [ ] for pending or [x] for completed. Feature sessions should mark
|
|
357
357
|
items [x] and append key file paths when implementing relevant ideas.
|
|
358
358
|
"""
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
359
|
+
# Check both new and old paths for backward compatibility
|
|
360
|
+
new_path = os.path.join(project_root, ".prizmkit", "plans", "project-brief.md")
|
|
361
|
+
old_path = os.path.join(project_root, "project-brief.md")
|
|
362
|
+
|
|
363
|
+
for brief_path in [new_path, old_path]:
|
|
364
|
+
if os.path.isfile(brief_path):
|
|
365
|
+
try:
|
|
366
|
+
with open(brief_path, "r", encoding="utf-8") as f:
|
|
367
|
+
content = f.read().strip()
|
|
368
|
+
if brief_path == old_path:
|
|
369
|
+
# Warn user about old path
|
|
370
|
+
import sys
|
|
371
|
+
print("⚠️ Migration notice: project-brief.md found in root. "
|
|
372
|
+
"Please move to .prizmkit/plans/project-brief.md",
|
|
373
|
+
file=sys.stderr)
|
|
374
|
+
return content
|
|
375
|
+
except IOError:
|
|
376
|
+
return "(project-brief.md exists but could not be read)"
|
|
377
|
+
|
|
366
378
|
return "(No project brief available)"
|
|
367
379
|
|
|
368
380
|
|
|
@@ -1179,12 +1191,12 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1179
1191
|
validator_scripts_dir = os.path.join(project_root, "dev-pipeline", "scripts")
|
|
1180
1192
|
init_script_path = os.path.join(validator_scripts_dir, "init-dev-team.py")
|
|
1181
1193
|
|
|
1182
|
-
# Session status path (relative to
|
|
1194
|
+
# Session status path (relative to project root)
|
|
1183
1195
|
session_status_path = os.path.join(
|
|
1184
|
-
"
|
|
1196
|
+
".prizmkit", "state", "features", args.feature_id,
|
|
1185
1197
|
"sessions", args.session_id, "session-status.json",
|
|
1186
1198
|
)
|
|
1187
|
-
# Make it
|
|
1199
|
+
# Make it absolute from project root
|
|
1188
1200
|
session_status_abs = os.path.join(project_root, session_status_path)
|
|
1189
1201
|
|
|
1190
1202
|
prev_status = get_prev_session_status(args.state_dir, args.feature_id)
|
|
@@ -1221,7 +1233,7 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1221
1233
|
critic_enabled = bool(feature.get("critic", False))
|
|
1222
1234
|
|
|
1223
1235
|
# Determine critic count (from feature field, default 1)
|
|
1224
|
-
# Multi-critic voting (3) must be explicitly set by the user in feature-list.json
|
|
1236
|
+
# Multi-critic voting (3) must be explicitly set by the user in .prizmkit/plans/feature-list.json
|
|
1225
1237
|
critic_count = feature.get("critic_count", 1)
|
|
1226
1238
|
|
|
1227
1239
|
# Guard: if critic enabled but agent file missing, force disable and warn
|