prizmkit 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/VERSION.json +3 -3
- package/bundled/adapters/claude/agent-adapter.js +18 -0
- package/bundled/adapters/claude/command-adapter.js +1 -27
- package/bundled/agents/prizm-dev-team-critic.md +2 -0
- package/bundled/agents/prizm-dev-team-dev.md +2 -0
- package/bundled/agents/prizm-dev-team-reviewer.md +2 -0
- package/bundled/dev-pipeline/README.md +63 -63
- package/bundled/dev-pipeline/assets/feature-list-example.json +1 -1
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +1 -1
- package/bundled/dev-pipeline/{launch-daemon.sh → launch-feature-daemon.sh} +33 -33
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +454 -0
- package/bundled/dev-pipeline/lib/branch.sh +1 -1
- package/bundled/dev-pipeline/reset-feature.sh +3 -3
- package/bundled/dev-pipeline/reset-refactor.sh +312 -0
- package/bundled/dev-pipeline/{retry-bug.sh → retry-bugfix.sh} +47 -59
- package/bundled/dev-pipeline/retry-feature.sh +41 -54
- package/bundled/dev-pipeline/retry-refactor.sh +358 -0
- package/bundled/dev-pipeline/run-bugfix.sh +6 -0
- package/bundled/dev-pipeline/{run.sh → run-feature.sh} +31 -31
- package/bundled/dev-pipeline/run-refactor.sh +787 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +177 -10
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +419 -0
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +393 -0
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +726 -0
- package/bundled/dev-pipeline/templates/agent-prompts/critic-code-challenge.md +13 -0
- package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +7 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +7 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +26 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-resume.md +5 -0
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-analyze.md +5 -0
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +12 -0
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +29 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +8 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +11 -10
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +2 -3
- package/bundled/dev-pipeline/templates/feature-list-schema.json +1 -1
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +159 -0
- package/bundled/dev-pipeline/templates/sections/ac-verification-checklist.md +13 -0
- package/bundled/dev-pipeline/templates/sections/feature-context.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +9 -8
- package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +9 -8
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +2 -1
- package/bundled/dev-pipeline/templates/sections/phase-critic-code.md +8 -10
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +9 -10
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +8 -9
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +7 -10
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +8 -15
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +7 -12
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +8 -19
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery.md +75 -0
- package/bundled/skills/_metadata.json +33 -6
- package/bundled/skills/app-planner/SKILL.md +105 -320
- package/bundled/skills/app-planner/assets/app-design-guide.md +101 -0
- package/bundled/skills/app-planner/references/frontend-design-guide.md +1 -1
- package/bundled/skills/app-planner/references/project-brief-guide.md +49 -80
- package/bundled/skills/bug-fix-workflow/SKILL.md +2 -2
- package/bundled/skills/bug-planner/SKILL.md +68 -5
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +3 -2
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +19 -5
- package/bundled/skills/{dev-pipeline-launcher → feature-pipeline-launcher}/SKILL.md +32 -32
- package/bundled/skills/feature-planner/SKILL.md +337 -0
- package/bundled/skills/{app-planner → feature-planner}/assets/evaluation-guide.md +4 -4
- package/bundled/skills/{app-planner → feature-planner}/assets/planning-guide.md +3 -171
- package/bundled/skills/{app-planner → feature-planner}/references/browser-interaction.md +6 -5
- package/bundled/skills/feature-planner/references/decomposition-patterns.md +75 -0
- package/bundled/skills/{app-planner → feature-planner}/references/error-recovery.md +8 -8
- package/bundled/skills/{app-planner → feature-planner}/references/incremental-feature-planning.md +1 -1
- package/bundled/skills/{app-planner/references/new-app-planning.md → feature-planner/references/new-project-planning.md} +1 -1
- package/bundled/skills/{app-planner → feature-planner}/scripts/validate-and-generate.py +4 -4
- package/bundled/skills/feature-workflow/SKILL.md +23 -23
- package/bundled/skills/prizm-kit/SKILL.md +1 -3
- package/bundled/skills/prizmkit-analyze/SKILL.md +2 -5
- package/bundled/skills/prizmkit-code-review/SKILL.md +2 -2
- package/bundled/skills/prizmkit-committer/SKILL.md +4 -8
- package/bundled/skills/prizmkit-deploy/SKILL.md +1 -5
- package/bundled/skills/prizmkit-implement/SKILL.md +3 -50
- package/bundled/skills/prizmkit-init/SKILL.md +5 -77
- package/bundled/skills/prizmkit-plan/SKILL.md +1 -12
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +6 -24
- package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +21 -0
- package/bundled/skills/prizmkit-retrospective/SKILL.md +12 -117
- package/bundled/skills/recovery-workflow/SKILL.md +166 -316
- package/bundled/skills/recovery-workflow/evals/evals.json +29 -13
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +232 -274
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +352 -0
- package/bundled/skills/refactor-planner/SKILL.md +436 -0
- package/bundled/skills/refactor-planner/assets/planning-guide.md +292 -0
- package/bundled/skills/refactor-planner/references/behavior-preservation.md +301 -0
- package/bundled/skills/refactor-planner/references/refactor-scoping-guide.md +221 -0
- package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +786 -0
- package/bundled/skills/refactor-workflow/SKILL.md +299 -319
- package/package.json +1 -1
- package/src/clean.js +3 -3
- package/src/scaffold.js +6 -6
- package/bundled/skills/prizmkit-plan/assets/spec-template.md +0 -56
- package/bundled/skills/prizmkit-plan/references/clarify-guide.md +0 -67
- package/src/config.js +0 -504
- package/src/prompts.js +0 -210
- /package/bundled/skills/{dev-pipeline-launcher → feature-pipeline-launcher}/scripts/preflight-check.py +0 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# ============================================================
|
|
5
|
+
# dev-pipeline/reset-refactor.sh - Reset a failed/stuck refactor
|
|
6
|
+
#
|
|
7
|
+
# Clears all state and artifacts for a refactor so it can be
|
|
8
|
+
# re-executed from scratch by the pipeline.
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
# ./reset-refactor.sh <refactor-id|range> [options] [refactor-list.json]
|
|
12
|
+
#
|
|
13
|
+
# Refactor selection:
|
|
14
|
+
# R-007 Single refactor
|
|
15
|
+
# R-008:R-013 Range of refactors (inclusive)
|
|
16
|
+
# --auto-skipped All refactors with auto_skipped status
|
|
17
|
+
# --failed All refactors with failed status
|
|
18
|
+
# --stalled All non-completed refactors (failed + auto_skipped)
|
|
19
|
+
#
|
|
20
|
+
# Options:
|
|
21
|
+
# --clean Also delete session history and .prizmkit/specs/{slug}/ artifacts
|
|
22
|
+
# --run After reset, immediately retry via pipeline (only with single refactor)
|
|
23
|
+
#
|
|
24
|
+
# Examples:
|
|
25
|
+
# ./reset-refactor.sh R-007 # Reset status only
|
|
26
|
+
# ./reset-refactor.sh R-007 --clean # Reset + delete artifacts
|
|
27
|
+
# ./reset-refactor.sh R-008:R-013 --clean # Reset range
|
|
28
|
+
# ./reset-refactor.sh --auto-skipped # Reset all auto_skipped
|
|
29
|
+
# ./reset-refactor.sh --failed --clean # Reset all failed + clean
|
|
30
|
+
# ./reset-refactor.sh --stalled --clean # Reset all non-completed
|
|
31
|
+
# ./reset-refactor.sh R-007 --clean --run # Reset + delete + retry
|
|
32
|
+
# ./reset-refactor.sh R-007 --clean my-refactors.json # Custom refactor list
|
|
33
|
+
# ============================================================
|
|
34
|
+
|
|
35
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
36
|
+
STATE_DIR="$SCRIPT_DIR/refactor-state"
|
|
37
|
+
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
38
|
+
|
|
39
|
+
# Colors
|
|
40
|
+
RED='\033[0;31m'
|
|
41
|
+
GREEN='\033[0;32m'
|
|
42
|
+
YELLOW='\033[1;33m'
|
|
43
|
+
BLUE='\033[0;34m'
|
|
44
|
+
BOLD='\033[1m'
|
|
45
|
+
NC='\033[0m'
|
|
46
|
+
|
|
47
|
+
log_info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
|
48
|
+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
49
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
|
50
|
+
log_success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
|
51
|
+
|
|
52
|
+
# ============================================================
|
|
53
|
+
# Parse args
|
|
54
|
+
# ============================================================
|
|
55
|
+
|
|
56
|
+
REFACTOR_ID=""
|
|
57
|
+
REFACTOR_RANGE=""
|
|
58
|
+
REFACTOR_LIST=""
|
|
59
|
+
DO_CLEAN=false
|
|
60
|
+
DO_RUN=false
|
|
61
|
+
FILTER_MODE=""
|
|
62
|
+
|
|
63
|
+
for arg in "$@"; do
|
|
64
|
+
case "$arg" in
|
|
65
|
+
--clean) DO_CLEAN=true ;;
|
|
66
|
+
--run) DO_RUN=true ;;
|
|
67
|
+
--auto-skipped) FILTER_MODE="auto_skipped" ;;
|
|
68
|
+
--failed) FILTER_MODE="failed" ;;
|
|
69
|
+
--stalled) FILTER_MODE="stalled" ;;
|
|
70
|
+
-h|--help)
|
|
71
|
+
echo "Usage: $0 <refactor-id|range> [--clean] [--run] [--auto-skipped|--failed|--stalled] [refactor-list.json]"
|
|
72
|
+
echo ""
|
|
73
|
+
echo " refactor-id Single refactor (e.g. R-007)"
|
|
74
|
+
echo " R-008:R-013 Range of refactors (inclusive)"
|
|
75
|
+
echo " --auto-skipped Reset all auto_skipped refactors"
|
|
76
|
+
echo " --failed Reset all failed refactors"
|
|
77
|
+
echo " --stalled Reset all non-completed (failed + auto_skipped)"
|
|
78
|
+
echo " --clean Delete session history and .prizmkit artifacts"
|
|
79
|
+
echo " --run Retry immediately after reset (single refactor only)"
|
|
80
|
+
echo " refactor-list.json Path to refactor list (default: refactor-list.json)"
|
|
81
|
+
exit 0
|
|
82
|
+
;;
|
|
83
|
+
R-*:R-*|r-*:r-*) REFACTOR_RANGE="$arg" ;;
|
|
84
|
+
R-*|r-*) REFACTOR_ID="$arg" ;;
|
|
85
|
+
*) REFACTOR_LIST="$arg" ;;
|
|
86
|
+
esac
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
if [[ -z "$REFACTOR_ID" && -z "$REFACTOR_RANGE" && -z "$FILTER_MODE" ]]; then
|
|
90
|
+
echo "Usage: $0 <refactor-id|range> [--clean] [--run] [--auto-skipped|--failed|--stalled] [refactor-list.json]"
|
|
91
|
+
echo ""
|
|
92
|
+
echo " refactor-id Single refactor (e.g. R-007)"
|
|
93
|
+
echo " R-008:R-013 Range of refactors (inclusive)"
|
|
94
|
+
echo " --auto-skipped Reset all auto_skipped refactors"
|
|
95
|
+
echo " --failed Reset all failed refactors"
|
|
96
|
+
echo " --stalled Reset all non-completed (failed + auto_skipped)"
|
|
97
|
+
echo " --clean Delete session history and .prizmkit artifacts"
|
|
98
|
+
echo " --run Retry immediately after reset (single refactor only)"
|
|
99
|
+
echo " refactor-list.json Path to refactor list (default: refactor-list.json)"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
REFACTOR_LIST="${REFACTOR_LIST:-refactor-list.json}"
|
|
104
|
+
|
|
105
|
+
# Resolve absolute path
|
|
106
|
+
if [[ ! "$REFACTOR_LIST" = /* ]]; then
|
|
107
|
+
REFACTOR_LIST="$(pwd)/$REFACTOR_LIST"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# ============================================================
|
|
111
|
+
# Validation
|
|
112
|
+
# ============================================================
|
|
113
|
+
|
|
114
|
+
if [[ ! -f "$REFACTOR_LIST" ]]; then
|
|
115
|
+
log_error "Refactor list not found: $REFACTOR_LIST"
|
|
116
|
+
exit 1
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
120
|
+
log_error "No pipeline state found. Run './run-refactor.sh run' first to initialize."
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# ============================================================
|
|
125
|
+
# Resolve refactor IDs to process
|
|
126
|
+
# ============================================================
|
|
127
|
+
|
|
128
|
+
REFACTOR_IDS=()
|
|
129
|
+
|
|
130
|
+
if [[ -n "$FILTER_MODE" ]]; then
|
|
131
|
+
# Filter by status from refactor-state/refactors/*/status.json
|
|
132
|
+
while IFS= read -r rid; do
|
|
133
|
+
[[ -n "$rid" ]] && REFACTOR_IDS+=("$rid")
|
|
134
|
+
done < <(python3 -c "
|
|
135
|
+
import json, os, sys
|
|
136
|
+
state_dir = '$STATE_DIR'
|
|
137
|
+
filter_mode = '$FILTER_MODE'
|
|
138
|
+
refactors_dir = os.path.join(state_dir, 'refactors')
|
|
139
|
+
if not os.path.isdir(refactors_dir):
|
|
140
|
+
sys.exit(0)
|
|
141
|
+
for rid in sorted(os.listdir(refactors_dir)):
|
|
142
|
+
status_file = os.path.join(refactors_dir, rid, 'status.json')
|
|
143
|
+
if not os.path.isfile(status_file):
|
|
144
|
+
continue
|
|
145
|
+
with open(status_file) as f:
|
|
146
|
+
status = json.load(f).get('status', '')
|
|
147
|
+
if filter_mode == 'auto_skipped' and status == 'auto_skipped':
|
|
148
|
+
print(rid)
|
|
149
|
+
elif filter_mode == 'failed' and status == 'failed':
|
|
150
|
+
print(rid)
|
|
151
|
+
elif filter_mode == 'stalled' and status in ('failed', 'auto_skipped'):
|
|
152
|
+
print(rid)
|
|
153
|
+
" 2>/dev/null)
|
|
154
|
+
|
|
155
|
+
if [[ ${#REFACTOR_IDS[@]} -eq 0 ]]; then
|
|
156
|
+
log_info "No refactors found with status: $FILTER_MODE"
|
|
157
|
+
exit 0
|
|
158
|
+
fi
|
|
159
|
+
log_info "Found ${#REFACTOR_IDS[@]} refactor(s) matching --$FILTER_MODE: ${REFACTOR_IDS[*]}"
|
|
160
|
+
|
|
161
|
+
elif [[ -n "$REFACTOR_RANGE" ]]; then
|
|
162
|
+
# Parse range R-NNN:R-MMM
|
|
163
|
+
RANGE_START="${REFACTOR_RANGE%%:*}"
|
|
164
|
+
RANGE_END="${REFACTOR_RANGE##*:}"
|
|
165
|
+
START_NUM=$(echo "$RANGE_START" | sed 's/[Rr]-//' | sed 's/^0*//')
|
|
166
|
+
END_NUM=$(echo "$RANGE_END" | sed 's/[Rr]-//' | sed 's/^0*//')
|
|
167
|
+
|
|
168
|
+
if [[ -z "$START_NUM" || -z "$END_NUM" || "$START_NUM" -gt "$END_NUM" ]]; then
|
|
169
|
+
log_error "Invalid range: $REFACTOR_RANGE (start must be <= end)"
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
for ((i=START_NUM; i<=END_NUM; i++)); do
|
|
174
|
+
REFACTOR_IDS+=("R-$(printf '%03d' "$i")")
|
|
175
|
+
done
|
|
176
|
+
log_info "Range $REFACTOR_RANGE -> ${REFACTOR_IDS[*]}"
|
|
177
|
+
|
|
178
|
+
else
|
|
179
|
+
REFACTOR_IDS=("$REFACTOR_ID")
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# --run only works with single refactor
|
|
183
|
+
if [[ "$DO_RUN" == true && ${#REFACTOR_IDS[@]} -gt 1 ]]; then
|
|
184
|
+
log_warn "--run is only supported for single refactor reset. Use './run-refactor.sh run' to resume pipeline after batch reset."
|
|
185
|
+
DO_RUN=false
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# ============================================================
|
|
189
|
+
# Process each refactor
|
|
190
|
+
# ============================================================
|
|
191
|
+
|
|
192
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
193
|
+
RESET_COUNT=0
|
|
194
|
+
FAIL_COUNT=0
|
|
195
|
+
|
|
196
|
+
for CUR_REFACTOR_ID in "${REFACTOR_IDS[@]}"; do
|
|
197
|
+
|
|
198
|
+
# Get refactor info from refactor list
|
|
199
|
+
REFACTOR_INFO=$(python3 -c "
|
|
200
|
+
import json, sys, re
|
|
201
|
+
with open('$REFACTOR_LIST') as f:
|
|
202
|
+
data = json.load(f)
|
|
203
|
+
for item in data.get('refactors', []):
|
|
204
|
+
if item.get('id') == '$CUR_REFACTOR_ID':
|
|
205
|
+
title = item.get('title', '')
|
|
206
|
+
# Compute slug
|
|
207
|
+
numeric = '$CUR_REFACTOR_ID'.replace('R-', '').replace('r-', '').zfill(3)
|
|
208
|
+
slug = title.lower()
|
|
209
|
+
slug = re.sub(r'[^a-z0-9\s-]', '', slug)
|
|
210
|
+
slug = re.sub(r'[\s]+', '-', slug.strip())
|
|
211
|
+
slug = re.sub(r'-+', '-', slug).strip('-')
|
|
212
|
+
slug = '{}-{}'.format(numeric, slug)
|
|
213
|
+
print(json.dumps({'title': title, 'slug': slug, 'status': item.get('status', 'unknown')}))
|
|
214
|
+
sys.exit(0)
|
|
215
|
+
sys.exit(1)
|
|
216
|
+
" 2>/dev/null) || {
|
|
217
|
+
log_warn "Refactor $CUR_REFACTOR_ID not found in $REFACTOR_LIST -- skipping"
|
|
218
|
+
FAIL_COUNT=$((FAIL_COUNT + 1))
|
|
219
|
+
continue
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
REFACTOR_TITLE=$(echo "$REFACTOR_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['title'])")
|
|
223
|
+
REFACTOR_SLUG=$(echo "$REFACTOR_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['slug'])")
|
|
224
|
+
|
|
225
|
+
# -- Show current state --
|
|
226
|
+
echo ""
|
|
227
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
228
|
+
echo -e "${BOLD} Reset: $CUR_REFACTOR_ID — $REFACTOR_TITLE${NC}"
|
|
229
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
230
|
+
|
|
231
|
+
STATUS_FILE="$STATE_DIR/refactors/$CUR_REFACTOR_ID/status.json"
|
|
232
|
+
if [[ -f "$STATUS_FILE" ]]; then
|
|
233
|
+
CURRENT_STATUS=$(python3 -c "import json; d=json.load(open('$STATUS_FILE')); print(d.get('status','?'))")
|
|
234
|
+
CURRENT_RETRY=$(python3 -c "import json; d=json.load(open('$STATUS_FILE')); print(d.get('retry_count',0))")
|
|
235
|
+
SESSION_COUNT=$(python3 -c "import json; d=json.load(open('$STATUS_FILE')); print(len(d.get('sessions',[])))")
|
|
236
|
+
log_info "Current status: $CURRENT_STATUS (retry $CURRENT_RETRY, $SESSION_COUNT sessions)"
|
|
237
|
+
else
|
|
238
|
+
log_info "No status file found (never executed)"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
SPECS_DIR="$PROJECT_ROOT/.prizmkit/specs/$REFACTOR_SLUG"
|
|
242
|
+
SPECS_COUNT=0
|
|
243
|
+
if [[ -d "$SPECS_DIR" ]]; then
|
|
244
|
+
SPECS_COUNT=$(find "$SPECS_DIR" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
245
|
+
log_info "PrizmKit artifacts: $SPECS_COUNT files in .prizmkit/specs/$REFACTOR_SLUG/"
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
SESSIONS_DIR="$STATE_DIR/refactors/$CUR_REFACTOR_ID/sessions"
|
|
249
|
+
SESSIONS_COUNT=0
|
|
250
|
+
if [[ -d "$SESSIONS_DIR" ]]; then
|
|
251
|
+
SESSIONS_COUNT=$(find "$SESSIONS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
252
|
+
log_info "Session history: $SESSIONS_COUNT session(s)"
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
256
|
+
|
|
257
|
+
# -- Execute reset --
|
|
258
|
+
if [[ "$DO_CLEAN" == true ]]; then
|
|
259
|
+
log_info "Cleaning $CUR_REFACTOR_ID (reset + delete artifacts)..."
|
|
260
|
+
RESULT=$(python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
261
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
262
|
+
--state-dir "$STATE_DIR" \
|
|
263
|
+
--refactor-id "$CUR_REFACTOR_ID" \
|
|
264
|
+
--project-root "$PROJECT_ROOT" \
|
|
265
|
+
--action clean 2>&1)
|
|
266
|
+
else
|
|
267
|
+
log_info "Resetting $CUR_REFACTOR_ID status..."
|
|
268
|
+
RESULT=$(python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
269
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
270
|
+
--state-dir "$STATE_DIR" \
|
|
271
|
+
--refactor-id "$CUR_REFACTOR_ID" \
|
|
272
|
+
--action reset 2>&1)
|
|
273
|
+
fi
|
|
274
|
+
|
|
275
|
+
# Check for errors
|
|
276
|
+
if echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); sys.exit(0 if 'error' not in d else 1)" 2>/dev/null; then
|
|
277
|
+
RESET_COUNT=$((RESET_COUNT + 1))
|
|
278
|
+
if [[ "$DO_CLEAN" == true ]]; then
|
|
279
|
+
log_success "$CUR_REFACTOR_ID cleaned: status -> pending, $SESSIONS_COUNT session(s) deleted, $SPECS_COUNT artifact(s) deleted"
|
|
280
|
+
else
|
|
281
|
+
log_success "$CUR_REFACTOR_ID reset: status -> pending, retry count -> 0"
|
|
282
|
+
fi
|
|
283
|
+
else
|
|
284
|
+
ERROR_MSG=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('error','unknown'))" 2>/dev/null || echo "$RESULT")
|
|
285
|
+
log_error "Reset $CUR_REFACTOR_ID failed: $ERROR_MSG"
|
|
286
|
+
FAIL_COUNT=$((FAIL_COUNT + 1))
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
done
|
|
290
|
+
|
|
291
|
+
# ============================================================
|
|
292
|
+
# Summary
|
|
293
|
+
# ============================================================
|
|
294
|
+
|
|
295
|
+
echo ""
|
|
296
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
297
|
+
echo -e "${BOLD} Reset complete: $RESET_COUNT succeeded, $FAIL_COUNT failed${NC}"
|
|
298
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
299
|
+
|
|
300
|
+
echo ""
|
|
301
|
+
echo -e "${BOLD}Next steps:${NC}"
|
|
302
|
+
if [[ "$DO_RUN" == true && ${#REFACTOR_IDS[@]} -eq 1 ]]; then
|
|
303
|
+
log_info "Auto-retrying ${REFACTOR_IDS[0]}..."
|
|
304
|
+
echo ""
|
|
305
|
+
exec "$SCRIPT_DIR/retry-refactor.sh" "${REFACTOR_IDS[0]}" "$REFACTOR_LIST"
|
|
306
|
+
else
|
|
307
|
+
log_info " ./dev-pipeline/run-refactor.sh run refactor-list.json # Resume pipeline from first pending"
|
|
308
|
+
if [[ ${#REFACTOR_IDS[@]} -eq 1 ]]; then
|
|
309
|
+
log_info " ./dev-pipeline/retry-refactor.sh ${REFACTOR_IDS[0]} # Retry single refactor"
|
|
310
|
+
fi
|
|
311
|
+
fi
|
|
312
|
+
echo ""
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# ============================================================
|
|
5
|
-
# dev-pipeline/retry-
|
|
5
|
+
# dev-pipeline/retry-bugfix.sh - Retry a single failed bug fix
|
|
6
6
|
#
|
|
7
7
|
# Runs exactly ONE AI CLI session for the specified bug, then exits.
|
|
8
8
|
# Use this to manually retry a failed bug without restarting
|
|
9
9
|
# the full bugfix pipeline.
|
|
10
10
|
#
|
|
11
11
|
# Usage:
|
|
12
|
-
# ./retry-
|
|
12
|
+
# ./retry-bugfix.sh <bug-id> [bug-fix-list.json]
|
|
13
13
|
#
|
|
14
14
|
# Examples:
|
|
15
|
-
# ./retry-
|
|
16
|
-
# ./retry-
|
|
17
|
-
# SESSION_TIMEOUT=3600 ./retry-
|
|
15
|
+
# ./retry-bugfix.sh B-001
|
|
16
|
+
# ./retry-bugfix.sh B-001 bug-fix-list.json
|
|
17
|
+
# SESSION_TIMEOUT=3600 ./retry-bugfix.sh B-001
|
|
18
18
|
# ============================================================
|
|
19
19
|
|
|
20
20
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -23,68 +23,22 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
|
23
23
|
|
|
24
24
|
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
25
25
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
26
|
+
AUTO_PUSH=${AUTO_PUSH:-0}
|
|
27
|
+
DEV_BRANCH=${DEV_BRANCH:-""}
|
|
26
28
|
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
elif [[ -f ".prizmkit/config.json" ]]; then
|
|
31
|
-
_config_cli=$(python3 -c "
|
|
32
|
-
import json, sys
|
|
33
|
-
try:
|
|
34
|
-
with open('.prizmkit/config.json') as f:
|
|
35
|
-
d = json.load(f)
|
|
36
|
-
v = d.get('ai_cli', '')
|
|
37
|
-
if v: print(v)
|
|
38
|
-
except: pass
|
|
39
|
-
" 2>/dev/null || true)
|
|
40
|
-
CLI_CMD="${_config_cli:-}"
|
|
41
|
-
if [[ -z "$CLI_CMD" ]]; then
|
|
42
|
-
if [[ -n "${CODEBUDDY_CLI:-}" ]]; then CLI_CMD="$CODEBUDDY_CLI"
|
|
43
|
-
elif command -v cbc &>/dev/null; then CLI_CMD="cbc"
|
|
44
|
-
elif command -v claude &>/dev/null; then CLI_CMD="claude"
|
|
45
|
-
else echo "ERROR: No AI CLI found. Set AI_CLI or configure .prizmkit/config.json" >&2; exit 1
|
|
46
|
-
fi
|
|
47
|
-
fi
|
|
48
|
-
elif [[ -n "${CODEBUDDY_CLI:-}" ]]; then
|
|
49
|
-
CLI_CMD="$CODEBUDDY_CLI"
|
|
50
|
-
elif command -v cbc &>/dev/null; then
|
|
51
|
-
CLI_CMD="cbc"
|
|
52
|
-
elif command -v claude &>/dev/null; then
|
|
53
|
-
CLI_CMD="claude"
|
|
54
|
-
else
|
|
55
|
-
echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude), or set AI_CLI." >&2
|
|
56
|
-
exit 1
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# Platform detection
|
|
60
|
-
if [[ -n "${PRIZMKIT_PLATFORM:-}" ]]; then
|
|
61
|
-
PLATFORM="$PRIZMKIT_PLATFORM"
|
|
62
|
-
elif [[ "$CLI_CMD" == *"claude"* ]]; then
|
|
63
|
-
PLATFORM="claude"
|
|
64
|
-
else
|
|
65
|
-
PLATFORM="codebuddy"
|
|
66
|
-
fi
|
|
67
|
-
export PRIZMKIT_PLATFORM="$PLATFORM"
|
|
29
|
+
# Source shared libraries (CLI/platform detection + logs + deps)
|
|
30
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
31
|
+
prizm_detect_cli_and_platform
|
|
68
32
|
|
|
69
33
|
# Source shared heartbeat library
|
|
70
34
|
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
71
35
|
|
|
36
|
+
# Source shared branch library
|
|
37
|
+
source "$SCRIPT_DIR/lib/branch.sh"
|
|
38
|
+
|
|
72
39
|
# Detect stream-json support
|
|
73
40
|
detect_stream_json_support "$CLI_CMD"
|
|
74
41
|
|
|
75
|
-
# Colors
|
|
76
|
-
RED='\033[0;31m'
|
|
77
|
-
GREEN='\033[0;32m'
|
|
78
|
-
YELLOW='\033[1;33m'
|
|
79
|
-
BLUE='\033[0;34m'
|
|
80
|
-
BOLD='\033[1m'
|
|
81
|
-
NC='\033[0m'
|
|
82
|
-
|
|
83
|
-
log_info() { echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
84
|
-
log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
85
|
-
log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
86
|
-
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
87
|
-
|
|
88
42
|
# ============================================================
|
|
89
43
|
# Args
|
|
90
44
|
# ============================================================
|
|
@@ -98,6 +52,9 @@ if [[ $# -lt 1 ]]; then
|
|
|
98
52
|
echo "Environment Variables:"
|
|
99
53
|
echo " SESSION_TIMEOUT Timeout in seconds (default: 0 = no limit)"
|
|
100
54
|
echo " HEARTBEAT_INTERVAL Heartbeat interval in seconds (default: 30)"
|
|
55
|
+
echo " AI_CLI AI CLI command (auto-detected: cbc or claude)"
|
|
56
|
+
echo " AUTO_PUSH Auto-push to remote after fix (default: 0)"
|
|
57
|
+
echo " DEV_BRANCH Custom dev branch name (default: auto-generated)"
|
|
101
58
|
exit 1
|
|
102
59
|
fi
|
|
103
60
|
|
|
@@ -166,6 +123,9 @@ sys.exit(1)
|
|
|
166
123
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
167
124
|
ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
168
125
|
|
|
126
|
+
# Branch tracking (for cleanup on interrupt)
|
|
127
|
+
_DEV_BRANCH_NAME=""
|
|
128
|
+
|
|
169
129
|
log_info "Cleaning $BUG_ID artifacts for full restart..."
|
|
170
130
|
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
171
131
|
--bug-list "$BUG_LIST" \
|
|
@@ -202,6 +162,15 @@ python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" \
|
|
|
202
162
|
# Run single AI CLI session
|
|
203
163
|
# ============================================================
|
|
204
164
|
|
|
165
|
+
# Branch lifecycle: create and checkout bugfix branch
|
|
166
|
+
_branch_name="${DEV_BRANCH:-bugfix/${BUG_ID}-$(date +%s)}"
|
|
167
|
+
if branch_create "$PROJECT_ROOT" "$_branch_name" "$ORIGINAL_BRANCH"; then
|
|
168
|
+
_DEV_BRANCH_NAME="$_branch_name"
|
|
169
|
+
log_info "Dev branch: $_branch_name"
|
|
170
|
+
else
|
|
171
|
+
log_warn "Failed to create branch; running session on current branch"
|
|
172
|
+
fi
|
|
173
|
+
|
|
205
174
|
echo ""
|
|
206
175
|
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
207
176
|
echo -e "${BOLD} Retry Bug Fix: $BUG_ID — $BUG_TITLE${NC}"
|
|
@@ -295,6 +264,10 @@ cleanup() {
|
|
|
295
264
|
stop_progress_parser "$PARSER_PID"
|
|
296
265
|
wait "$CLI_PID" 2>/dev/null || true
|
|
297
266
|
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
267
|
+
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
268
|
+
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
269
|
+
log_info "Original branch was: $ORIGINAL_BRANCH"
|
|
270
|
+
fi
|
|
298
271
|
log_info "Session log: $SESSION_LOG"
|
|
299
272
|
exit 130
|
|
300
273
|
}
|
|
@@ -380,6 +353,15 @@ if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
|
380
353
|
fi
|
|
381
354
|
fi
|
|
382
355
|
|
|
356
|
+
# ── Merge dev branch back to original on success ────────────────────
|
|
357
|
+
if [[ "$SESSION_STATUS" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
358
|
+
if branch_merge "$PROJECT_ROOT" "$_DEV_BRANCH_NAME" "$ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
359
|
+
_DEV_BRANCH_NAME=""
|
|
360
|
+
else
|
|
361
|
+
log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
|
|
362
|
+
fi
|
|
363
|
+
fi
|
|
364
|
+
|
|
383
365
|
# Update bug status
|
|
384
366
|
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
385
367
|
--bug-list "$BUG_LIST" \
|
|
@@ -390,6 +372,12 @@ python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
|
390
372
|
--max-retries 999 \
|
|
391
373
|
--action update >/dev/null 2>&1 || true
|
|
392
374
|
|
|
375
|
+
# Commit bug-fix-list.json status update (pipeline management commit)
|
|
376
|
+
if ! git -C "$PROJECT_ROOT" diff --quiet "$BUG_LIST" 2>/dev/null; then
|
|
377
|
+
git -C "$PROJECT_ROOT" add "$BUG_LIST"
|
|
378
|
+
git -C "$PROJECT_ROOT" commit --no-verify -m "chore($BUG_ID): update bug status" 2>/dev/null || true
|
|
379
|
+
fi
|
|
380
|
+
|
|
393
381
|
echo ""
|
|
394
382
|
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
395
383
|
log_success "════════════════════════════════════════════════════"
|
|
@@ -24,66 +24,23 @@ SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
|
24
24
|
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
25
25
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
26
26
|
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
elif [[ -f ".prizmkit/config.json" ]]; then
|
|
31
|
-
_config_cli=$(python3 -c "
|
|
32
|
-
import json, sys
|
|
33
|
-
try:
|
|
34
|
-
with open('.prizmkit/config.json') as f:
|
|
35
|
-
d = json.load(f)
|
|
36
|
-
v = d.get('ai_cli', '')
|
|
37
|
-
if v: print(v)
|
|
38
|
-
except: pass
|
|
39
|
-
" 2>/dev/null || true)
|
|
40
|
-
CLI_CMD="${_config_cli:-}"
|
|
41
|
-
if [[ -z "$CLI_CMD" ]]; then
|
|
42
|
-
if [[ -n "${CODEBUDDY_CLI:-}" ]]; then CLI_CMD="$CODEBUDDY_CLI"
|
|
43
|
-
elif command -v cbc &>/dev/null; then CLI_CMD="cbc"
|
|
44
|
-
elif command -v claude &>/dev/null; then CLI_CMD="claude"
|
|
45
|
-
else echo "ERROR: No AI CLI found. Set AI_CLI or configure .prizmkit/config.json" >&2; exit 1
|
|
46
|
-
fi
|
|
47
|
-
fi
|
|
48
|
-
elif [[ -n "${CODEBUDDY_CLI:-}" ]]; then
|
|
49
|
-
CLI_CMD="$CODEBUDDY_CLI"
|
|
50
|
-
elif command -v cbc &>/dev/null; then
|
|
51
|
-
CLI_CMD="cbc"
|
|
52
|
-
elif command -v claude &>/dev/null; then
|
|
53
|
-
CLI_CMD="claude"
|
|
54
|
-
else
|
|
55
|
-
echo "ERROR: No AI CLI found. Install CodeBuddy (cbc) or Claude Code (claude), or set AI_CLI." >&2
|
|
56
|
-
exit 1
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# Platform detection
|
|
60
|
-
if [[ -n "${PRIZMKIT_PLATFORM:-}" ]]; then
|
|
61
|
-
PLATFORM="$PRIZMKIT_PLATFORM"
|
|
62
|
-
elif [[ "$CLI_CMD" == *"claude"* ]]; then
|
|
63
|
-
PLATFORM="claude"
|
|
64
|
-
else
|
|
65
|
-
PLATFORM="codebuddy"
|
|
66
|
-
fi
|
|
67
|
-
export PRIZMKIT_PLATFORM="$PLATFORM"
|
|
27
|
+
# Source shared common helpers (CLI/platform detection + logs + deps)
|
|
28
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
29
|
+
prizm_detect_cli_and_platform
|
|
68
30
|
|
|
69
31
|
# Source shared heartbeat library
|
|
70
32
|
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
71
33
|
|
|
34
|
+
# Source shared branch library
|
|
35
|
+
source "$SCRIPT_DIR/lib/branch.sh"
|
|
36
|
+
|
|
72
37
|
# Detect stream-json support
|
|
73
38
|
detect_stream_json_support "$CLI_CMD"
|
|
74
39
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
BLUE='\033[0;34m'
|
|
80
|
-
BOLD='\033[1m'
|
|
81
|
-
NC='\033[0m'
|
|
82
|
-
|
|
83
|
-
log_info() { echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
84
|
-
log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
85
|
-
log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
86
|
-
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
40
|
+
# Branch tracking
|
|
41
|
+
_ORIGINAL_BRANCH=""
|
|
42
|
+
_DEV_BRANCH_NAME=""
|
|
43
|
+
AUTO_PUSH=${AUTO_PUSH:-0}
|
|
87
44
|
|
|
88
45
|
# ============================================================
|
|
89
46
|
# Args
|
|
@@ -120,7 +77,7 @@ if [[ ! -f "$FEATURE_LIST" ]]; then
|
|
|
120
77
|
fi
|
|
121
78
|
|
|
122
79
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
123
|
-
log_error "No pipeline state found. Run './run.sh run' first to initialize."
|
|
80
|
+
log_error "No pipeline state found. Run './run-feature.sh run' first to initialize."
|
|
124
81
|
exit 1
|
|
125
82
|
fi
|
|
126
83
|
|
|
@@ -150,6 +107,7 @@ sys.exit(1)
|
|
|
150
107
|
|
|
151
108
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
152
109
|
ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
110
|
+
_ORIGINAL_BRANCH="$ORIGINAL_BRANCH"
|
|
153
111
|
FEATURE_SLUG=$(FEATURE_ID="$FEATURE_ID" FEATURE_TITLE="$FEATURE_TITLE" python3 -c "
|
|
154
112
|
import os, re
|
|
155
113
|
fid = os.environ['FEATURE_ID'].replace('F-', '').replace('f-', '').zfill(3)
|
|
@@ -232,6 +190,15 @@ log_info "Log: $SESSION_DIR/logs/session.log"
|
|
|
232
190
|
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
233
191
|
echo ""
|
|
234
192
|
|
|
193
|
+
# Create per-feature dev branch (consistent with run-feature.sh behavior)
|
|
194
|
+
_feature_branch="${DEV_BRANCH:-dev/${FEATURE_ID}-retry-$(date +%Y%m%d%H%M)}"
|
|
195
|
+
if branch_create "$PROJECT_ROOT" "$_feature_branch" "$_ORIGINAL_BRANCH"; then
|
|
196
|
+
_DEV_BRANCH_NAME="$_feature_branch"
|
|
197
|
+
log_info "Dev branch: $_feature_branch"
|
|
198
|
+
else
|
|
199
|
+
log_warn "Failed to create dev branch; running on current branch"
|
|
200
|
+
fi
|
|
201
|
+
|
|
235
202
|
SESSION_LOG="$SESSION_DIR/logs/session.log"
|
|
236
203
|
PROGRESS_JSON="$SESSION_DIR/logs/progress.json"
|
|
237
204
|
|
|
@@ -409,6 +376,26 @@ python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
|
409
376
|
--max-retries 999 \
|
|
410
377
|
--action update >/dev/null 2>&1 || true
|
|
411
378
|
|
|
379
|
+
# Commit feature-list.json status update (pipeline management commit)
|
|
380
|
+
if ! git -C "$PROJECT_ROOT" diff --quiet "$FEATURE_LIST" 2>/dev/null; then
|
|
381
|
+
git -C "$PROJECT_ROOT" add "$FEATURE_LIST"
|
|
382
|
+
git -C "$PROJECT_ROOT" commit --no-verify -m "chore($FEATURE_ID): update feature status" 2>/dev/null || true
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
# Merge dev branch back to original on success
|
|
386
|
+
if [[ "$SESSION_STATUS" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
387
|
+
if branch_merge "$PROJECT_ROOT" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
388
|
+
_DEV_BRANCH_NAME=""
|
|
389
|
+
else
|
|
390
|
+
log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
|
|
391
|
+
fi
|
|
392
|
+
elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
393
|
+
# Session failed — return to original branch, preserve dev branch for inspection
|
|
394
|
+
git -C "$PROJECT_ROOT" checkout "$_ORIGINAL_BRANCH" 2>/dev/null || true
|
|
395
|
+
log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
|
|
396
|
+
_DEV_BRANCH_NAME=""
|
|
397
|
+
fi
|
|
398
|
+
|
|
412
399
|
echo ""
|
|
413
400
|
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
414
401
|
log_success "════════════════════════════════════════════════════"
|