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.
Files changed (63) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/README.md +65 -65
  3. package/bundled/dev-pipeline/assets/feature-list-example.json +2 -2
  4. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +11 -10
  5. package/bundled/dev-pipeline/launch-feature-daemon.sh +12 -11
  6. package/bundled/dev-pipeline/launch-refactor-daemon.sh +11 -10
  7. package/bundled/dev-pipeline/reset-bug.sh +305 -0
  8. package/bundled/dev-pipeline/reset-feature.sh +9 -8
  9. package/bundled/dev-pipeline/reset-refactor.sh +10 -9
  10. package/bundled/dev-pipeline/retry-bugfix.sh +7 -6
  11. package/bundled/dev-pipeline/retry-feature.sh +7 -6
  12. package/bundled/dev-pipeline/retry-refactor.sh +7 -6
  13. package/bundled/dev-pipeline/run-bugfix.sh +71 -23
  14. package/bundled/dev-pipeline/run-feature.sh +30 -21
  15. package/bundled/dev-pipeline/run-refactor.sh +21 -17
  16. package/bundled/dev-pipeline/scripts/cleanup-logs.py +2 -2
  17. package/bundled/dev-pipeline/scripts/detect-stuck.py +3 -3
  18. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +26 -14
  19. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +6 -6
  20. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +6 -6
  21. package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +4 -4
  22. package/bundled/dev-pipeline/scripts/init-pipeline.py +26 -12
  23. package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +4 -4
  24. package/bundled/dev-pipeline/scripts/update-bug-status.py +10 -10
  25. package/bundled/dev-pipeline/scripts/update-feature-status.py +31 -31
  26. package/bundled/dev-pipeline/scripts/update-refactor-status.py +8 -8
  27. package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +111 -31
  28. package/bundled/dev-pipeline/templates/feature-list-schema.json +91 -25
  29. package/bundled/dev-pipeline/templates/refactor-list-schema.json +107 -28
  30. package/bundled/dev-pipeline/tests/test_auto_skip.py +1 -1
  31. package/bundled/skills/_metadata.json +10 -2
  32. package/bundled/skills/app-planner/SKILL.md +24 -13
  33. package/bundled/skills/app-planner/references/project-brief-guide.md +1 -1
  34. package/bundled/skills/bug-fix-workflow/SKILL.md +7 -5
  35. package/bundled/skills/bug-planner/SKILL.md +80 -25
  36. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +3 -3
  37. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +38 -33
  38. package/bundled/skills/feature-pipeline-launcher/SKILL.md +33 -33
  39. package/bundled/skills/feature-pipeline-launcher/scripts/preflight-check.py +3 -3
  40. package/bundled/skills/feature-planner/SKILL.md +96 -24
  41. package/bundled/skills/feature-planner/references/error-recovery.md +9 -9
  42. package/bundled/skills/feature-planner/scripts/validate-and-generate.py +25 -24
  43. package/bundled/skills/feature-workflow/SKILL.md +23 -20
  44. package/bundled/skills/prizmkit-committer/SKILL.md +1 -0
  45. package/bundled/skills/prizmkit-deploy/SKILL.md +1 -0
  46. package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +1 -1
  47. package/bundled/skills/prizmkit-implement/SKILL.md +1 -1
  48. package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +4 -4
  49. package/bundled/skills/prizmkit-plan/SKILL.md +3 -3
  50. package/bundled/skills/prizmkit-retrospective/SKILL.md +40 -3
  51. package/bundled/skills/prizmkit-verify/SKILL.md +281 -0
  52. package/bundled/skills/prizmkit-verify/scripts/verify-light.py +402 -0
  53. package/bundled/skills/recovery-workflow/SKILL.md +15 -14
  54. package/bundled/skills/recovery-workflow/evals/evals.json +5 -5
  55. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +43 -10
  56. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +38 -34
  57. package/bundled/skills/refactor-planner/SKILL.md +74 -24
  58. package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +17 -17
  59. package/bundled/skills/refactor-workflow/SKILL.md +24 -20
  60. package/package.json +1 -1
  61. package/src/clean.js +4 -4
  62. package/src/gitignore-template.js +7 -8
  63. 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
- STATE_DIR="$SCRIPT_DIR/bugfix-state"
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 "dev-pipeline/bugfix-state")
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
- # Reset bug status
441
- python3 "$SCRIPTS_DIR/update-bug-status.py" \
442
- --bug-list "$bug_list" \
443
- --state-dir "$STATE_DIR" \
444
- --bug-id "$bug_id" \
445
- --action reset >/dev/null 2>&1 || true
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:-bug-fix-list.json}"
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-bug-fix-list.json>"
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 "dev-pipeline/bugfix-state")
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) || true
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:-bug-fix-list.json}"
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:-bug-fix-list.json}" \
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
- STATE_DIR="$SCRIPT_DIR/state"
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:-feature-list.json}"
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-feature-list.json>"
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 "dev-pipeline/state")
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) || true
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:-feature-list.json}" \
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
- STATE_DIR="$SCRIPT_DIR/refactor-state"
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 "dev-pipeline/refactor-state")
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:-refactor-list.json}"
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-refactor-list.json>"
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 "dev-pipeline/refactor-state")
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) || true
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:-refactor-list.json}"
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:-refactor-list.json}" \
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 dev-pipeline/state
13
- python3 cleanup-logs.py --state-dir dev-pipeline/bugfix-state --retention-days 30 --max-total-mb 2048
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/ directory",
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 project root if it exists.
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
- brief_path = os.path.join(project_root, "project-brief.md")
360
- if os.path.isfile(brief_path):
361
- try:
362
- with open(brief_path, "r", encoding="utf-8") as f:
363
- return f.read().strip()
364
- except IOError:
365
- return "(project-brief.md exists but could not be read)"
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 dev-pipeline/)
1194
+ # Session status path (relative to project root)
1183
1195
  session_status_path = os.path.join(
1184
- "dev-pipeline", "state", "features", args.feature_id,
1196
+ ".prizmkit", "state", "features", args.feature_id,
1185
1197
  "sessions", args.session_id, "session-status.json",
1186
1198
  )
1187
- # Make it relative from project root
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