prizmkit 1.1.9 → 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.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/README.md +10 -46
- package/bundled/dev-pipeline/reset-bug.sh +84 -10
- package/bundled/dev-pipeline/reset-feature.sh +86 -10
- package/bundled/dev-pipeline/reset-refactor.sh +68 -4
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +47 -46
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -12
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +124 -20
- package/bundled/dev-pipeline/scripts/utils.py +20 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +13 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +62 -66
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +37 -40
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +35 -48
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +135 -182
- package/bundled/dev-pipeline/templates/feature-list-schema.json +6 -21
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +9 -9
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
- package/bundled/dev-pipeline/templates/sections/feature-context.md +4 -0
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +41 -24
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +4 -12
- package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +9 -17
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +3 -2
- package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +0 -18
- package/bundled/dev-pipeline/templates/sections/session-context.md +1 -2
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +75 -0
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +66 -0
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +3 -8
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +4 -16
- package/bundled/skills/feature-planner/SKILL.md +9 -5
- package/bundled/skills/feature-planner/assets/planning-guide.md +16 -11
- package/bundled/skills/feature-planner/references/browser-interaction.md +9 -8
- package/bundled/skills/feature-planner/references/completeness-review.md +1 -1
- package/bundled/skills/feature-planner/references/error-recovery.md +1 -1
- package/bundled/skills/feature-planner/references/incremental-feature-planning.md +1 -1
- package/bundled/skills/feature-planner/scripts/validate-and-generate.py +10 -7
- package/bundled/skills/recovery-workflow/SKILL.md +3 -3
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +4 -15
- package/package.json +1 -1
- package/bundled/dev-pipeline/retry-bugfix.sh +0 -429
- package/bundled/dev-pipeline/retry-feature.sh +0 -445
- package/bundled/dev-pipeline/retry-refactor.sh +0 -441
- package/bundled/dev-pipeline/templates/sections/failure-log-check.md +0 -9
- package/bundled/dev-pipeline/templates/sections/resume-header.md +0 -5
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery.md +0 -75
|
@@ -227,7 +227,7 @@ Detect user intent from their message, then follow the corresponding workflow:
|
|
|
227
227
|
**If foreground**: Pipeline runs to completion in the terminal. After it finishes:
|
|
228
228
|
- Summarize results: total refactors, succeeded, failed, skipped
|
|
229
229
|
- If all succeeded: each refactor session has already run `prizmkit-retrospective` internally. Ask user what's next.
|
|
230
|
-
- If some failed: show failed refactor IDs and suggest `
|
|
230
|
+
- If some failed: show failed refactor IDs and suggest `reset-refactor.sh <R-XXX> --clean --run` for a fresh retry
|
|
231
231
|
|
|
232
232
|
**If background daemon**:
|
|
233
233
|
1. Verify launch:
|
|
@@ -315,25 +315,14 @@ Detect user intent from their message, then follow the corresponding workflow:
|
|
|
315
315
|
|
|
316
316
|
#### Intent E: Retry Single Refactor
|
|
317
317
|
|
|
318
|
-
When user says "retry R-001":
|
|
319
|
-
|
|
320
|
-
```bash
|
|
321
|
-
dev-pipeline/retry-refactor.sh R-001 .prizmkit/plans/refactor-list.json
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
When user says "clean retry R-001" or "retry R-001 from scratch":
|
|
318
|
+
When user says "retry R-001" or "clean retry R-001":
|
|
325
319
|
|
|
326
320
|
```bash
|
|
327
321
|
dev-pipeline/reset-refactor.sh R-001 --clean --run .prizmkit/plans/refactor-list.json
|
|
328
322
|
```
|
|
329
323
|
|
|
330
|
-
Environment variables (optional):
|
|
331
|
-
```bash
|
|
332
|
-
SESSION_TIMEOUT=3600 STRICT_BEHAVIOR_CHECK=1 dev-pipeline/retry-refactor.sh R-001 .prizmkit/plans/refactor-list.json
|
|
333
|
-
```
|
|
334
|
-
|
|
335
324
|
Notes:
|
|
336
|
-
- `
|
|
325
|
+
- `reset-refactor.sh --clean --run` performs a full clean (deletes session history and artifacts) before retrying — this gives a fresh start.
|
|
337
326
|
- Keep pipeline daemon mode for main run management (`launch-refactor-daemon.sh`).
|
|
338
327
|
|
|
339
328
|
---
|
|
@@ -350,7 +339,7 @@ Notes:
|
|
|
350
339
|
| Refactor pipeline already running | Show status, ask if user wants to stop and restart |
|
|
351
340
|
| PID file stale (process dead) | `launch-refactor-daemon.sh` auto-cleans, retry start |
|
|
352
341
|
| Launch failed (process died immediately) | Show last 20 lines of log: `tail -20 .prizmkit/state/refactor/pipeline-daemon.log` |
|
|
353
|
-
| Refactor stuck/blocked | Use `
|
|
342
|
+
| Refactor stuck/blocked | Use `reset-refactor.sh <R-XXX> --clean --run` for a fresh retry |
|
|
354
343
|
| All refactors blocked/failed | Show status, suggest recovery: `dev-pipeline/reset-refactor.sh <R-XXX> --clean --run .prizmkit/plans/refactor-list.json` |
|
|
355
344
|
| Permission denied on script | Run `chmod +x dev-pipeline/launch-refactor-daemon.sh dev-pipeline/run-refactor.sh` |
|
|
356
345
|
|
package/package.json
CHANGED
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# ============================================================
|
|
5
|
-
# dev-pipeline/retry-bugfix.sh - Retry a single failed bug fix
|
|
6
|
-
#
|
|
7
|
-
# Runs exactly ONE AI CLI session for the specified bug, then exits.
|
|
8
|
-
# Use this to manually retry a failed bug without restarting
|
|
9
|
-
# the full bugfix pipeline.
|
|
10
|
-
#
|
|
11
|
-
# Usage:
|
|
12
|
-
# ./retry-bugfix.sh <bug-id> [.prizmkit/plans/bug-fix-list.json]
|
|
13
|
-
#
|
|
14
|
-
# Examples:
|
|
15
|
-
# ./retry-bugfix.sh B-001
|
|
16
|
-
# ./retry-bugfix.sh B-001 .prizmkit/plans/bug-fix-list.json
|
|
17
|
-
# SESSION_TIMEOUT=3600 ./retry-bugfix.sh B-001
|
|
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/bugfix"
|
|
23
|
-
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
24
|
-
|
|
25
|
-
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
26
|
-
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
27
|
-
AUTO_PUSH=${AUTO_PUSH:-0}
|
|
28
|
-
DEV_BRANCH=${DEV_BRANCH:-""}
|
|
29
|
-
|
|
30
|
-
# Source shared libraries (CLI/platform detection + logs + deps)
|
|
31
|
-
source "$SCRIPT_DIR/lib/common.sh"
|
|
32
|
-
prizm_detect_cli_and_platform
|
|
33
|
-
|
|
34
|
-
# Source shared heartbeat library
|
|
35
|
-
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
36
|
-
|
|
37
|
-
# Source shared branch library
|
|
38
|
-
source "$SCRIPT_DIR/lib/branch.sh"
|
|
39
|
-
|
|
40
|
-
# Detect stream-json support
|
|
41
|
-
detect_stream_json_support "$CLI_CMD"
|
|
42
|
-
|
|
43
|
-
# ============================================================
|
|
44
|
-
# Args
|
|
45
|
-
# ============================================================
|
|
46
|
-
|
|
47
|
-
if [[ $# -lt 1 ]]; then
|
|
48
|
-
echo "Usage: $0 <bug-id> [.prizmkit/plans/bug-fix-list.json]"
|
|
49
|
-
echo ""
|
|
50
|
-
echo " bug-id Bug to retry (e.g. B-001)"
|
|
51
|
-
echo " bug-fix-list.json Path to bug fix list (default: .prizmkit/plans/bug-fix-list.json)"
|
|
52
|
-
echo ""
|
|
53
|
-
echo "Environment Variables:"
|
|
54
|
-
echo " SESSION_TIMEOUT Timeout in seconds (default: 0 = no limit)"
|
|
55
|
-
echo " HEARTBEAT_INTERVAL Heartbeat interval in seconds (default: 30)"
|
|
56
|
-
echo " AI_CLI AI CLI command (auto-detected: cbc or claude)"
|
|
57
|
-
echo " AUTO_PUSH Auto-push to remote after fix (default: 0)"
|
|
58
|
-
echo " DEV_BRANCH Custom dev branch name (default: auto-generated)"
|
|
59
|
-
exit 1
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
BUG_ID="$1"
|
|
63
|
-
BUG_LIST="${2:-.prizmkit/plans/bug-fix-list.json}"
|
|
64
|
-
|
|
65
|
-
if [[ ! "$BUG_LIST" = /* ]]; then
|
|
66
|
-
BUG_LIST="$(pwd)/$BUG_LIST"
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
# ============================================================
|
|
70
|
-
# Validation
|
|
71
|
-
# ============================================================
|
|
72
|
-
|
|
73
|
-
if [[ ! -f "$BUG_LIST" ]]; then
|
|
74
|
-
log_error "Bug fix list not found: $BUG_LIST"
|
|
75
|
-
exit 1
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
if ! command -v jq &>/dev/null; then
|
|
79
|
-
log_error "jq is required. Install with: brew install jq"
|
|
80
|
-
exit 1
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Initialize state if needed
|
|
84
|
-
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
85
|
-
log_info "Initializing bugfix pipeline state..."
|
|
86
|
-
python3 "$SCRIPTS_DIR/init-bugfix-pipeline.py" \
|
|
87
|
-
--bug-list "$BUG_LIST" \
|
|
88
|
-
--state-dir "$STATE_DIR" >/dev/null 2>&1 || {
|
|
89
|
-
log_error "Failed to initialize bugfix pipeline state"
|
|
90
|
-
exit 1
|
|
91
|
-
}
|
|
92
|
-
fi
|
|
93
|
-
|
|
94
|
-
# Verify bug exists
|
|
95
|
-
BUG_TITLE=$(python3 -c "
|
|
96
|
-
import json, sys
|
|
97
|
-
with open('$BUG_LIST') as f:
|
|
98
|
-
data = json.load(f)
|
|
99
|
-
for bug in data.get('bugs', []):
|
|
100
|
-
if bug.get('id') == '$BUG_ID':
|
|
101
|
-
print(bug.get('title', ''))
|
|
102
|
-
sys.exit(0)
|
|
103
|
-
sys.exit(1)
|
|
104
|
-
" 2>/dev/null) || {
|
|
105
|
-
log_error "Bug $BUG_ID not found in $BUG_LIST"
|
|
106
|
-
exit 1
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
BUG_SEVERITY=$(python3 -c "
|
|
110
|
-
import json, sys
|
|
111
|
-
with open('$BUG_LIST') as f:
|
|
112
|
-
data = json.load(f)
|
|
113
|
-
for bug in data.get('bugs', []):
|
|
114
|
-
if bug.get('id') == '$BUG_ID':
|
|
115
|
-
print(bug.get('severity', 'medium'))
|
|
116
|
-
sys.exit(0)
|
|
117
|
-
sys.exit(1)
|
|
118
|
-
" 2>/dev/null) || BUG_SEVERITY="medium"
|
|
119
|
-
|
|
120
|
-
# ============================================================
|
|
121
|
-
# Clean bug artifacts + reset status for a full restart
|
|
122
|
-
# ============================================================
|
|
123
|
-
|
|
124
|
-
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
125
|
-
ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
126
|
-
|
|
127
|
-
# Branch tracking (for cleanup on interrupt)
|
|
128
|
-
_DEV_BRANCH_NAME=""
|
|
129
|
-
|
|
130
|
-
log_info "Reading retry state for $BUG_ID..."
|
|
131
|
-
RETRY_COUNT=$(python3 -c "
|
|
132
|
-
import json, os
|
|
133
|
-
status_path = os.path.join('$STATE_DIR', 'bugs', '$BUG_ID', 'status.json')
|
|
134
|
-
if os.path.isfile(status_path):
|
|
135
|
-
with open(status_path) as f:
|
|
136
|
-
d = json.load(f)
|
|
137
|
-
print(d.get('retry_count', 0))
|
|
138
|
-
else:
|
|
139
|
-
print(0)
|
|
140
|
-
" 2>/dev/null || echo "0")
|
|
141
|
-
RESUME_PHASE=$(python3 -c "
|
|
142
|
-
import json, os
|
|
143
|
-
status_path = os.path.join('$STATE_DIR', 'bugs', '$BUG_ID', 'status.json')
|
|
144
|
-
if os.path.isfile(status_path):
|
|
145
|
-
with open(status_path) as f:
|
|
146
|
-
d = json.load(f)
|
|
147
|
-
print(d.get('resume_from_phase') or 'null')
|
|
148
|
-
else:
|
|
149
|
-
print('null')
|
|
150
|
-
" 2>/dev/null || echo "null")
|
|
151
|
-
log_info "Retry count: $RETRY_COUNT, Resume phase: $RESUME_PHASE"
|
|
152
|
-
|
|
153
|
-
# ============================================================
|
|
154
|
-
# Generate bootstrap prompt
|
|
155
|
-
# ============================================================
|
|
156
|
-
|
|
157
|
-
RUN_ID=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
158
|
-
SESSION_ID="${BUG_ID}-$(date +%Y%m%d%H%M%S)"
|
|
159
|
-
SESSION_DIR="$STATE_DIR/bugs/$BUG_ID/sessions/$SESSION_ID"
|
|
160
|
-
mkdir -p "$SESSION_DIR/logs"
|
|
161
|
-
|
|
162
|
-
BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
|
|
163
|
-
|
|
164
|
-
log_info "Generating bugfix bootstrap prompt..."
|
|
165
|
-
GEN_ARGS=(
|
|
166
|
-
--bug-list "$BUG_LIST"
|
|
167
|
-
--bug-id "$BUG_ID"
|
|
168
|
-
--session-id "$SESSION_ID"
|
|
169
|
-
--run-id "$RUN_ID"
|
|
170
|
-
--retry-count "$RETRY_COUNT"
|
|
171
|
-
--resume-phase "$RESUME_PHASE"
|
|
172
|
-
--state-dir "$STATE_DIR"
|
|
173
|
-
--output "$BOOTSTRAP_PROMPT"
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
# Support PIPELINE_MODE env var
|
|
177
|
-
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
178
|
-
GEN_ARGS+=(--mode "$PIPELINE_MODE")
|
|
179
|
-
fi
|
|
180
|
-
|
|
181
|
-
# Support ENABLE_CRITIC env var
|
|
182
|
-
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
183
|
-
GEN_ARGS+=(--critic "true")
|
|
184
|
-
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
185
|
-
GEN_ARGS+=(--critic "false")
|
|
186
|
-
fi
|
|
187
|
-
|
|
188
|
-
GEN_OUTPUT=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${GEN_ARGS[@]}" 2>/dev/null) || {
|
|
189
|
-
log_error "Failed to generate bootstrap prompt"
|
|
190
|
-
exit 1
|
|
191
|
-
}
|
|
192
|
-
BUG_MODEL=$(echo "$GEN_OUTPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
193
|
-
|
|
194
|
-
# ============================================================
|
|
195
|
-
# Run single AI CLI session
|
|
196
|
-
# ============================================================
|
|
197
|
-
|
|
198
|
-
# Branch lifecycle: create and checkout bugfix branch
|
|
199
|
-
_branch_name="${DEV_BRANCH:-bugfix/${BUG_ID}-$(date +%s)}"
|
|
200
|
-
if branch_create "$PROJECT_ROOT" "$_branch_name" "$ORIGINAL_BRANCH"; then
|
|
201
|
-
_DEV_BRANCH_NAME="$_branch_name"
|
|
202
|
-
log_info "Dev branch: $_branch_name"
|
|
203
|
-
else
|
|
204
|
-
log_warn "Failed to create branch; running session on current branch"
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
echo ""
|
|
208
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
209
|
-
echo -e "${BOLD} Retry Bug Fix: $BUG_ID — $BUG_TITLE${NC}"
|
|
210
|
-
echo -e "${BOLD} Severity: $BUG_SEVERITY${NC}"
|
|
211
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
212
|
-
log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
213
|
-
EFFECTIVE_MODEL="${BUG_MODEL:-${MODEL:-}}"
|
|
214
|
-
if [[ -n "$EFFECTIVE_MODEL" ]]; then
|
|
215
|
-
log_info "Model: $EFFECTIVE_MODEL"
|
|
216
|
-
else
|
|
217
|
-
log_info "Model: (CLI default)"
|
|
218
|
-
fi
|
|
219
|
-
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
220
|
-
log_info "Session timeout: ${SESSION_TIMEOUT}s"
|
|
221
|
-
else
|
|
222
|
-
log_info "Session timeout: none"
|
|
223
|
-
fi
|
|
224
|
-
log_info "Prompt: $BOOTSTRAP_PROMPT"
|
|
225
|
-
log_info "Log: $SESSION_DIR/logs/session.log"
|
|
226
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
227
|
-
echo ""
|
|
228
|
-
|
|
229
|
-
SESSION_LOG="$SESSION_DIR/logs/session.log"
|
|
230
|
-
PROGRESS_JSON="$SESSION_DIR/logs/progress.json"
|
|
231
|
-
|
|
232
|
-
# Build stream-json flag
|
|
233
|
-
STREAM_JSON_FLAG=""
|
|
234
|
-
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
235
|
-
STREAM_JSON_FLAG="--output-format stream-json"
|
|
236
|
-
fi
|
|
237
|
-
|
|
238
|
-
# claude-internal requires --verbose when using stream-json with -p/--print
|
|
239
|
-
VERBOSE_FLAG=""
|
|
240
|
-
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
241
|
-
VERBOSE_FLAG="--verbose"
|
|
242
|
-
fi
|
|
243
|
-
|
|
244
|
-
# Spawn AI CLI session — model priority: bug.model > $MODEL env > none
|
|
245
|
-
EFFECTIVE_MODEL="${BUG_MODEL:-${MODEL:-}}"
|
|
246
|
-
MODEL_FLAG=""
|
|
247
|
-
if [[ -n "$EFFECTIVE_MODEL" ]]; then
|
|
248
|
-
MODEL_FLAG="--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" "$BUG_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
|
-
CLI_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
|
|
285
|
-
WATCHER_PID=""
|
|
286
|
-
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
287
|
-
( sleep "$SESSION_TIMEOUT" && kill -TERM "$CLI_PID" 2>/dev/null ) &
|
|
288
|
-
WATCHER_PID=$!
|
|
289
|
-
fi
|
|
290
|
-
|
|
291
|
-
# Heartbeat
|
|
292
|
-
start_heartbeat "$CLI_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 "$CLI_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 "$CLI_PID" 2>/dev/null || true
|
|
304
|
-
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
305
|
-
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
306
|
-
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
307
|
-
log_info "Original branch was: $ORIGINAL_BRANCH"
|
|
308
|
-
fi
|
|
309
|
-
log_info "Session log: $SESSION_LOG"
|
|
310
|
-
exit 130
|
|
311
|
-
}
|
|
312
|
-
trap cleanup SIGINT SIGTERM
|
|
313
|
-
|
|
314
|
-
# Wait
|
|
315
|
-
EXIT_CODE=0
|
|
316
|
-
if wait "$CLI_PID" 2>/dev/null; then
|
|
317
|
-
EXIT_CODE=0
|
|
318
|
-
else
|
|
319
|
-
EXIT_CODE=$?
|
|
320
|
-
fi
|
|
321
|
-
|
|
322
|
-
# Cleanup background processes
|
|
323
|
-
[[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
|
|
324
|
-
stop_heartbeat "$HEARTBEAT_PID"
|
|
325
|
-
stop_progress_parser "$PARSER_PID"
|
|
326
|
-
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
327
|
-
|
|
328
|
-
[[ $EXIT_CODE -eq 143 ]] && EXIT_CODE=124
|
|
329
|
-
|
|
330
|
-
# ============================================================
|
|
331
|
-
# Check result
|
|
332
|
-
# ============================================================
|
|
333
|
-
|
|
334
|
-
echo ""
|
|
335
|
-
if [[ -f "$SESSION_LOG" ]]; then
|
|
336
|
-
FINAL_LINES=$(wc -l < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
337
|
-
FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
338
|
-
log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
|
|
339
|
-
fi
|
|
340
|
-
log_info "exit_code=$EXIT_CODE"
|
|
341
|
-
|
|
342
|
-
# ── Determine session outcome from observable signals ──────────────
|
|
343
|
-
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
344
|
-
DEFAULT_BRANCH="$ORIGINAL_BRANCH"
|
|
345
|
-
|
|
346
|
-
if [[ $EXIT_CODE -eq 124 ]]; then
|
|
347
|
-
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
348
|
-
SESSION_STATUS="timed_out"
|
|
349
|
-
elif [[ $EXIT_CODE -ne 0 ]]; then
|
|
350
|
-
log_warn "Session exited with code $EXIT_CODE"
|
|
351
|
-
SESSION_STATUS="crashed"
|
|
352
|
-
else
|
|
353
|
-
# Exit code 0 — check if the session produced commits
|
|
354
|
-
HAS_COMMITS=""
|
|
355
|
-
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
356
|
-
HAS_COMMITS=$(git -C "$PROJECT_ROOT" log "${DEFAULT_BRANCH}..HEAD" --oneline 2>/dev/null | head -1)
|
|
357
|
-
fi
|
|
358
|
-
|
|
359
|
-
if [[ -n "$HAS_COMMITS" ]]; then
|
|
360
|
-
SESSION_STATUS="success"
|
|
361
|
-
else
|
|
362
|
-
UNCOMMITTED=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null | head -1 || true)
|
|
363
|
-
if [[ -n "$UNCOMMITTED" ]]; then
|
|
364
|
-
log_warn "Session exited cleanly but produced no commits (uncommitted changes found) — auto-committing..."
|
|
365
|
-
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
366
|
-
if git -C "$PROJECT_ROOT" commit --no-verify -m "chore($BUG_ID): auto-commit session work" 2>/dev/null; then
|
|
367
|
-
log_info "Auto-commit succeeded"
|
|
368
|
-
SESSION_STATUS="success"
|
|
369
|
-
else
|
|
370
|
-
log_warn "Auto-commit failed — no changes to commit"
|
|
371
|
-
SESSION_STATUS="crashed"
|
|
372
|
-
fi
|
|
373
|
-
else
|
|
374
|
-
log_warn "Session exited cleanly but produced no commits and no changes"
|
|
375
|
-
SESSION_STATUS="crashed"
|
|
376
|
-
fi
|
|
377
|
-
fi
|
|
378
|
-
fi
|
|
379
|
-
|
|
380
|
-
# ── Post-success validation ──────────────────────────────────────────
|
|
381
|
-
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
382
|
-
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
383
|
-
DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
|
|
384
|
-
if [[ -n "$DIRTY_FILES" ]]; then
|
|
385
|
-
log_info "Auto-committing remaining session artifacts..."
|
|
386
|
-
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
387
|
-
git -C "$PROJECT_ROOT" commit --no-verify --amend --no-edit -a 2>/dev/null \
|
|
388
|
-
|| git -C "$PROJECT_ROOT" commit --no-verify -m "chore($BUG_ID): include remaining session artifacts" 2>/dev/null \
|
|
389
|
-
|| true
|
|
390
|
-
fi
|
|
391
|
-
fi
|
|
392
|
-
fi
|
|
393
|
-
|
|
394
|
-
# ── Merge dev branch back to original on success ────────────────────
|
|
395
|
-
if [[ "$SESSION_STATUS" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
396
|
-
if branch_merge "$PROJECT_ROOT" "$_DEV_BRANCH_NAME" "$ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
397
|
-
_DEV_BRANCH_NAME=""
|
|
398
|
-
else
|
|
399
|
-
log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
|
|
400
|
-
fi
|
|
401
|
-
fi
|
|
402
|
-
|
|
403
|
-
# Update bug status
|
|
404
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
405
|
-
--bug-list "$BUG_LIST" \
|
|
406
|
-
--state-dir "$STATE_DIR" \
|
|
407
|
-
--bug-id "$BUG_ID" \
|
|
408
|
-
--session-status "$SESSION_STATUS" \
|
|
409
|
-
--session-id "$SESSION_ID" \
|
|
410
|
-
--max-retries 999 \
|
|
411
|
-
--action update >/dev/null 2>&1 || true
|
|
412
|
-
|
|
413
|
-
# Commit bug-fix-list.json status update (pipeline management commit)
|
|
414
|
-
if ! git -C "$PROJECT_ROOT" diff --quiet "$BUG_LIST" 2>/dev/null; then
|
|
415
|
-
git -C "$PROJECT_ROOT" add "$BUG_LIST"
|
|
416
|
-
git -C "$PROJECT_ROOT" commit --no-verify -m "chore($BUG_ID): update bug status" 2>/dev/null || true
|
|
417
|
-
fi
|
|
418
|
-
|
|
419
|
-
echo ""
|
|
420
|
-
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
421
|
-
log_success "════════════════════════════════════════════════════"
|
|
422
|
-
log_success " $BUG_ID fixed successfully!"
|
|
423
|
-
log_success "════════════════════════════════════════════════════"
|
|
424
|
-
else
|
|
425
|
-
log_error "════════════════════════════════════════════════════"
|
|
426
|
-
log_error " $BUG_ID result: $SESSION_STATUS"
|
|
427
|
-
log_error " Review log: $SESSION_LOG"
|
|
428
|
-
log_error "════════════════════════════════════════════════════"
|
|
429
|
-
fi
|