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,358 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# ============================================================
|
|
5
|
+
# dev-pipeline/retry-refactor.sh - Retry a single failed refactor
|
|
6
|
+
#
|
|
7
|
+
# Runs exactly ONE AI CLI session for the specified refactor, then exits.
|
|
8
|
+
# Use this to manually retry a failed refactor without restarting
|
|
9
|
+
# the full refactor pipeline.
|
|
10
|
+
#
|
|
11
|
+
# Usage:
|
|
12
|
+
# ./retry-refactor.sh <refactor-id> [refactor-list.json]
|
|
13
|
+
#
|
|
14
|
+
# Examples:
|
|
15
|
+
# ./retry-refactor.sh R-001
|
|
16
|
+
# ./retry-refactor.sh R-001 refactor-list.json
|
|
17
|
+
# SESSION_TIMEOUT=3600 ./retry-refactor.sh R-001
|
|
18
|
+
# ============================================================
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
STATE_DIR="$SCRIPT_DIR/refactor-state"
|
|
22
|
+
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
23
|
+
|
|
24
|
+
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
25
|
+
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
26
|
+
|
|
27
|
+
# Source shared common helpers (CLI/platform detection + logs + deps)
|
|
28
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
29
|
+
prizm_detect_cli_and_platform
|
|
30
|
+
|
|
31
|
+
# Source shared heartbeat library
|
|
32
|
+
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
33
|
+
|
|
34
|
+
# Detect stream-json support
|
|
35
|
+
detect_stream_json_support "$CLI_CMD"
|
|
36
|
+
|
|
37
|
+
# ============================================================
|
|
38
|
+
# Args
|
|
39
|
+
# ============================================================
|
|
40
|
+
|
|
41
|
+
if [[ $# -lt 1 ]]; then
|
|
42
|
+
echo "Usage: $0 <refactor-id> [refactor-list.json]"
|
|
43
|
+
echo ""
|
|
44
|
+
echo " refactor-id Refactor to retry (e.g. R-001)"
|
|
45
|
+
echo " refactor-list.json Path to refactor list (default: refactor-list.json)"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Environment Variables:"
|
|
48
|
+
echo " SESSION_TIMEOUT Timeout in seconds (default: 0 = no limit)"
|
|
49
|
+
echo " HEARTBEAT_INTERVAL Heartbeat interval in seconds (default: 30)"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
REFACTOR_ID="$1"
|
|
54
|
+
REFACTOR_LIST="${2:-refactor-list.json}"
|
|
55
|
+
|
|
56
|
+
if [[ ! "$REFACTOR_LIST" = /* ]]; then
|
|
57
|
+
REFACTOR_LIST="$(pwd)/$REFACTOR_LIST"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# ============================================================
|
|
61
|
+
# Validation
|
|
62
|
+
# ============================================================
|
|
63
|
+
|
|
64
|
+
if [[ ! -f "$REFACTOR_LIST" ]]; then
|
|
65
|
+
log_error "Refactor list not found: $REFACTOR_LIST"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
if ! command -v jq &>/dev/null; then
|
|
70
|
+
log_error "jq is required. Install with: brew install jq"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Initialize state if needed
|
|
75
|
+
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
76
|
+
log_info "Initializing refactor pipeline state..."
|
|
77
|
+
python3 "$SCRIPTS_DIR/init-refactor-pipeline.py" \
|
|
78
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
79
|
+
--state-dir "$STATE_DIR" >/dev/null 2>&1 || {
|
|
80
|
+
log_error "Failed to initialize refactor pipeline state"
|
|
81
|
+
exit 1
|
|
82
|
+
}
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Verify refactor exists
|
|
86
|
+
REFACTOR_TITLE=$(python3 -c "
|
|
87
|
+
import json, sys
|
|
88
|
+
with open('$REFACTOR_LIST') as f:
|
|
89
|
+
data = json.load(f)
|
|
90
|
+
for item in data.get('refactors', []):
|
|
91
|
+
if item.get('id') == '$REFACTOR_ID':
|
|
92
|
+
print(item.get('title', ''))
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
sys.exit(1)
|
|
95
|
+
" 2>/dev/null) || {
|
|
96
|
+
log_error "Refactor $REFACTOR_ID not found in $REFACTOR_LIST"
|
|
97
|
+
exit 1
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
REFACTOR_COMPLEXITY=$(python3 -c "
|
|
101
|
+
import json, sys
|
|
102
|
+
with open('$REFACTOR_LIST') as f:
|
|
103
|
+
data = json.load(f)
|
|
104
|
+
for item in data.get('refactors', []):
|
|
105
|
+
if item.get('id') == '$REFACTOR_ID':
|
|
106
|
+
print(item.get('complexity', 'medium'))
|
|
107
|
+
sys.exit(0)
|
|
108
|
+
sys.exit(1)
|
|
109
|
+
" 2>/dev/null) || REFACTOR_COMPLEXITY="medium"
|
|
110
|
+
|
|
111
|
+
# ============================================================
|
|
112
|
+
# Clean refactor artifacts + reset status for a full restart
|
|
113
|
+
# ============================================================
|
|
114
|
+
|
|
115
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
116
|
+
ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
117
|
+
|
|
118
|
+
log_info "Cleaning $REFACTOR_ID artifacts for full restart..."
|
|
119
|
+
python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
120
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
121
|
+
--state-dir "$STATE_DIR" \
|
|
122
|
+
--refactor-id "$REFACTOR_ID" \
|
|
123
|
+
--project-root "$PROJECT_ROOT" \
|
|
124
|
+
--action clean >/dev/null 2>&1 || {
|
|
125
|
+
log_warn "Failed to clean refactor artifacts (continuing with fresh session only)"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# ============================================================
|
|
129
|
+
# Generate bootstrap prompt
|
|
130
|
+
# ============================================================
|
|
131
|
+
|
|
132
|
+
RUN_ID=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
133
|
+
SESSION_ID="${REFACTOR_ID}-$(date +%Y%m%d%H%M%S)"
|
|
134
|
+
SESSION_DIR="$STATE_DIR/refactors/$REFACTOR_ID/sessions/$SESSION_ID"
|
|
135
|
+
mkdir -p "$SESSION_DIR/logs"
|
|
136
|
+
|
|
137
|
+
BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
|
|
138
|
+
|
|
139
|
+
log_info "Generating refactor bootstrap prompt..."
|
|
140
|
+
python3 "$SCRIPTS_DIR/generate-refactor-prompt.py" \
|
|
141
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
142
|
+
--refactor-id "$REFACTOR_ID" \
|
|
143
|
+
--session-id "$SESSION_ID" \
|
|
144
|
+
--run-id "$RUN_ID" \
|
|
145
|
+
--retry-count 0 \
|
|
146
|
+
--resume-phase "null" \
|
|
147
|
+
--state-dir "$STATE_DIR" \
|
|
148
|
+
--output "$BOOTSTRAP_PROMPT" >/dev/null 2>&1
|
|
149
|
+
|
|
150
|
+
# ============================================================
|
|
151
|
+
# Run single AI CLI session
|
|
152
|
+
# ============================================================
|
|
153
|
+
|
|
154
|
+
echo ""
|
|
155
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
156
|
+
echo -e "${BOLD} Retry Refactor: $REFACTOR_ID — $REFACTOR_TITLE${NC}"
|
|
157
|
+
echo -e "${BOLD} Complexity: $REFACTOR_COMPLEXITY${NC}"
|
|
158
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
159
|
+
log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
160
|
+
if [[ -n "${MODEL:-}" ]]; then
|
|
161
|
+
log_info "Model: $MODEL"
|
|
162
|
+
else
|
|
163
|
+
log_info "Model: (CLI default)"
|
|
164
|
+
fi
|
|
165
|
+
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
166
|
+
log_info "Session timeout: ${SESSION_TIMEOUT}s"
|
|
167
|
+
else
|
|
168
|
+
log_info "Session timeout: none"
|
|
169
|
+
fi
|
|
170
|
+
log_info "Prompt: $BOOTSTRAP_PROMPT"
|
|
171
|
+
log_info "Log: $SESSION_DIR/logs/session.log"
|
|
172
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
173
|
+
echo ""
|
|
174
|
+
|
|
175
|
+
SESSION_LOG="$SESSION_DIR/logs/session.log"
|
|
176
|
+
PROGRESS_JSON="$SESSION_DIR/logs/progress.json"
|
|
177
|
+
|
|
178
|
+
# Build stream-json flag
|
|
179
|
+
STREAM_JSON_FLAG=""
|
|
180
|
+
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
181
|
+
STREAM_JSON_FLAG="--output-format stream-json"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# claude-internal requires --verbose when using stream-json with -p/--print
|
|
185
|
+
VERBOSE_FLAG=""
|
|
186
|
+
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
187
|
+
VERBOSE_FLAG="--verbose"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Spawn AI CLI session
|
|
191
|
+
MODEL_FLAG=""
|
|
192
|
+
if [[ -n "${MODEL:-}" ]]; then
|
|
193
|
+
MODEL_FLAG="--model $MODEL"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
unset CLAUDECODE 2>/dev/null || true
|
|
197
|
+
|
|
198
|
+
case "$CLI_CMD" in
|
|
199
|
+
*claude*)
|
|
200
|
+
# Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
|
|
201
|
+
"$CLI_CMD" \
|
|
202
|
+
-p "$(cat "$BOOTSTRAP_PROMPT")" \
|
|
203
|
+
--dangerously-skip-permissions \
|
|
204
|
+
$VERBOSE_FLAG \
|
|
205
|
+
$STREAM_JSON_FLAG \
|
|
206
|
+
$MODEL_FLAG \
|
|
207
|
+
> "$SESSION_LOG" 2>&1 &
|
|
208
|
+
;;
|
|
209
|
+
*)
|
|
210
|
+
# CodeBuddy (cbc) and others: prompt via stdin
|
|
211
|
+
"$CLI_CMD" \
|
|
212
|
+
--print \
|
|
213
|
+
-y \
|
|
214
|
+
$STREAM_JSON_FLAG \
|
|
215
|
+
$MODEL_FLAG \
|
|
216
|
+
< "$BOOTSTRAP_PROMPT" \
|
|
217
|
+
> "$SESSION_LOG" 2>&1 &
|
|
218
|
+
;;
|
|
219
|
+
esac
|
|
220
|
+
CLI_PID=$!
|
|
221
|
+
|
|
222
|
+
# Start progress parser (no-op if stream-json not supported)
|
|
223
|
+
start_progress_parser "$SESSION_LOG" "$PROGRESS_JSON" "$SCRIPTS_DIR"
|
|
224
|
+
PARSER_PID="${_PARSER_PID:-}"
|
|
225
|
+
|
|
226
|
+
# Timeout watchdog
|
|
227
|
+
WATCHER_PID=""
|
|
228
|
+
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
229
|
+
( sleep "$SESSION_TIMEOUT" && kill -TERM "$CLI_PID" 2>/dev/null ) &
|
|
230
|
+
WATCHER_PID=$!
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# Heartbeat
|
|
234
|
+
start_heartbeat "$CLI_PID" "$SESSION_LOG" "$PROGRESS_JSON" "$HEARTBEAT_INTERVAL"
|
|
235
|
+
HEARTBEAT_PID="${_HEARTBEAT_PID:-}"
|
|
236
|
+
|
|
237
|
+
# Ctrl+C cleanup
|
|
238
|
+
cleanup() {
|
|
239
|
+
echo ""
|
|
240
|
+
log_warn "Interrupted. Killing session..."
|
|
241
|
+
kill "$CLI_PID" 2>/dev/null || true
|
|
242
|
+
[[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
|
|
243
|
+
stop_heartbeat "$HEARTBEAT_PID"
|
|
244
|
+
stop_progress_parser "$PARSER_PID"
|
|
245
|
+
wait "$CLI_PID" 2>/dev/null || true
|
|
246
|
+
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
247
|
+
log_info "Session log: $SESSION_LOG"
|
|
248
|
+
exit 130
|
|
249
|
+
}
|
|
250
|
+
trap cleanup SIGINT SIGTERM
|
|
251
|
+
|
|
252
|
+
# Wait
|
|
253
|
+
EXIT_CODE=0
|
|
254
|
+
if wait "$CLI_PID" 2>/dev/null; then
|
|
255
|
+
EXIT_CODE=0
|
|
256
|
+
else
|
|
257
|
+
EXIT_CODE=$?
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
# Cleanup background processes
|
|
261
|
+
[[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
|
|
262
|
+
stop_heartbeat "$HEARTBEAT_PID"
|
|
263
|
+
stop_progress_parser "$PARSER_PID"
|
|
264
|
+
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
265
|
+
|
|
266
|
+
[[ $EXIT_CODE -eq 143 ]] && EXIT_CODE=124
|
|
267
|
+
|
|
268
|
+
# ============================================================
|
|
269
|
+
# Check result
|
|
270
|
+
# ============================================================
|
|
271
|
+
|
|
272
|
+
echo ""
|
|
273
|
+
if [[ -f "$SESSION_LOG" ]]; then
|
|
274
|
+
FINAL_LINES=$(wc -l < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
275
|
+
FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
276
|
+
log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
|
|
277
|
+
fi
|
|
278
|
+
log_info "exit_code=$EXIT_CODE"
|
|
279
|
+
|
|
280
|
+
# ── Determine session outcome from observable signals ──────────────
|
|
281
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
282
|
+
DEFAULT_BRANCH="$ORIGINAL_BRANCH"
|
|
283
|
+
|
|
284
|
+
if [[ $EXIT_CODE -eq 124 ]]; then
|
|
285
|
+
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
286
|
+
SESSION_STATUS="timed_out"
|
|
287
|
+
elif [[ $EXIT_CODE -ne 0 ]]; then
|
|
288
|
+
log_warn "Session exited with code $EXIT_CODE"
|
|
289
|
+
SESSION_STATUS="crashed"
|
|
290
|
+
else
|
|
291
|
+
# Exit code 0 — check if the session produced commits
|
|
292
|
+
HAS_COMMITS=""
|
|
293
|
+
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
294
|
+
HAS_COMMITS=$(git -C "$PROJECT_ROOT" log "${DEFAULT_BRANCH}..HEAD" --oneline 2>/dev/null | head -1)
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
if [[ -n "$HAS_COMMITS" ]]; then
|
|
298
|
+
SESSION_STATUS="success"
|
|
299
|
+
else
|
|
300
|
+
UNCOMMITTED=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null | head -1 || true)
|
|
301
|
+
if [[ -n "$UNCOMMITTED" ]]; then
|
|
302
|
+
log_warn "Session exited cleanly but produced no commits (uncommitted changes found) — auto-committing..."
|
|
303
|
+
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
304
|
+
if git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): auto-commit session work" 2>/dev/null; then
|
|
305
|
+
log_info "Auto-commit succeeded"
|
|
306
|
+
SESSION_STATUS="success"
|
|
307
|
+
else
|
|
308
|
+
log_warn "Auto-commit failed — no changes to commit"
|
|
309
|
+
SESSION_STATUS="crashed"
|
|
310
|
+
fi
|
|
311
|
+
else
|
|
312
|
+
log_warn "Session exited cleanly but produced no commits and no changes"
|
|
313
|
+
SESSION_STATUS="crashed"
|
|
314
|
+
fi
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
# ── Post-success validation ──────────────────────────────────────────
|
|
319
|
+
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
320
|
+
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
321
|
+
DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
|
|
322
|
+
if [[ -n "$DIRTY_FILES" ]]; then
|
|
323
|
+
log_info "Auto-committing remaining session artifacts..."
|
|
324
|
+
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
325
|
+
git -C "$PROJECT_ROOT" commit --no-verify --amend --no-edit -a 2>/dev/null \
|
|
326
|
+
|| git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): include remaining session artifacts" 2>/dev/null \
|
|
327
|
+
|| true
|
|
328
|
+
fi
|
|
329
|
+
fi
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
# Update refactor status
|
|
333
|
+
python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
334
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
335
|
+
--state-dir "$STATE_DIR" \
|
|
336
|
+
--refactor-id "$REFACTOR_ID" \
|
|
337
|
+
--session-status "$SESSION_STATUS" \
|
|
338
|
+
--session-id "$SESSION_ID" \
|
|
339
|
+
--max-retries 999 \
|
|
340
|
+
--action update >/dev/null 2>&1 || true
|
|
341
|
+
|
|
342
|
+
# Commit refactor-list.json status update (pipeline management commit)
|
|
343
|
+
if ! git -C "$PROJECT_ROOT" diff --quiet "$REFACTOR_LIST" 2>/dev/null; then
|
|
344
|
+
git -C "$PROJECT_ROOT" add "$REFACTOR_LIST"
|
|
345
|
+
git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): update refactor status" 2>/dev/null || true
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
echo ""
|
|
349
|
+
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
350
|
+
log_success "════════════════════════════════════════════════════"
|
|
351
|
+
log_success " $REFACTOR_ID completed successfully!"
|
|
352
|
+
log_success "════════════════════════════════════════════════════"
|
|
353
|
+
else
|
|
354
|
+
log_error "════════════════════════════════════════════════════"
|
|
355
|
+
log_error " $REFACTOR_ID result: $SESSION_STATUS"
|
|
356
|
+
log_error " Review log: $SESSION_LOG"
|
|
357
|
+
log_error "════════════════════════════════════════════════════"
|
|
358
|
+
fi
|
|
@@ -237,6 +237,12 @@ spawn_and_wait_session() {
|
|
|
237
237
|
--max-retries "$max_retries" \
|
|
238
238
|
--action update >/dev/null 2>&1 || true
|
|
239
239
|
|
|
240
|
+
# Commit bug-fix-list.json status update (pipeline management commit)
|
|
241
|
+
if ! git -C "$project_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
242
|
+
git -C "$project_root" add "$bug_list"
|
|
243
|
+
git -C "$project_root" commit --no-verify -m "chore($bug_id): update bug status" 2>/dev/null || true
|
|
244
|
+
fi
|
|
245
|
+
|
|
240
246
|
_SPAWN_RESULT="$session_status"
|
|
241
247
|
}
|
|
242
248
|
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# ============================================================
|
|
5
|
-
# dev-pipeline/run.sh - Autonomous Dev Pipeline Runner
|
|
5
|
+
# dev-pipeline/run-feature.sh - Autonomous Dev Pipeline Runner
|
|
6
6
|
#
|
|
7
7
|
# Drives the prizm-dev-team multi-agent team through iterative
|
|
8
8
|
# AI CLI sessions (CodeBuddy or Claude Code) to build a complete app
|
|
9
9
|
# from a feature list.
|
|
10
10
|
#
|
|
11
11
|
# Usage:
|
|
12
|
-
# ./run.sh run [feature-list.json] Run all features
|
|
13
|
-
# ./run.sh run <feature-id> [options] Run a single feature
|
|
14
|
-
# ./run.sh status [feature-list.json] Show pipeline status
|
|
15
|
-
# ./run.sh reset Clear all state
|
|
12
|
+
# ./run-feature.sh run [feature-list.json] Run all features
|
|
13
|
+
# ./run-feature.sh run <feature-id> [options] Run a single feature
|
|
14
|
+
# ./run-feature.sh status [feature-list.json] Show pipeline status
|
|
15
|
+
# ./run-feature.sh reset Clear all state
|
|
16
16
|
#
|
|
17
17
|
# Environment Variables:
|
|
18
18
|
# MAX_RETRIES Max retries per feature (default: 3)
|
|
@@ -116,7 +116,7 @@ spawn_and_wait_session() {
|
|
|
116
116
|
fi
|
|
117
117
|
|
|
118
118
|
# Unset CLAUDECODE to prevent "nested session" error when launched from
|
|
119
|
-
# within an existing Claude Code session (e.g. via launch-daemon.sh).
|
|
119
|
+
# within an existing Claude Code session (e.g. via launch-feature-daemon.sh).
|
|
120
120
|
unset CLAUDECODE 2>/dev/null || true
|
|
121
121
|
|
|
122
122
|
case "$CLI_CMD" in
|
|
@@ -316,8 +316,8 @@ sys.exit(1)
|
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
# Commit feature status update (pipeline management commit)
|
|
319
|
-
if ! git -C "$project_root" diff --quiet
|
|
320
|
-
git -C "$project_root" add
|
|
319
|
+
if ! git -C "$project_root" diff --quiet "$feature_list" 2>/dev/null; then
|
|
320
|
+
git -C "$project_root" add "$feature_list"
|
|
321
321
|
git -C "$project_root" commit --no-verify -m "chore($feature_id): update feature status" 2>/dev/null || true
|
|
322
322
|
fi
|
|
323
323
|
|
|
@@ -349,7 +349,7 @@ cleanup() {
|
|
|
349
349
|
--action pause 2>/dev/null || true
|
|
350
350
|
fi
|
|
351
351
|
|
|
352
|
-
log_info "Pipeline paused. Run './run.sh run' to resume."
|
|
352
|
+
log_info "Pipeline paused. Run './run-feature.sh run' to resume."
|
|
353
353
|
exit 130
|
|
354
354
|
}
|
|
355
355
|
trap cleanup SIGINT SIGTERM
|
|
@@ -809,8 +809,8 @@ main() {
|
|
|
809
809
|
# Validate feature list exists
|
|
810
810
|
if [[ ! -f "$feature_list" ]]; then
|
|
811
811
|
log_error "Feature list not found: $feature_list"
|
|
812
|
-
log_info "Create a feature list first using the
|
|
813
|
-
log_info "or provide a path: ./run.sh run <path-to-feature-list.json>"
|
|
812
|
+
log_info "Create a feature list first using the feature-planner skill,"
|
|
813
|
+
log_info "or provide a path: ./run-feature.sh run <path-to-feature-list.json>"
|
|
814
814
|
exit 1
|
|
815
815
|
fi
|
|
816
816
|
|
|
@@ -956,8 +956,8 @@ print(count)
|
|
|
956
956
|
if [[ "$auto_skipped_count" -gt 0 ]]; then
|
|
957
957
|
echo ""
|
|
958
958
|
log_warn "$auto_skipped_count feature(s) were auto-skipped due to failed dependencies."
|
|
959
|
-
log_warn "Run './run.sh status' to see details."
|
|
960
|
-
log_warn "Run './run.sh unskip' to reset and retry them."
|
|
959
|
+
log_warn "Run './run-feature.sh status' to see details."
|
|
960
|
+
log_warn "Run './run-feature.sh unskip' to reset and retry them."
|
|
961
961
|
fi
|
|
962
962
|
|
|
963
963
|
break
|
|
@@ -965,7 +965,7 @@ print(count)
|
|
|
965
965
|
|
|
966
966
|
if [[ "$next_feature" == "PIPELINE_BLOCKED" ]]; then
|
|
967
967
|
log_warn "All remaining features are blocked by dependencies or failed."
|
|
968
|
-
log_warn "Run './run.sh status' to see details."
|
|
968
|
+
log_warn "Run './run-feature.sh status' to see details."
|
|
969
969
|
log_warn "Waiting 60s before re-checking... (Ctrl+C to stop)"
|
|
970
970
|
sleep 60
|
|
971
971
|
continue
|
|
@@ -1027,12 +1027,12 @@ print(count)
|
|
|
1027
1027
|
--output "$bootstrap_prompt"
|
|
1028
1028
|
)
|
|
1029
1029
|
|
|
1030
|
-
# Support PIPELINE_MODE env var (set by launch-daemon.sh --mode)
|
|
1030
|
+
# Support PIPELINE_MODE env var (set by launch-feature-daemon.sh --mode)
|
|
1031
1031
|
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
1032
1032
|
main_prompt_args+=(--mode "$PIPELINE_MODE")
|
|
1033
1033
|
fi
|
|
1034
1034
|
|
|
1035
|
-
# Support ENABLE_CRITIC env var (set by launch-daemon.sh --critic)
|
|
1035
|
+
# Support ENABLE_CRITIC env var (set by launch-feature-daemon.sh --critic)
|
|
1036
1036
|
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
1037
1037
|
main_prompt_args+=(--critic "true")
|
|
1038
1038
|
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
@@ -1154,18 +1154,18 @@ show_help() {
|
|
|
1154
1154
|
echo " ENABLE_CRITIC Enable critic review for all features: true|false"
|
|
1155
1155
|
echo ""
|
|
1156
1156
|
echo "Examples:"
|
|
1157
|
-
echo " ./run.sh run # Run all features"
|
|
1158
|
-
echo " ./run.sh run --features F-001,F-003,F-005 # Run specific features"
|
|
1159
|
-
echo " ./run.sh run --features F-001:F-010 # Run features F-001 through F-010"
|
|
1160
|
-
echo " ./run.sh run F-007 --dry-run # Inspect generated prompt"
|
|
1161
|
-
echo " ./run.sh run F-007 --dry-run --mode lite # Test lite mode"
|
|
1162
|
-
echo " ./run.sh run F-007 --resume-phase 6 # Skip to implementation"
|
|
1163
|
-
echo " ./run.sh run F-007 --mode full --timeout 3600 # Full mode, 1h timeout"
|
|
1164
|
-
echo " ./run.sh run F-007 --clean --mode standard # Clean + run standard"
|
|
1165
|
-
echo " ./run.sh status # Show pipeline status"
|
|
1166
|
-
echo " MAX_RETRIES=5 SESSION_TIMEOUT=7200 ./run.sh run # Custom config"
|
|
1167
|
-
echo " MODEL=claude-sonnet-4.6 ./run.sh run # Use Sonnet model"
|
|
1168
|
-
echo " MODEL=claude-haiku-4.5 ./run.sh test-cli # Test with Haiku"
|
|
1157
|
+
echo " ./run-feature.sh run # Run all features"
|
|
1158
|
+
echo " ./run-feature.sh run --features F-001,F-003,F-005 # Run specific features"
|
|
1159
|
+
echo " ./run-feature.sh run --features F-001:F-010 # Run features F-001 through F-010"
|
|
1160
|
+
echo " ./run-feature.sh run F-007 --dry-run # Inspect generated prompt"
|
|
1161
|
+
echo " ./run-feature.sh run F-007 --dry-run --mode lite # Test lite mode"
|
|
1162
|
+
echo " ./run-feature.sh run F-007 --resume-phase 6 # Skip to implementation"
|
|
1163
|
+
echo " ./run-feature.sh run F-007 --mode full --timeout 3600 # Full mode, 1h timeout"
|
|
1164
|
+
echo " ./run-feature.sh run F-007 --clean --mode standard # Clean + run standard"
|
|
1165
|
+
echo " ./run-feature.sh status # Show pipeline status"
|
|
1166
|
+
echo " MAX_RETRIES=5 SESSION_TIMEOUT=7200 ./run-feature.sh run # Custom config"
|
|
1167
|
+
echo " MODEL=claude-sonnet-4.6 ./run-feature.sh run # Use Sonnet model"
|
|
1168
|
+
echo " MODEL=claude-haiku-4.5 ./run-feature.sh test-cli # Test with Haiku"
|
|
1169
1169
|
}
|
|
1170
1170
|
|
|
1171
1171
|
case "${1:-run}" in
|
|
@@ -1201,7 +1201,7 @@ case "${1:-run}" in
|
|
|
1201
1201
|
status)
|
|
1202
1202
|
check_dependencies
|
|
1203
1203
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1204
|
-
log_error "No pipeline state found. Run './run.sh run' first."
|
|
1204
|
+
log_error "No pipeline state found. Run './run-feature.sh run' first."
|
|
1205
1205
|
exit 1
|
|
1206
1206
|
fi
|
|
1207
1207
|
python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
@@ -1270,12 +1270,12 @@ case "${1:-run}" in
|
|
|
1270
1270
|
reset)
|
|
1271
1271
|
log_warn "Resetting pipeline state..."
|
|
1272
1272
|
rm -rf "$STATE_DIR"
|
|
1273
|
-
log_success "State cleared. Run './run.sh run' to start fresh."
|
|
1273
|
+
log_success "State cleared. Run './run-feature.sh run' to start fresh."
|
|
1274
1274
|
;;
|
|
1275
1275
|
unskip)
|
|
1276
1276
|
check_dependencies
|
|
1277
1277
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1278
|
-
log_error "No pipeline state found. Run './run.sh run' first."
|
|
1278
|
+
log_error "No pipeline state found. Run './run-feature.sh run' first."
|
|
1279
1279
|
exit 1
|
|
1280
1280
|
fi
|
|
1281
1281
|
_unskip_feature_list="feature-list.json"
|