prizmkit 1.1.10 → 1.1.12

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 (47) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/README.md +10 -46
  3. package/bundled/dev-pipeline/reset-bug.sh +84 -10
  4. package/bundled/dev-pipeline/reset-feature.sh +86 -10
  5. package/bundled/dev-pipeline/reset-refactor.sh +68 -4
  6. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +47 -46
  7. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -12
  8. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +124 -20
  9. package/bundled/dev-pipeline/scripts/utils.py +20 -0
  10. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +13 -7
  11. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +62 -66
  12. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +37 -40
  13. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +35 -48
  14. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +135 -182
  15. package/bundled/dev-pipeline/templates/feature-list-schema.json +6 -21
  16. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +9 -9
  17. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
  18. package/bundled/dev-pipeline/templates/sections/feature-context.md +4 -0
  19. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +41 -24
  20. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +4 -12
  21. package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +9 -17
  22. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +1 -1
  23. package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +3 -2
  24. package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +4 -2
  25. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +0 -18
  26. package/bundled/dev-pipeline/templates/sections/session-context.md +1 -2
  27. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +75 -0
  28. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +66 -0
  29. package/bundled/skills/_metadata.json +1 -1
  30. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +3 -8
  31. package/bundled/skills/feature-pipeline-launcher/SKILL.md +4 -16
  32. package/bundled/skills/feature-planner/SKILL.md +8 -4
  33. package/bundled/skills/feature-planner/assets/planning-guide.md +16 -11
  34. package/bundled/skills/feature-planner/references/browser-interaction.md +9 -8
  35. package/bundled/skills/feature-planner/references/completeness-review.md +1 -1
  36. package/bundled/skills/feature-planner/references/error-recovery.md +1 -1
  37. package/bundled/skills/feature-planner/references/incremental-feature-planning.md +1 -1
  38. package/bundled/skills/feature-planner/scripts/validate-and-generate.py +10 -7
  39. package/bundled/skills/recovery-workflow/SKILL.md +3 -3
  40. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +4 -15
  41. package/package.json +1 -1
  42. package/bundled/dev-pipeline/retry-bugfix.sh +0 -429
  43. package/bundled/dev-pipeline/retry-feature.sh +0 -445
  44. package/bundled/dev-pipeline/retry-refactor.sh +0 -441
  45. package/bundled/dev-pipeline/templates/sections/failure-log-check.md +0 -9
  46. package/bundled/dev-pipeline/templates/sections/resume-header.md +0 -5
  47. package/bundled/dev-pipeline/templates/sections/test-failure-recovery.md +0 -75
@@ -1,445 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- # ============================================================
5
- # dev-pipeline/retry-feature.sh - Retry a single failed feature
6
- #
7
- # Runs exactly ONE AI CLI session for the specified feature, then exits.
8
- # Use this to manually retry a failed feature without restarting
9
- # the full pipeline.
10
- #
11
- # Usage:
12
- # ./retry-feature.sh <feature-id> [.prizmkit/plans/feature-list.json]
13
- #
14
- # Examples:
15
- # ./retry-feature.sh F-007
16
- # ./retry-feature.sh F-007 .prizmkit/plans/feature-list.json
17
- # SESSION_TIMEOUT=3600 ./retry-feature.sh F-007 # with 1h timeout
18
- # ============================================================
19
-
20
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
22
- STATE_DIR="${PROJECT_ROOT}/.prizmkit/state/features"
23
- SCRIPTS_DIR="$SCRIPT_DIR/scripts"
24
-
25
- SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
26
- HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
27
-
28
- # Source shared common helpers (CLI/platform detection + logs + deps)
29
- source "$SCRIPT_DIR/lib/common.sh"
30
- prizm_detect_cli_and_platform
31
-
32
- # Source shared heartbeat library
33
- source "$SCRIPT_DIR/lib/heartbeat.sh"
34
-
35
- # Source shared branch library
36
- source "$SCRIPT_DIR/lib/branch.sh"
37
-
38
- # Detect stream-json support
39
- detect_stream_json_support "$CLI_CMD"
40
-
41
- # Branch tracking
42
- _ORIGINAL_BRANCH=""
43
- _DEV_BRANCH_NAME=""
44
- AUTO_PUSH=${AUTO_PUSH:-0}
45
-
46
- # ============================================================
47
- # Args
48
- # ============================================================
49
-
50
- if [[ $# -lt 1 ]]; then
51
- echo "Usage: $0 <feature-id> [.prizmkit/plans/feature-list.json]"
52
- echo ""
53
- echo " feature-id Feature to retry (e.g. F-007)"
54
- echo " feature-list.json Path to feature list (default: .prizmkit/plans/feature-list.json)"
55
- echo ""
56
- echo "Environment Variables:"
57
- echo " SESSION_TIMEOUT Timeout in seconds (default: 0 = no limit)"
58
- echo " HEARTBEAT_INTERVAL Heartbeat interval in seconds (default: 30)"
59
- echo " AI_CLI AI CLI command (auto-detected: cbc or claude)"
60
- exit 1
61
- fi
62
-
63
- FEATURE_ID="$1"
64
- FEATURE_LIST="${2:-.prizmkit/plans/feature-list.json}"
65
-
66
- # Resolve absolute path
67
- if [[ ! "$FEATURE_LIST" = /* ]]; then
68
- FEATURE_LIST="$(pwd)/$FEATURE_LIST"
69
- fi
70
-
71
- # ============================================================
72
- # Validation
73
- # ============================================================
74
-
75
- if [[ ! -f "$FEATURE_LIST" ]]; then
76
- log_error "Feature list not found: $FEATURE_LIST"
77
- exit 1
78
- fi
79
-
80
- if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
81
- log_error "No pipeline state found. Run './run-feature.sh run' first to initialize."
82
- exit 1
83
- fi
84
-
85
- if ! command -v jq &>/dev/null; then
86
- log_error "jq is required. Install with: brew install jq"
87
- exit 1
88
- fi
89
-
90
- # Verify feature exists in feature list
91
- FEATURE_TITLE=$(python3 -c "
92
- import json, sys
93
- with open('$FEATURE_LIST') as f:
94
- data = json.load(f)
95
- for feat in data.get('features', []):
96
- if feat.get('id') == '$FEATURE_ID':
97
- print(feat.get('title', ''))
98
- sys.exit(0)
99
- sys.exit(1)
100
- " 2>/dev/null) || {
101
- log_error "Feature $FEATURE_ID not found in $FEATURE_LIST"
102
- exit 1
103
- }
104
-
105
- # ============================================================
106
- # Clean feature artifacts + reset status for a full restart
107
- # ============================================================
108
-
109
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
110
- ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
111
- _ORIGINAL_BRANCH="$ORIGINAL_BRANCH"
112
- FEATURE_SLUG=$(FEATURE_ID="$FEATURE_ID" FEATURE_TITLE="$FEATURE_TITLE" python3 -c "
113
- import os, re
114
- fid = os.environ['FEATURE_ID'].replace('F-', '').replace('f-', '').zfill(3)
115
- title = os.environ.get('FEATURE_TITLE', '').lower()
116
- title = re.sub(r'[^a-z0-9\s-]', '', title)
117
- title = re.sub(r'[\s]+', '-', title.strip())
118
- title = re.sub(r'-+', '-', title).strip('-') or 'feature'
119
- print(f'{fid}-{title}')
120
- " 2>/dev/null)
121
-
122
- log_info "Reading retry state for $FEATURE_ID..."
123
- RETRY_COUNT=$(python3 -c "
124
- import json, os
125
- status_path = os.path.join('$STATE_DIR', 'features', '$FEATURE_ID', 'status.json')
126
- if os.path.isfile(status_path):
127
- with open(status_path) as f:
128
- d = json.load(f)
129
- print(d.get('retry_count', 0))
130
- else:
131
- print(0)
132
- " 2>/dev/null || echo "0")
133
- RESUME_PHASE=$(python3 -c "
134
- import json, os
135
- status_path = os.path.join('$STATE_DIR', 'features', '$FEATURE_ID', 'status.json')
136
- if os.path.isfile(status_path):
137
- with open(status_path) as f:
138
- d = json.load(f)
139
- print(d.get('resume_from_phase') or 'null')
140
- else:
141
- print('null')
142
- " 2>/dev/null || echo "null")
143
- log_info "Retry count: $RETRY_COUNT, Resume phase: $RESUME_PHASE"
144
-
145
- # ============================================================
146
- # Generate bootstrap prompt
147
- # ============================================================
148
-
149
- RUN_ID=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
150
- SESSION_ID="${FEATURE_ID}-$(date +%Y%m%d%H%M%S)"
151
- SESSION_DIR="$STATE_DIR/features/$FEATURE_ID/sessions/$SESSION_ID"
152
- mkdir -p "$SESSION_DIR/logs"
153
-
154
- BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
155
-
156
- log_info "Generating bootstrap prompt..."
157
- GEN_ARGS=(
158
- --feature-list "$FEATURE_LIST"
159
- --feature-id "$FEATURE_ID"
160
- --session-id "$SESSION_ID"
161
- --run-id "$RUN_ID"
162
- --retry-count "$RETRY_COUNT"
163
- --resume-phase "$RESUME_PHASE"
164
- --state-dir "$STATE_DIR"
165
- --output "$BOOTSTRAP_PROMPT"
166
- )
167
-
168
- # Support PIPELINE_MODE env var
169
- if [[ -n "${PIPELINE_MODE:-}" ]]; then
170
- GEN_ARGS+=(--mode "$PIPELINE_MODE")
171
- fi
172
-
173
- # Support ENABLE_CRITIC env var
174
- if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
175
- GEN_ARGS+=(--critic "true")
176
- elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
177
- GEN_ARGS+=(--critic "false")
178
- fi
179
-
180
- GEN_OUTPUT=$(python3 "$SCRIPTS_DIR/generate-bootstrap-prompt.py" "${GEN_ARGS[@]}" 2>/dev/null) || {
181
- log_error "Failed to generate bootstrap prompt"
182
- exit 1
183
- }
184
- FEATURE_MODEL=$(echo "$GEN_OUTPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
185
-
186
- # ============================================================
187
- # Run single AI CLI session
188
- # ============================================================
189
-
190
- echo ""
191
- echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
192
- echo -e "${BOLD} Retry: $FEATURE_ID — $FEATURE_TITLE${NC}"
193
- echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
194
- log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
195
- EFFECTIVE_MODEL="${FEATURE_MODEL:-${MODEL:-}}"
196
- if [[ -n "$EFFECTIVE_MODEL" ]]; then
197
- log_info "Model: $EFFECTIVE_MODEL"
198
- else
199
- log_info "Model: (CLI default)"
200
- fi
201
- if [[ $SESSION_TIMEOUT -gt 0 ]]; then
202
- log_info "Session timeout: ${SESSION_TIMEOUT}s"
203
- else
204
- log_info "Session timeout: none"
205
- fi
206
- log_info "Prompt: $BOOTSTRAP_PROMPT"
207
- log_info "Log: $SESSION_DIR/logs/session.log"
208
- echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
209
- echo ""
210
-
211
- # Create per-feature dev branch (consistent with run-feature.sh behavior)
212
- _feature_branch="${DEV_BRANCH:-dev/${FEATURE_ID}-retry-$(date +%Y%m%d%H%M)}"
213
- if branch_create "$PROJECT_ROOT" "$_feature_branch" "$_ORIGINAL_BRANCH"; then
214
- _DEV_BRANCH_NAME="$_feature_branch"
215
- log_info "Dev branch: $_feature_branch"
216
- else
217
- log_warn "Failed to create dev branch; running on current branch"
218
- fi
219
-
220
- SESSION_LOG="$SESSION_DIR/logs/session.log"
221
- PROGRESS_JSON="$SESSION_DIR/logs/progress.json"
222
-
223
- # Build stream-json flag
224
- STREAM_JSON_FLAG=""
225
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
226
- STREAM_JSON_FLAG="--output-format stream-json"
227
- fi
228
-
229
- # claude-internal requires --verbose when using stream-json with -p/--print
230
- VERBOSE_FLAG=""
231
- if [[ "$USE_STREAM_JSON" == "true" ]]; then
232
- VERBOSE_FLAG="--verbose"
233
- fi
234
-
235
- # Mark feature as in-progress before spawning session
236
- python3 "$SCRIPTS_DIR/update-feature-status.py" \
237
- --feature-list "$FEATURE_LIST" \
238
- --state-dir "$STATE_DIR" \
239
- --feature-id "$FEATURE_ID" \
240
- --action start >/dev/null 2>&1 || true
241
-
242
- # Spawn AI CLI session
243
- # Spawn AI CLI session — model priority: feature.model > $MODEL env > none
244
- EFFECTIVE_MODEL="${FEATURE_MODEL:-${MODEL:-}}"
245
- MODEL_FLAG=""
246
- if [[ -n "$EFFECTIVE_MODEL" ]]; then
247
- MODEL_FLAG="--model $EFFECTIVE_MODEL"
248
- log_info "Model: $EFFECTIVE_MODEL"
249
- fi
250
-
251
- unset CLAUDECODE 2>/dev/null || true
252
-
253
- # Log bootstrap prompt in test mode
254
- prizm_log_bootstrap_prompt "$BOOTSTRAP_PROMPT" "$FEATURE_ID"
255
-
256
- case "$CLI_CMD" in
257
- *claude*)
258
- # Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
259
- "$CLI_CMD" \
260
- -p "$(cat "$BOOTSTRAP_PROMPT")" \
261
- --dangerously-skip-permissions \
262
- $VERBOSE_FLAG \
263
- $STREAM_JSON_FLAG \
264
- $MODEL_FLAG \
265
- > "$SESSION_LOG" 2>&1 &
266
- ;;
267
- *)
268
- # CodeBuddy (cbc) and others: prompt via stdin
269
- "$CLI_CMD" \
270
- --print \
271
- -y \
272
- $STREAM_JSON_FLAG \
273
- $MODEL_FLAG \
274
- < "$BOOTSTRAP_PROMPT" \
275
- > "$SESSION_LOG" 2>&1 &
276
- ;;
277
- esac
278
- CBC_PID=$!
279
-
280
- # Start progress parser (no-op if stream-json not supported)
281
- start_progress_parser "$SESSION_LOG" "$PROGRESS_JSON" "$SCRIPTS_DIR"
282
- PARSER_PID="${_PARSER_PID:-}"
283
-
284
- # Timeout watchdog (only if SESSION_TIMEOUT > 0)
285
- WATCHER_PID=""
286
- if [[ $SESSION_TIMEOUT -gt 0 ]]; then
287
- ( sleep "$SESSION_TIMEOUT" && kill -TERM "$CBC_PID" 2>/dev/null ) &
288
- WATCHER_PID=$!
289
- fi
290
-
291
- # Heartbeat
292
- start_heartbeat "$CBC_PID" "$SESSION_LOG" "$PROGRESS_JSON" "$HEARTBEAT_INTERVAL"
293
- HEARTBEAT_PID="${_HEARTBEAT_PID:-}"
294
-
295
- # Ctrl+C cleanup
296
- cleanup() {
297
- echo ""
298
- log_warn "Interrupted. Killing session..."
299
- kill "$CBC_PID" 2>/dev/null || true
300
- [[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
301
- stop_heartbeat "$HEARTBEAT_PID"
302
- stop_progress_parser "$PARSER_PID"
303
- wait "$CBC_PID" 2>/dev/null || true
304
- [[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
305
- log_info "Session log: $SESSION_LOG"
306
- exit 130
307
- }
308
- trap cleanup SIGINT SIGTERM
309
-
310
- # Wait
311
- EXIT_CODE=0
312
- if wait "$CBC_PID" 2>/dev/null; then
313
- EXIT_CODE=0
314
- else
315
- EXIT_CODE=$?
316
- fi
317
-
318
- # Cleanup background processes
319
- [[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
320
- stop_heartbeat "$HEARTBEAT_PID"
321
- stop_progress_parser "$PARSER_PID"
322
- [[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
323
-
324
- [[ $EXIT_CODE -eq 143 ]] && EXIT_CODE=124
325
-
326
- # ============================================================
327
- # Check result
328
- # ============================================================
329
-
330
- echo ""
331
- if [[ -f "$SESSION_LOG" ]]; then
332
- FINAL_LINES=$(wc -l < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
333
- FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
334
- log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
335
- fi
336
- log_info "exit_code=$EXIT_CODE"
337
-
338
- # ── Determine session outcome from observable signals ──────────────
339
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
340
- DEFAULT_BRANCH="$ORIGINAL_BRANCH"
341
-
342
- if [[ $EXIT_CODE -eq 124 ]]; then
343
- log_warn "Session timed out after ${SESSION_TIMEOUT}s"
344
- SESSION_STATUS="timed_out"
345
- elif [[ $EXIT_CODE -ne 0 ]]; then
346
- log_warn "Session exited with code $EXIT_CODE"
347
- SESSION_STATUS="crashed"
348
- else
349
- # Exit code 0 — check if the session produced commits
350
- HAS_COMMITS=""
351
- if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
352
- HAS_COMMITS=$(git -C "$PROJECT_ROOT" log "${DEFAULT_BRANCH}..HEAD" --oneline 2>/dev/null | head -1)
353
- fi
354
-
355
- if [[ -n "$HAS_COMMITS" ]]; then
356
- SESSION_STATUS="success"
357
- else
358
- UNCOMMITTED=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null | head -1 || true)
359
- if [[ -n "$UNCOMMITTED" ]]; then
360
- log_warn "Session exited cleanly but produced no commits (uncommitted changes found) — auto-committing..."
361
- git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
362
- if git -C "$PROJECT_ROOT" commit --no-verify -m "chore($FEATURE_ID): auto-commit session work" 2>/dev/null; then
363
- log_info "Auto-commit succeeded"
364
- SESSION_STATUS="success"
365
- else
366
- log_warn "Auto-commit failed — no changes to commit"
367
- SESSION_STATUS="crashed"
368
- fi
369
- else
370
- log_warn "Session exited cleanly but produced no commits and no changes"
371
- SESSION_STATUS="crashed"
372
- fi
373
- fi
374
- fi
375
-
376
- # ── Post-success validation ──────────────────────────────────────────
377
- if [[ "$SESSION_STATUS" == "success" ]]; then
378
- if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
379
- DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
380
- if [[ -n "$DIRTY_FILES" ]]; then
381
- log_info "Auto-committing remaining session artifacts..."
382
- git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
383
- git -C "$PROJECT_ROOT" commit --no-verify --amend --no-edit -a 2>/dev/null \
384
- || git -C "$PROJECT_ROOT" commit --no-verify -m "chore($FEATURE_ID): include remaining session artifacts" 2>/dev/null \
385
- || true
386
- fi
387
- fi
388
- fi
389
-
390
- # ── Propagate completion notes for dependency context ─────────────────
391
- if [[ "$SESSION_STATUS" == "success" && -n "$FEATURE_SLUG" ]]; then
392
- SUMMARY_PATH="$PROJECT_ROOT/.prizmkit/specs/$FEATURE_SLUG/completion-summary.json"
393
- if [[ -f "$SUMMARY_PATH" ]]; then
394
- python3 "$SCRIPTS_DIR/patch-completion-notes.py" \
395
- --feature-list "$FEATURE_LIST" \
396
- --feature-id "$FEATURE_ID" \
397
- --summary "$SUMMARY_PATH" >/dev/null 2>&1 && {
398
- log_info "Propagated completion notes for $FEATURE_ID"
399
- } || {
400
- log_warn "Failed to propagate completion notes for $FEATURE_ID"
401
- }
402
- fi
403
- fi
404
-
405
- # Update feature status
406
- python3 "$SCRIPTS_DIR/update-feature-status.py" \
407
- --feature-list "$FEATURE_LIST" \
408
- --state-dir "$STATE_DIR" \
409
- --feature-id "$FEATURE_ID" \
410
- --session-status "$SESSION_STATUS" \
411
- --session-id "$SESSION_ID" \
412
- --max-retries 999 \
413
- --action update >/dev/null 2>&1 || true
414
-
415
- # Commit feature-list.json status update (pipeline management commit)
416
- if ! git -C "$PROJECT_ROOT" diff --quiet "$FEATURE_LIST" 2>/dev/null; then
417
- git -C "$PROJECT_ROOT" add "$FEATURE_LIST"
418
- git -C "$PROJECT_ROOT" commit --no-verify -m "chore($FEATURE_ID): update feature status" 2>/dev/null || true
419
- fi
420
-
421
- # Merge dev branch back to original on success
422
- if [[ "$SESSION_STATUS" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
423
- if branch_merge "$PROJECT_ROOT" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
424
- _DEV_BRANCH_NAME=""
425
- else
426
- log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
427
- fi
428
- elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
429
- # Session failed — return to original branch, preserve dev branch for inspection
430
- git -C "$PROJECT_ROOT" checkout "$_ORIGINAL_BRANCH" 2>/dev/null || true
431
- log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
432
- _DEV_BRANCH_NAME=""
433
- fi
434
-
435
- echo ""
436
- if [[ "$SESSION_STATUS" == "success" ]]; then
437
- log_success "════════════════════════════════════════════════════"
438
- log_success " $FEATURE_ID completed successfully!"
439
- log_success "════════════════════════════════════════════════════"
440
- else
441
- log_error "════════════════════════════════════════════════════"
442
- log_error " $FEATURE_ID result: $SESSION_STATUS"
443
- log_error " Review log: $SESSION_LOG"
444
- log_error "════════════════════════════════════════════════════"
445
- fi