prizmkit 1.1.8 → 1.1.9

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 (123) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codebuddy/skill-adapter.js +21 -7
  3. package/bundled/agents/prizm-dev-team-reviewer.md +53 -173
  4. package/bundled/dev-pipeline/.env.example +45 -0
  5. package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +535 -0
  6. package/bundled/dev-pipeline/assets/feature-list-example.json +0 -1
  7. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +57 -12
  8. package/bundled/dev-pipeline/launch-feature-daemon.sh +3 -1
  9. package/bundled/dev-pipeline/launch-refactor-daemon.sh +57 -12
  10. package/bundled/dev-pipeline/lib/branch.sh +6 -1
  11. package/bundled/dev-pipeline/lib/common.sh +71 -0
  12. package/bundled/dev-pipeline/lib/heartbeat.sh +2 -2
  13. package/bundled/dev-pipeline/retry-bugfix.sh +60 -23
  14. package/bundled/dev-pipeline/retry-feature.sh +47 -12
  15. package/bundled/dev-pipeline/retry-refactor.sh +105 -23
  16. package/bundled/dev-pipeline/run-bugfix.sh +265 -44
  17. package/bundled/dev-pipeline/run-feature.sh +35 -1
  18. package/bundled/dev-pipeline/run-refactor.sh +376 -51
  19. package/bundled/dev-pipeline/scripts/check-session-status.py +24 -1
  20. package/bundled/dev-pipeline/scripts/detect-stuck.py +195 -85
  21. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +31 -19
  22. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +19 -3
  23. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +98 -11
  24. package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +30 -5
  25. package/bundled/dev-pipeline/scripts/init-pipeline.py +3 -3
  26. package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +15 -4
  27. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +1 -5
  28. package/bundled/dev-pipeline/scripts/patch-completion-notes.py +191 -0
  29. package/bundled/dev-pipeline/scripts/update-bug-status.py +159 -14
  30. package/bundled/dev-pipeline/scripts/update-feature-status.py +79 -37
  31. package/bundled/dev-pipeline/scripts/update-refactor-status.py +343 -13
  32. package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +1 -1
  33. package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +7 -11
  34. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +41 -7
  35. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +27 -3
  36. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +43 -19
  37. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +54 -26
  38. package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +5 -14
  39. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +36 -25
  40. package/bundled/dev-pipeline/templates/feature-list-schema.json +23 -11
  41. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +270 -0
  42. package/bundled/dev-pipeline/templates/refactor-list-schema.json +10 -2
  43. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +3 -1
  44. package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +1 -0
  45. package/bundled/dev-pipeline/templates/sections/feature-context.md +2 -0
  46. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +29 -2
  47. package/bundled/dev-pipeline/templates/sections/phase-commit.md +22 -0
  48. package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +2 -2
  49. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +8 -6
  50. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +7 -5
  51. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -3
  52. package/bundled/skills/_metadata.json +5 -22
  53. package/bundled/skills/app-planner/SKILL.md +92 -66
  54. package/bundled/skills/app-planner/assets/app-design-guide.md +1 -1
  55. package/bundled/skills/app-planner/references/architecture-decisions.md +1 -1
  56. package/bundled/skills/app-planner/references/project-brief-guide.md +69 -66
  57. package/bundled/skills/bug-fix-workflow/SKILL.md +47 -4
  58. package/bundled/skills/bug-planner/SKILL.md +130 -188
  59. package/bundled/skills/bug-planner/assets/bug-confirmation-template.md +43 -0
  60. package/bundled/skills/bug-planner/references/critic-and-verification.md +44 -0
  61. package/bundled/skills/bug-planner/references/error-recovery.md +73 -0
  62. package/bundled/skills/bug-planner/references/input-formats.md +53 -0
  63. package/bundled/skills/bug-planner/references/schema-validation.md +25 -0
  64. package/bundled/skills/bug-planner/references/severity-rules.md +16 -0
  65. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +1 -5
  66. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +5 -10
  67. package/bundled/skills/feature-pipeline-launcher/SKILL.md +16 -3
  68. package/bundled/skills/feature-planner/SKILL.md +33 -122
  69. package/bundled/skills/feature-planner/assets/evaluation-guide.md +1 -1
  70. package/bundled/skills/feature-planner/assets/planning-guide.md +21 -5
  71. package/bundled/skills/feature-planner/references/browser-interaction.md +2 -4
  72. package/bundled/skills/feature-planner/references/completeness-review.md +57 -0
  73. package/bundled/skills/feature-planner/references/error-recovery.md +15 -34
  74. package/bundled/skills/feature-planner/references/incremental-feature-planning.md +1 -1
  75. package/bundled/skills/feature-planner/references/new-project-planning.md +2 -2
  76. package/bundled/skills/feature-planner/scripts/validate-and-generate.py +1 -2
  77. package/bundled/skills/feature-workflow/SKILL.md +3 -4
  78. package/bundled/skills/prizm-kit/SKILL.md +39 -49
  79. package/bundled/skills/prizmkit-code-review/SKILL.md +51 -64
  80. package/bundled/skills/prizmkit-code-review/rules/dimensions.md +85 -0
  81. package/bundled/skills/prizmkit-code-review/rules/fix-strategy.md +11 -11
  82. package/bundled/skills/prizmkit-committer/SKILL.md +3 -31
  83. package/bundled/skills/prizmkit-deploy/SKILL.md +34 -31
  84. package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +1 -1
  85. package/bundled/skills/prizmkit-implement/SKILL.md +35 -68
  86. package/bundled/skills/prizmkit-init/SKILL.md +112 -65
  87. package/bundled/skills/prizmkit-init/assets/project-brief-template.md +82 -0
  88. package/bundled/skills/prizmkit-plan/SKILL.md +120 -79
  89. package/bundled/skills/prizmkit-plan/assets/plan-template.md +28 -18
  90. package/bundled/skills/prizmkit-plan/assets/spec-template.md +28 -11
  91. package/bundled/skills/prizmkit-plan/references/clarify-guide.md +3 -3
  92. package/bundled/skills/prizmkit-plan/references/verification-checklist.md +60 -0
  93. package/bundled/skills/prizmkit-prizm-docs/SKILL.md +10 -81
  94. package/bundled/skills/prizmkit-prizm-docs/assets/{PRIZM-SPEC.md → prizm-docs-format.md} +41 -526
  95. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +46 -0
  96. package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +16 -0
  97. package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +14 -0
  98. package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +19 -0
  99. package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +17 -0
  100. package/bundled/skills/prizmkit-retrospective/SKILL.md +27 -65
  101. package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -4
  102. package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +7 -25
  103. package/bundled/skills/recovery-workflow/SKILL.md +8 -8
  104. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +17 -9
  105. package/bundled/skills/refactor-planner/SKILL.md +23 -41
  106. package/bundled/skills/refactor-workflow/SKILL.md +1 -2
  107. package/bundled/team/prizm-dev-team.json +1 -1
  108. package/bundled/{skills/prizm-kit/assets → templates}/project-memory-template.md +1 -1
  109. package/package.json +1 -1
  110. package/src/clean.js +0 -1
  111. package/src/gitignore-template.js +0 -1
  112. package/src/scaffold.js +10 -3
  113. package/bundled/dev-pipeline/templates/agent-prompts/reviewer-analyze.md +0 -5
  114. package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +0 -19
  115. package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +0 -19
  116. package/bundled/skills/app-planner/references/project-conventions.md +0 -93
  117. package/bundled/skills/prizmkit-analyze/SKILL.md +0 -207
  118. package/bundled/skills/prizmkit-code-review/rules/dimensions-bugfix.md +0 -25
  119. package/bundled/skills/prizmkit-code-review/rules/dimensions-feature.md +0 -43
  120. package/bundled/skills/prizmkit-code-review/rules/dimensions-refactor.md +0 -25
  121. package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +0 -69
  122. package/bundled/skills/prizmkit-verify/SKILL.md +0 -281
  123. package/bundled/skills/prizmkit-verify/scripts/verify-light.py +0 -402
@@ -24,6 +24,8 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
24
24
 
25
25
  SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
26
26
  HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
27
+ AUTO_PUSH=${AUTO_PUSH:-0}
28
+ DEV_BRANCH=${DEV_BRANCH:-""}
27
29
 
28
30
  # Source shared common helpers (CLI/platform detection + logs + deps)
29
31
  source "$SCRIPT_DIR/lib/common.sh"
@@ -32,6 +34,9 @@ prizm_detect_cli_and_platform
32
34
  # Source shared heartbeat library
33
35
  source "$SCRIPT_DIR/lib/heartbeat.sh"
34
36
 
37
+ # Source shared branch library
38
+ source "$SCRIPT_DIR/lib/branch.sh"
39
+
35
40
  # Detect stream-json support
36
41
  detect_stream_json_support "$CLI_CMD"
37
42
 
@@ -116,15 +121,31 @@ sys.exit(1)
116
121
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
117
122
  ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
118
123
 
119
- log_info "Cleaning $REFACTOR_ID artifacts for full restart..."
120
- python3 "$SCRIPTS_DIR/update-refactor-status.py" \
121
- --refactor-list "$REFACTOR_LIST" \
122
- --state-dir "$STATE_DIR" \
123
- --refactor-id "$REFACTOR_ID" \
124
- --project-root "$PROJECT_ROOT" \
125
- --action clean >/dev/null 2>&1 || {
126
- log_warn "Failed to clean refactor artifacts (continuing with fresh session only)"
127
- }
124
+ # Branch tracking (for cleanup on interrupt)
125
+ _DEV_BRANCH_NAME=""
126
+
127
+ log_info "Reading retry state for $REFACTOR_ID..."
128
+ RETRY_COUNT=$(python3 -c "
129
+ import json, os
130
+ status_path = os.path.join('$STATE_DIR', 'refactors', '$REFACTOR_ID', 'status.json')
131
+ if os.path.isfile(status_path):
132
+ with open(status_path) as f:
133
+ d = json.load(f)
134
+ print(d.get('retry_count', 0))
135
+ else:
136
+ print(0)
137
+ " 2>/dev/null || echo "0")
138
+ RESUME_PHASE=$(python3 -c "
139
+ import json, os
140
+ status_path = os.path.join('$STATE_DIR', 'refactors', '$REFACTOR_ID', 'status.json')
141
+ if os.path.isfile(status_path):
142
+ with open(status_path) as f:
143
+ d = json.load(f)
144
+ print(d.get('resume_from_phase') or 'null')
145
+ else:
146
+ print('null')
147
+ " 2>/dev/null || echo "null")
148
+ log_info "Retry count: $RETRY_COUNT, Resume phase: $RESUME_PHASE"
128
149
 
129
150
  # ============================================================
130
151
  # Generate bootstrap prompt
@@ -138,28 +159,57 @@ mkdir -p "$SESSION_DIR/logs"
138
159
  BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
139
160
 
140
161
  log_info "Generating refactor bootstrap prompt..."
141
- python3 "$SCRIPTS_DIR/generate-refactor-prompt.py" \
142
- --refactor-list "$REFACTOR_LIST" \
143
- --refactor-id "$REFACTOR_ID" \
144
- --session-id "$SESSION_ID" \
145
- --run-id "$RUN_ID" \
146
- --retry-count 0 \
147
- --resume-phase "null" \
148
- --state-dir "$STATE_DIR" \
149
- --output "$BOOTSTRAP_PROMPT" >/dev/null 2>&1
162
+ GEN_ARGS=(
163
+ --refactor-list "$REFACTOR_LIST"
164
+ --refactor-id "$REFACTOR_ID"
165
+ --session-id "$SESSION_ID"
166
+ --run-id "$RUN_ID"
167
+ --retry-count "$RETRY_COUNT"
168
+ --resume-phase "$RESUME_PHASE"
169
+ --state-dir "$STATE_DIR"
170
+ --output "$BOOTSTRAP_PROMPT"
171
+ )
172
+
173
+ # Support PIPELINE_MODE env var
174
+ if [[ -n "${PIPELINE_MODE:-}" ]]; then
175
+ GEN_ARGS+=(--mode "$PIPELINE_MODE")
176
+ fi
177
+
178
+ # Support ENABLE_CRITIC env var
179
+ if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
180
+ GEN_ARGS+=(--critic "true")
181
+ elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
182
+ GEN_ARGS+=(--critic "false")
183
+ fi
184
+
185
+ GEN_OUTPUT=$(python3 "$SCRIPTS_DIR/generate-refactor-prompt.py" "${GEN_ARGS[@]}" 2>/dev/null) || {
186
+ log_error "Failed to generate bootstrap prompt"
187
+ exit 1
188
+ }
189
+ REFACTOR_MODEL=$(echo "$GEN_OUTPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
150
190
 
151
191
  # ============================================================
152
192
  # Run single AI CLI session
153
193
  # ============================================================
154
194
 
195
+ # Branch lifecycle: create and checkout refactor branch
196
+ _branch_name="${DEV_BRANCH:-refactor/${REFACTOR_ID}-$(date +%s)}"
197
+ if branch_create "$PROJECT_ROOT" "$_branch_name" "$ORIGINAL_BRANCH"; then
198
+ _DEV_BRANCH_NAME="$_branch_name"
199
+ log_info "Dev branch: $_branch_name"
200
+ else
201
+ log_warn "Failed to create branch; running session on current branch"
202
+ fi
203
+
155
204
  echo ""
156
205
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
157
206
  echo -e "${BOLD} Retry Refactor: $REFACTOR_ID — $REFACTOR_TITLE${NC}"
158
207
  echo -e "${BOLD} Complexity: $REFACTOR_COMPLEXITY${NC}"
159
208
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
160
209
  log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
161
- if [[ -n "${MODEL:-}" ]]; then
162
- log_info "Model: $MODEL"
210
+ EFFECTIVE_MODEL="${REFACTOR_MODEL:-${MODEL:-}}"
211
+ if [[ -n "$EFFECTIVE_MODEL" ]]; then
212
+ log_info "Model: $EFFECTIVE_MODEL"
163
213
  else
164
214
  log_info "Model: (CLI default)"
165
215
  fi
@@ -188,14 +238,18 @@ if [[ "$USE_STREAM_JSON" == "true" ]]; then
188
238
  VERBOSE_FLAG="--verbose"
189
239
  fi
190
240
 
191
- # Spawn AI CLI session
241
+ # Spawn AI CLI session — model priority: refactor.model > $MODEL env > none
242
+ EFFECTIVE_MODEL="${REFACTOR_MODEL:-${MODEL:-}}"
192
243
  MODEL_FLAG=""
193
- if [[ -n "${MODEL:-}" ]]; then
194
- MODEL_FLAG="--model $MODEL"
244
+ if [[ -n "$EFFECTIVE_MODEL" ]]; then
245
+ MODEL_FLAG="--model $EFFECTIVE_MODEL"
195
246
  fi
196
247
 
197
248
  unset CLAUDECODE 2>/dev/null || true
198
249
 
250
+ # Log bootstrap prompt in test mode
251
+ prizm_log_bootstrap_prompt "$BOOTSTRAP_PROMPT" "$REFACTOR_ID"
252
+
199
253
  case "$CLI_CMD" in
200
254
  *claude*)
201
255
  # Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
@@ -245,6 +299,10 @@ cleanup() {
245
299
  stop_progress_parser "$PARSER_PID"
246
300
  wait "$CLI_PID" 2>/dev/null || true
247
301
  [[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
302
+ if [[ -n "$_DEV_BRANCH_NAME" ]]; then
303
+ log_info "Development was on branch: $_DEV_BRANCH_NAME"
304
+ log_info "Original branch was: $ORIGINAL_BRANCH"
305
+ fi
248
306
  log_info "Session log: $SESSION_LOG"
249
307
  exit 130
250
308
  }
@@ -330,6 +388,30 @@ if [[ "$SESSION_STATUS" == "success" ]]; then
330
388
  fi
331
389
  fi
332
390
 
391
+ # ── Propagate completion notes for dependency context ─────────────────
392
+ if [[ "$SESSION_STATUS" == "success" ]]; then
393
+ SUMMARY_PATH="$PROJECT_ROOT/.prizmkit/refactor/$REFACTOR_ID/completion-summary.json"
394
+ if [[ -f "$SUMMARY_PATH" ]]; then
395
+ python3 "$SCRIPTS_DIR/patch-completion-notes.py" \
396
+ --refactor-list "$REFACTOR_LIST" \
397
+ --refactor-id "$REFACTOR_ID" \
398
+ --summary "$SUMMARY_PATH" >/dev/null 2>&1 && {
399
+ log_info "Propagated completion notes for $REFACTOR_ID"
400
+ } || {
401
+ log_warn "Failed to propagate completion notes for $REFACTOR_ID"
402
+ }
403
+ fi
404
+ fi
405
+
406
+ # ── Merge dev branch back to original on success ────────────────────
407
+ if [[ "$SESSION_STATUS" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
408
+ if branch_merge "$PROJECT_ROOT" "$_DEV_BRANCH_NAME" "$ORIGINAL_BRANCH" "$AUTO_PUSH"; then
409
+ _DEV_BRANCH_NAME=""
410
+ else
411
+ log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
412
+ fi
413
+ fi
414
+
333
415
  # Update refactor status
334
416
  python3 "$SCRIPTS_DIR/update-refactor-status.py" \
335
417
  --refactor-list "$REFACTOR_LIST" \
@@ -43,6 +43,7 @@ LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
43
43
  LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
44
44
  LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
45
45
  VERBOSE=${VERBOSE:-0}
46
+ MODEL=${MODEL:-""}
46
47
  DEV_BRANCH=${DEV_BRANCH:-""}
47
48
  AUTO_PUSH=${AUTO_PUSH:-0}
48
49
 
@@ -77,7 +78,8 @@ spawn_and_wait_session() {
77
78
  local bootstrap_prompt="$4"
78
79
  local session_dir="$5"
79
80
  local max_retries="$6"
80
- local base_branch="${7:-main}"
81
+ local item_model="${7:-}"
82
+ local base_branch="${8:-main}"
81
83
 
82
84
  local session_log="$session_dir/logs/session.log"
83
85
  local progress_json="$session_dir/logs/progress.json"
@@ -95,7 +97,9 @@ spawn_and_wait_session() {
95
97
  fi
96
98
 
97
99
  local model_flag=""
98
- if [[ -n "${MODEL:-}" ]]; then
100
+ if [[ -n "$item_model" ]]; then
101
+ model_flag="--model $item_model"
102
+ elif [[ -n "${MODEL:-}" ]]; then
99
103
  model_flag="--model $MODEL"
100
104
  fi
101
105
 
@@ -103,6 +107,9 @@ spawn_and_wait_session() {
103
107
  # within an existing Claude Code session (e.g. via launch-bugfix-daemon.sh).
104
108
  unset CLAUDECODE 2>/dev/null || true
105
109
 
110
+ # Log bootstrap prompt in test mode
111
+ prizm_log_bootstrap_prompt "$bootstrap_prompt" "$bug_id"
112
+
106
113
  case "$CLI_CMD" in
107
114
  *claude*)
108
115
  # Claude Code: prompt via -p, --dangerously-skip-permissions for auto-accept
@@ -355,6 +362,8 @@ run_one() {
355
362
  local dry_run=false
356
363
  local do_clean=false
357
364
  local no_reset=false
365
+ local mode_override=""
366
+ local critic_override=""
358
367
 
359
368
  while [[ $# -gt 0 ]]; do
360
369
  case "$1" in
@@ -362,6 +371,20 @@ run_one() {
362
371
  --clean) do_clean=true; shift ;;
363
372
  --no-reset) no_reset=true; shift ;;
364
373
  --timeout) shift; SESSION_TIMEOUT="${1:-0}"; shift ;;
374
+ --mode)
375
+ shift
376
+ if [[ $# -eq 0 ]]; then
377
+ log_error "--mode requires a value (lite|standard|full)"
378
+ exit 1
379
+ fi
380
+ case "$1" in
381
+ lite|standard|full) mode_override="$1" ;;
382
+ *) log_error "Invalid mode: $1 (must be lite, standard, or full)"; exit 1 ;;
383
+ esac
384
+ shift
385
+ ;;
386
+ --critic) critic_override="true"; shift ;;
387
+ --no-critic) critic_override="false"; shift ;;
365
388
  B-*|b-*) bug_id="$1"; shift ;;
366
389
  *) bug_list="$1"; shift ;;
367
390
  esac
@@ -494,16 +517,66 @@ sys.exit(1)
494
517
 
495
518
  bootstrap_prompt="$session_dir/bootstrap-prompt.md"
496
519
 
520
+ # Read retry count from status.json
521
+ local retry_count
522
+ retry_count=$(python3 -c "
523
+ import json, os
524
+ status_path = os.path.join('$STATE_DIR', 'bugs', '$bug_id', 'status.json')
525
+ if os.path.isfile(status_path):
526
+ with open(status_path) as f:
527
+ d = json.load(f)
528
+ print(d.get('retry_count', 0))
529
+ else:
530
+ print(0)
531
+ " 2>/dev/null || echo "0")
532
+ local resume_phase
533
+ resume_phase=$(python3 -c "
534
+ import json, os
535
+ status_path = os.path.join('$STATE_DIR', 'bugs', '$bug_id', 'status.json')
536
+ if os.path.isfile(status_path):
537
+ with open(status_path) as f:
538
+ d = json.load(f)
539
+ print(d.get('resume_from_phase') or 'null')
540
+ else:
541
+ print('null')
542
+ " 2>/dev/null || echo "null")
543
+
497
544
  log_info "Generating bugfix bootstrap prompt..."
498
- python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" \
499
- --bug-list "$bug_list" \
500
- --bug-id "$bug_id" \
501
- --session-id "$session_id" \
502
- --run-id "$run_id" \
503
- --retry-count 0 \
504
- --resume-phase "null" \
505
- --state-dir "$STATE_DIR" \
506
- --output "$bootstrap_prompt" >/dev/null 2>&1
545
+ local prompt_args=(
546
+ --bug-list "$bug_list"
547
+ --bug-id "$bug_id"
548
+ --session-id "$session_id"
549
+ --run-id "$run_id"
550
+ --retry-count "$retry_count"
551
+ --resume-phase "$resume_phase"
552
+ --state-dir "$STATE_DIR"
553
+ --output "$bootstrap_prompt"
554
+ )
555
+
556
+ if [[ -n "$mode_override" ]]; then
557
+ prompt_args+=(--mode "$mode_override")
558
+ elif [[ -n "${PIPELINE_MODE:-}" ]]; then
559
+ prompt_args+=(--mode "$PIPELINE_MODE")
560
+ fi
561
+
562
+ if [[ -n "${critic_override:-}" ]]; then
563
+ prompt_args+=(--critic "$critic_override")
564
+ elif [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
565
+ prompt_args+=(--critic "true")
566
+ elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
567
+ prompt_args+=(--critic "false")
568
+ fi
569
+
570
+ local gen_output
571
+ gen_output=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${prompt_args[@]}" 2>/dev/null) || {
572
+ log_error "Failed to generate bootstrap prompt for $bug_id"
573
+ return 1
574
+ }
575
+ local bug_model pipeline_mode agent_count critic_enabled
576
+ bug_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
577
+ pipeline_mode=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('pipeline_mode','standard'))" 2>/dev/null || echo "standard")
578
+ agent_count=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('agent_count',3))" 2>/dev/null || echo "3")
579
+ critic_enabled=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('critic_enabled','false'))" 2>/dev/null || echo "false")
507
580
 
508
581
  if [[ "$dry_run" == true ]]; then
509
582
  echo ""
@@ -512,6 +585,20 @@ sys.exit(1)
512
585
  echo -e "${BOLD} Severity: $bug_severity${NC}"
513
586
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
514
587
  echo ""
588
+ log_info "Session ID: $session_id"
589
+ if [[ -n "$mode_override" ]]; then
590
+ log_info "Mode Override: $mode_override"
591
+ fi
592
+ log_info "Pipeline mode: $pipeline_mode"
593
+ log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
594
+ if [[ -n "$bug_model" ]]; then
595
+ log_info "Bug Model: $bug_model"
596
+ elif [[ -n "$MODEL" ]]; then
597
+ log_info "Model (env): $MODEL"
598
+ else
599
+ log_info "Model: (CLI default)"
600
+ fi
601
+ echo ""
515
602
  log_info "Bootstrap prompt written to:"
516
603
  echo " $bootstrap_prompt"
517
604
  echo ""
@@ -528,6 +615,18 @@ sys.exit(1)
528
615
  log_info "Session ID: $session_id"
529
616
  log_info "Prompt: $bootstrap_prompt"
530
617
  log_info "Log: $session_dir/logs/session.log"
618
+ local _run_one_mode_desc
619
+ case "$pipeline_mode" in
620
+ lite) _run_one_mode_desc="Tier 1 — Single Agent" ;;
621
+ standard) _run_one_mode_desc="Tier 2 — Orchestrator + Dev + Reviewer" ;;
622
+ full) _run_one_mode_desc="Tier 3 — Full Team (+ Multi-Critic)" ;;
623
+ *) _run_one_mode_desc="$pipeline_mode" ;;
624
+ esac
625
+ log_info "Pipeline mode: ${BOLD}$pipeline_mode${NC} ($_run_one_mode_desc)"
626
+ log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
627
+ if [[ -n "$bug_model" ]]; then
628
+ log_info "Bug model: $bug_model"
629
+ fi
531
630
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
532
631
  echo ""
533
632
 
@@ -562,7 +661,7 @@ sys.exit(1)
562
661
 
563
662
  spawn_and_wait_session \
564
663
  "$bug_id" "$bug_list" "$session_id" \
565
- "$bootstrap_prompt" "$session_dir" 999 "$_ORIGINAL_BRANCH"
664
+ "$bootstrap_prompt" "$session_dir" 999 "$bug_model" "$_ORIGINAL_BRANCH"
566
665
  local session_status="$_SPAWN_RESULT"
567
666
 
568
667
  # Merge dev branch back to original on success
@@ -665,23 +764,13 @@ main() {
665
764
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
666
765
  echo ""
667
766
 
668
- # Branch lifecycle: create bugfix branch for this pipeline run
767
+ # Branch lifecycle: per-bug branches (like feature pipeline)
669
768
  local _proj_root
670
769
  _proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
671
770
  local _source_branch
672
771
  _source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
673
772
  _ORIGINAL_BRANCH="$_source_branch"
674
773
 
675
- local run_id_for_branch
676
- run_id_for_branch=$(jq -r '.run_id' "$STATE_DIR/pipeline.json" 2>/dev/null || echo "$$")
677
- local _branch_name="${DEV_BRANCH:-bugfix/pipeline-${run_id_for_branch}}"
678
- if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
679
- _DEV_BRANCH_NAME="$_branch_name"
680
- log_info "Dev branch: $_branch_name"
681
- else
682
- log_warn "Failed to create bugfix branch; running on current branch: $_source_branch"
683
- fi
684
-
685
774
  local session_count=0
686
775
  local total_subagent_calls=0
687
776
 
@@ -705,15 +794,6 @@ main() {
705
794
  log_success " Total subagent calls: $total_subagent_calls"
706
795
  log_success "════════════════════════════════════════════════════"
707
796
 
708
- # Merge dev branch back to original
709
- if [[ -n "$_DEV_BRANCH_NAME" ]]; then
710
- if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
711
- _DEV_BRANCH_NAME=""
712
- else
713
- log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
714
- log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
715
- fi
716
- fi
717
797
  break
718
798
  fi
719
799
 
@@ -742,6 +822,23 @@ main() {
742
822
  fi
743
823
  echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
744
824
 
825
+ # Pre-commit any dirty tree from previous iteration
826
+ if ! git -C "$_proj_root" diff --quiet HEAD 2>/dev/null || [ -n "$(git -C "$_proj_root" ls-files --others --exclude-standard 2>/dev/null)" ]; then
827
+ log_info "Dirty working tree detected — committing before $bug_id..."
828
+ git -C "$_proj_root" add -A 2>/dev/null || true
829
+ git -C "$_proj_root" commit --no-verify -m "chore: capture artifacts before $bug_id session" 2>/dev/null || true
830
+ fi
831
+
832
+ # Create per-bug dev branch
833
+ local _bug_branch="${DEV_BRANCH:-bugfix/${bug_id}-$(date +%Y%m%d%H%M)}"
834
+ if branch_create "$_proj_root" "$_bug_branch" "$_ORIGINAL_BRANCH"; then
835
+ _DEV_BRANCH_NAME="$_bug_branch"
836
+ log_info "Dev branch: $_bug_branch"
837
+ else
838
+ log_warn "Failed to create dev branch; running on current branch: $_ORIGINAL_BRANCH"
839
+ _DEV_BRANCH_NAME=""
840
+ fi
841
+
745
842
  # Generate session
746
843
  local session_id run_id
747
844
  run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
@@ -751,19 +848,61 @@ main() {
751
848
  mkdir -p "$session_dir/logs"
752
849
 
753
850
  local bootstrap_prompt="$session_dir/bootstrap-prompt.md"
754
- python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" \
851
+
852
+ local main_prompt_args=(
853
+ --bug-list "$bug_list"
854
+ --bug-id "$bug_id"
855
+ --session-id "$session_id"
856
+ --run-id "$run_id"
857
+ --retry-count "$retry_count"
858
+ --resume-phase "$resume_phase"
859
+ --state-dir "$STATE_DIR"
860
+ --output "$bootstrap_prompt"
861
+ )
862
+
863
+ # Support PIPELINE_MODE env var (set by launch-bugfix-daemon.sh --mode)
864
+ if [[ -n "${PIPELINE_MODE:-}" ]]; then
865
+ main_prompt_args+=(--mode "$PIPELINE_MODE")
866
+ fi
867
+
868
+ # Support ENABLE_CRITIC env var (set by launch-bugfix-daemon.sh --critic)
869
+ if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
870
+ main_prompt_args+=(--critic "true")
871
+ elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
872
+ main_prompt_args+=(--critic "false")
873
+ fi
874
+
875
+ local gen_output
876
+ gen_output=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${main_prompt_args[@]}" 2>/dev/null) || {
877
+ log_error "Failed to generate bootstrap prompt for $bug_id"
878
+ continue
879
+ }
880
+ local bug_model pipeline_mode agent_count critic_enabled
881
+ bug_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
882
+ pipeline_mode=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('pipeline_mode','standard'))" 2>/dev/null || echo "standard")
883
+ agent_count=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('agent_count',3))" 2>/dev/null || echo "3")
884
+ critic_enabled=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('critic_enabled','false'))" 2>/dev/null || echo "false")
885
+
886
+ # Log pipeline mode and agent configuration
887
+ local _mode_desc
888
+ case "$pipeline_mode" in
889
+ lite) _mode_desc="Tier 1 — Single Agent" ;;
890
+ standard) _mode_desc="Tier 2 — Orchestrator + Dev + Reviewer" ;;
891
+ full) _mode_desc="Tier 3 — Full Team (+ Multi-Critic)" ;;
892
+ *) _mode_desc="$pipeline_mode" ;;
893
+ esac
894
+ log_info "Pipeline mode: ${BOLD}$pipeline_mode${NC} ($_mode_desc)"
895
+ log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
896
+ if [[ -n "$bug_model" ]]; then
897
+ log_info "Bug model: $bug_model"
898
+ fi
899
+
900
+ # Mark bug as in-progress before spawning session
901
+ python3 "$SCRIPTS_DIR/update-bug-status.py" \
755
902
  --bug-list "$bug_list" \
756
- --bug-id "$bug_id" \
757
- --session-id "$session_id" \
758
- --run-id "$run_id" \
759
- --retry-count "$retry_count" \
760
- --resume-phase "$resume_phase" \
761
903
  --state-dir "$STATE_DIR" \
762
- --output "$bootstrap_prompt" >/dev/null 2>&1
763
-
764
- # Log agent configuration (bugfix always uses dual-agent: Orchestrator + Dev + Reviewer)
765
- log_info "Pipeline mode: ${BOLD}standard${NC} (Dual Agent — Orchestrator + Dev + Reviewer)"
766
- log_info "Agents: 3 (critic: disabled)"
904
+ --bug-id "$bug_id" \
905
+ --action start >/dev/null 2>&1 || true
767
906
 
768
907
  # Spawn session
769
908
  log_info "Spawning AI CLI session: $session_id"
@@ -771,11 +910,53 @@ main() {
771
910
 
772
911
  spawn_and_wait_session \
773
912
  "$bug_id" "$bug_list" "$session_id" \
774
- "$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$_ORIGINAL_BRANCH"
913
+ "$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$bug_model" "$_ORIGINAL_BRANCH"
914
+
915
+ local session_status="$_SPAWN_RESULT"
916
+
917
+ # Merge per-bug dev branch back to original on success
918
+ if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
919
+ if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
920
+ _DEV_BRANCH_NAME=""
921
+ else
922
+ log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
923
+ log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
924
+ git -C "$_proj_root" checkout "$_ORIGINAL_BRANCH" 2>/dev/null || true
925
+ _DEV_BRANCH_NAME=""
926
+ fi
927
+ elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
928
+ # Session failed — return to original branch, preserve dev branch for inspection
929
+ if ! git -C "$_proj_root" checkout "$_ORIGINAL_BRANCH" 2>/dev/null; then
930
+ log_warn "Failed to checkout $_ORIGINAL_BRANCH after session failure — staying on dev branch"
931
+ fi
932
+ log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
933
+ _DEV_BRANCH_NAME=""
934
+ fi
775
935
 
776
936
  session_count=$((session_count + 1))
777
937
  total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
778
938
 
939
+ # Stuck detection
940
+ if python3 "$SCRIPTS_DIR/detect-stuck.py" \
941
+ --state-dir "$STATE_DIR" \
942
+ --pipeline-type bugfix \
943
+ --bug-list "$bug_list" \
944
+ --max-retries "$MAX_RETRIES" \
945
+ 2>/dev/null | jq -e '.stuck_count > 0' >/dev/null 2>&1; then
946
+ log_warn "STUCK_DETECTED: Some bugs may be stuck — run detect-stuck.py for details"
947
+ fi
948
+
949
+ # Completion notes propagation (on success)
950
+ if [ "$_SPAWN_RESULT" = "success" ]; then
951
+ local _summary_path="$_proj_root/.prizmkit/bugfix/${bug_id}/completion-summary.json"
952
+ if [ -f "$_summary_path" ]; then
953
+ python3 "$SCRIPTS_DIR/patch-completion-notes.py" \
954
+ --bug-list "$bug_list" \
955
+ --bug-id "$bug_id" \
956
+ --summary "$_summary_path" 2>/dev/null || true
957
+ fi
958
+ fi
959
+
779
960
  log_info "Pausing 5s before next bug..."
780
961
  sleep 5
781
962
  done
@@ -800,10 +981,16 @@ show_help() {
800
981
  echo " --clean Delete artifacts and reset before running"
801
982
  echo " --no-reset Skip status reset (preserve retry count)"
802
983
  echo " --timeout N Session timeout in seconds (default: 0 = no limit)"
984
+ echo " --mode <lite|standard|full> Override pipeline mode"
985
+ echo " --critic Enable adversarial critic review"
986
+ echo " --no-critic Disable adversarial critic review"
803
987
  echo ""
804
988
  echo "Environment Variables:"
805
989
  echo " MAX_RETRIES Max retries per bug (default: 3)"
806
990
  echo " SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)"
991
+ echo " MODEL Default AI model (overridden by per-bug model in bug list)"
992
+ echo " PIPELINE_MODE Default pipeline mode: lite|standard|full (overridden by --mode)"
993
+ echo " ENABLE_CRITIC Enable/disable critic: true|false|1|0 (overridden by --critic/--no-critic)"
807
994
  echo " AI_CLI AI CLI command name (auto-detected: cbc or claude)"
808
995
  echo " VERBOSE Set to 1 for verbose AI CLI output"
809
996
  echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
@@ -847,6 +1034,40 @@ case "${1:-run}" in
847
1034
  rm -rf "$STATE_DIR"
848
1035
  log_success "Bugfix state cleared. Run './run-bugfix.sh run' to start fresh."
849
1036
  ;;
1037
+ unskip)
1038
+ check_dependencies
1039
+ if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
1040
+ log_error "No bugfix pipeline state found. Run './run-bugfix.sh run' first."
1041
+ exit 1
1042
+ fi
1043
+ _unskip_bug_list=".prizmkit/plans/bug-fix-list.json"
1044
+ _unskip_bug_id=""
1045
+ shift || true
1046
+ # Parse arguments: optional bug-id and bug-list path
1047
+ while [[ $# -gt 0 ]]; do
1048
+ if [[ "$1" =~ ^[Bb]-[0-9]+ ]]; then
1049
+ _unskip_bug_id="$1"
1050
+ else
1051
+ _unskip_bug_list="$1"
1052
+ fi
1053
+ shift
1054
+ done
1055
+ _unskip_args=(
1056
+ --bug-list "$_unskip_bug_list"
1057
+ --state-dir "$STATE_DIR"
1058
+ --action unskip
1059
+ )
1060
+ if [[ -n "$_unskip_bug_id" ]]; then
1061
+ _unskip_args+=(--bug-id "$_unskip_bug_id")
1062
+ fi
1063
+ python3 "$SCRIPTS_DIR/update-bug-status.py" "${_unskip_args[@]}"
1064
+
1065
+ # Commit the status change
1066
+ if ! git diff --quiet "$_unskip_bug_list" 2>/dev/null; then
1067
+ git add "$_unskip_bug_list"
1068
+ git commit -m "chore: unskip skipped bugs" 2>/dev/null || true
1069
+ fi
1070
+ ;;
850
1071
  help|--help|-h)
851
1072
  show_help
852
1073
  ;;