prizmkit 1.1.23 → 1.1.24
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/lib/heartbeat.sh +50 -7
- package/bundled/dev-pipeline/run-bugfix.sh +40 -2
- package/bundled/dev-pipeline/run-feature.sh +41 -1
- package/bundled/dev-pipeline/run-refactor.sh +40 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +50 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +50 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +50 -7
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +20 -0
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +84 -5
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +7 -0
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -0
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +7 -0
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
package/bundled/VERSION.json
CHANGED
|
@@ -6,9 +6,14 @@
|
|
|
6
6
|
# structured progress from progress.json (written by
|
|
7
7
|
# parse-stream-progress.py) and fall back to tail-based monitoring.
|
|
8
8
|
#
|
|
9
|
+
# When stale_kill_threshold is set (>0), the heartbeat monitor will
|
|
10
|
+
# automatically kill the AI CLI process if it shows no progress for
|
|
11
|
+
# the specified duration. This prevents sessions from hanging forever
|
|
12
|
+
# when the AI CLI process doesn't exit after completing its work.
|
|
13
|
+
#
|
|
9
14
|
# Usage:
|
|
10
15
|
# source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
11
|
-
# start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$interval"
|
|
16
|
+
# start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$interval" ["$stale_kill_threshold"]
|
|
12
17
|
# # ... wait for CLI to finish ...
|
|
13
18
|
# stop_heartbeat "$_HEARTBEAT_PID"
|
|
14
19
|
#
|
|
@@ -20,19 +25,23 @@
|
|
|
20
25
|
# Sets _HEARTBEAT_PID to the background process PID.
|
|
21
26
|
#
|
|
22
27
|
# Arguments:
|
|
23
|
-
# $1 - cli_pid
|
|
24
|
-
# $2 - session_log
|
|
25
|
-
# $3 - progress_json
|
|
26
|
-
# $4 - interval
|
|
28
|
+
# $1 - cli_pid PID of the AI CLI process to monitor
|
|
29
|
+
# $2 - session_log Path to session.log
|
|
30
|
+
# $3 - progress_json Path to progress.json (may not exist if stream-json disabled)
|
|
31
|
+
# $4 - interval Heartbeat interval in seconds
|
|
32
|
+
# $5 - stale_kill_threshold (optional) Seconds of no progress before auto-killing the process.
|
|
33
|
+
# 0 = disabled (default). Recommended: 900 (15 minutes).
|
|
27
34
|
start_heartbeat() {
|
|
28
35
|
local cli_pid="$1"
|
|
29
36
|
local session_log="$2"
|
|
30
37
|
local progress_json="$3"
|
|
31
38
|
local heartbeat_interval="$4"
|
|
39
|
+
local stale_kill_threshold="${5:-0}"
|
|
32
40
|
|
|
33
41
|
(
|
|
34
42
|
local elapsed=0
|
|
35
43
|
local prev_size=0
|
|
44
|
+
local stale_seconds=0
|
|
36
45
|
while kill -0 "$cli_pid" 2>/dev/null; do
|
|
37
46
|
sleep "$heartbeat_interval"
|
|
38
47
|
elapsed=$((elapsed + heartbeat_interval))
|
|
@@ -48,6 +57,13 @@ start_heartbeat() {
|
|
|
48
57
|
local growth=$((cur_size - prev_size))
|
|
49
58
|
prev_size=$cur_size
|
|
50
59
|
|
|
60
|
+
# Track progress staleness (no log growth = stale)
|
|
61
|
+
if [[ $growth -eq 0 ]]; then
|
|
62
|
+
stale_seconds=$((stale_seconds + heartbeat_interval))
|
|
63
|
+
else
|
|
64
|
+
stale_seconds=0
|
|
65
|
+
fi
|
|
66
|
+
|
|
51
67
|
local size_display
|
|
52
68
|
if [[ $cur_size -gt 1048576 ]]; then
|
|
53
69
|
size_display="$((cur_size / 1048576))MB"
|
|
@@ -67,6 +83,33 @@ start_heartbeat() {
|
|
|
67
83
|
status_icon="${YELLOW}⏸${NC}"
|
|
68
84
|
fi
|
|
69
85
|
|
|
86
|
+
# Stale-kill: auto-terminate process if no progress for too long
|
|
87
|
+
if [[ $stale_kill_threshold -gt 0 && $stale_seconds -ge $stale_kill_threshold ]]; then
|
|
88
|
+
local stale_mins=$((stale_seconds / 60))
|
|
89
|
+
echo -e " ${RED}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${RED}STALE-KILL: no progress for ${stale_mins}m (threshold: ${stale_kill_threshold}s)${NC}"
|
|
90
|
+
echo -e " ${RED}[HEARTBEAT]${NC} Killing AI CLI process $cli_pid (stale session)..."
|
|
91
|
+
kill -TERM "$cli_pid" 2>/dev/null || true
|
|
92
|
+
# Give process 10s to exit gracefully, then force kill
|
|
93
|
+
sleep 10
|
|
94
|
+
if kill -0 "$cli_pid" 2>/dev/null; then
|
|
95
|
+
echo -e " ${RED}[HEARTBEAT]${NC} Process still alive after SIGTERM, sending SIGKILL..."
|
|
96
|
+
kill -9 "$cli_pid" 2>/dev/null || true
|
|
97
|
+
fi
|
|
98
|
+
# Write stale-kill marker so spawn_and_wait_session knows this wasn't a crash
|
|
99
|
+
local _marker_dir
|
|
100
|
+
_marker_dir="$(dirname "$session_log")"
|
|
101
|
+
echo "{\"killed_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\", \"reason\": \"stale_session\", \"stale_seconds\": $stale_seconds, \"threshold\": $stale_kill_threshold}" > "$_marker_dir/stale-kill.json" 2>/dev/null || true
|
|
102
|
+
break
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# Build staleness hint for display
|
|
106
|
+
local stale_hint=""
|
|
107
|
+
if [[ $stale_kill_threshold -gt 0 && $stale_seconds -gt 0 ]]; then
|
|
108
|
+
local stale_mins=$((stale_seconds / 60))
|
|
109
|
+
local threshold_mins=$((stale_kill_threshold / 60))
|
|
110
|
+
stale_hint=" | stale: ${stale_mins}m/${threshold_mins}m"
|
|
111
|
+
fi
|
|
112
|
+
|
|
70
113
|
# Try structured progress from progress.json
|
|
71
114
|
if [[ -f "$progress_json" ]]; then
|
|
72
115
|
local phase tool msgs tools_total
|
|
@@ -86,7 +129,7 @@ try:
|
|
|
86
129
|
except Exception:
|
|
87
130
|
sys.exit(1)
|
|
88
131
|
" "$progress_json" 2>/dev/null) && {
|
|
89
|
-
echo -e " ${status_icon} ${BLUE}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${phase}"
|
|
132
|
+
echo -e " ${status_icon} ${BLUE}[HEARTBEAT]${NC} ${mins}m${secs}s | log: ${size_display} | ${phase}${stale_hint}"
|
|
90
133
|
continue
|
|
91
134
|
}
|
|
92
135
|
fi
|
|
@@ -97,7 +140,7 @@ except Exception:
|
|
|
97
140
|
last_activity=$(tail -20 "$session_log" 2>/dev/null | grep -v '^$' | tail -1 | cut -c1-80 || echo "")
|
|
98
141
|
fi
|
|
99
142
|
|
|
100
|
-
echo -e " ${status_icon} ${BLUE}[HEARTBEAT]${NC} ${mins}m${secs}s elapsed | log: ${size_display} (+${growth}B) | ${last_activity}"
|
|
143
|
+
echo -e " ${status_icon} ${BLUE}[HEARTBEAT]${NC} ${mins}m${secs}s elapsed | log: ${size_display} (+${growth}B) | ${last_activity}${stale_hint}"
|
|
101
144
|
done
|
|
102
145
|
) &
|
|
103
146
|
_HEARTBEAT_PID=$!
|
|
@@ -21,6 +21,7 @@ set -euo pipefail
|
|
|
21
21
|
# PRIZMKIT_PLATFORM Force platform: 'codebuddy' or 'claude' (auto-detected)
|
|
22
22
|
# VERBOSE Set to 1 to enable --verbose on AI CLI
|
|
23
23
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
24
|
+
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
24
25
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
25
26
|
# LOG_CLEANUP_ENABLED Run periodic log cleanup (default: 1)
|
|
26
27
|
# LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
|
|
@@ -39,6 +40,7 @@ MAX_RETRIES=${MAX_RETRIES:-3}
|
|
|
39
40
|
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
40
41
|
HEARTBEAT_STALE_THRESHOLD=${HEARTBEAT_STALE_THRESHOLD:-600}
|
|
41
42
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
43
|
+
STALE_KILL_THRESHOLD=${STALE_KILL_THRESHOLD:-900}
|
|
42
44
|
LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
|
|
43
45
|
LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
|
|
44
46
|
LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
|
|
@@ -146,8 +148,8 @@ spawn_and_wait_session() {
|
|
|
146
148
|
watcher_pid=$!
|
|
147
149
|
fi
|
|
148
150
|
|
|
149
|
-
# Heartbeat monitor
|
|
150
|
-
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL"
|
|
151
|
+
# Heartbeat monitor (with stale-kill protection)
|
|
152
|
+
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL" "$STALE_KILL_THRESHOLD"
|
|
151
153
|
local heartbeat_pid="${_HEARTBEAT_PID:-}"
|
|
152
154
|
|
|
153
155
|
# Wait for AI CLI to finish
|
|
@@ -166,6 +168,14 @@ spawn_and_wait_session() {
|
|
|
166
168
|
|
|
167
169
|
[[ $exit_code -eq 143 ]] && exit_code=124
|
|
168
170
|
|
|
171
|
+
# Check for stale-kill marker (heartbeat killed the process due to no progress)
|
|
172
|
+
local stale_kill_marker="$session_dir/logs/stale-kill.json"
|
|
173
|
+
local was_stale_killed=false
|
|
174
|
+
if [[ -f "$stale_kill_marker" ]]; then
|
|
175
|
+
was_stale_killed=true
|
|
176
|
+
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
177
|
+
fi
|
|
178
|
+
|
|
169
179
|
# Session summary
|
|
170
180
|
if [[ -f "$session_log" ]]; then
|
|
171
181
|
local final_size=$(wc -c < "$session_log" 2>/dev/null | tr -d ' ')
|
|
@@ -183,6 +193,33 @@ spawn_and_wait_session() {
|
|
|
183
193
|
if [[ $exit_code -eq 124 ]]; then
|
|
184
194
|
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
185
195
|
session_status="timed_out"
|
|
196
|
+
elif [[ "$was_stale_killed" == true ]]; then
|
|
197
|
+
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
198
|
+
local has_commits=""
|
|
199
|
+
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
200
|
+
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
201
|
+
fi
|
|
202
|
+
if [[ -n "$has_commits" ]]; then
|
|
203
|
+
log_info "Stale-killed session has commits — treating as success"
|
|
204
|
+
session_status="success"
|
|
205
|
+
else
|
|
206
|
+
local uncommitted=""
|
|
207
|
+
uncommitted=$(git -C "$project_root" status --porcelain 2>/dev/null | head -1 || true)
|
|
208
|
+
if [[ -n "$uncommitted" ]]; then
|
|
209
|
+
log_warn "Stale-killed session has uncommitted changes — auto-committing..."
|
|
210
|
+
git -C "$project_root" add -A 2>/dev/null || true
|
|
211
|
+
if git -C "$project_root" commit --no-verify -m "chore($bug_id): auto-commit session work (stale-killed)" 2>/dev/null; then
|
|
212
|
+
log_info "Auto-commit succeeded"
|
|
213
|
+
session_status="success"
|
|
214
|
+
else
|
|
215
|
+
log_warn "Auto-commit failed — no changes to commit"
|
|
216
|
+
session_status="crashed"
|
|
217
|
+
fi
|
|
218
|
+
else
|
|
219
|
+
log_warn "Stale-killed session produced no commits and no changes"
|
|
220
|
+
session_status="crashed"
|
|
221
|
+
fi
|
|
222
|
+
fi
|
|
186
223
|
elif [[ $exit_code -ne 0 ]]; then
|
|
187
224
|
log_warn "Session exited with code $exit_code"
|
|
188
225
|
session_status="crashed"
|
|
@@ -1091,6 +1128,7 @@ show_help() {
|
|
|
1091
1128
|
echo " AI_CLI AI CLI command name (auto-detected: cbc or claude)"
|
|
1092
1129
|
echo " VERBOSE Set to 1 for verbose AI CLI output"
|
|
1093
1130
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1131
|
+
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1094
1132
|
echo " LOG_CLEANUP_ENABLED Run log cleanup before execution (default: 1)"
|
|
1095
1133
|
echo " LOG_RETENTION_DAYS Delete logs older than N days (default: 14)"
|
|
1096
1134
|
echo " LOG_MAX_TOTAL_MB Keep total logs under N MB (default: 1024)"
|
|
@@ -23,6 +23,7 @@ set -euo pipefail
|
|
|
23
23
|
# MODEL AI model to use (e.g. claude-opus-4.6, claude-sonnet-4.6, claude-haiku-4.5)
|
|
24
24
|
# VERBOSE Set to 1 to enable --verbose on AI CLI (shows subagent output)
|
|
25
25
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
26
|
+
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
26
27
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
27
28
|
# LOG_CLEANUP_ENABLED Run periodic log cleanup (default: 1)
|
|
28
29
|
# LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
|
|
@@ -42,6 +43,7 @@ MAX_RETRIES=${MAX_RETRIES:-3}
|
|
|
42
43
|
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
43
44
|
HEARTBEAT_STALE_THRESHOLD=${HEARTBEAT_STALE_THRESHOLD:-600}
|
|
44
45
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
46
|
+
STALE_KILL_THRESHOLD=${STALE_KILL_THRESHOLD:-900}
|
|
45
47
|
LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
|
|
46
48
|
LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
|
|
47
49
|
LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
|
|
@@ -157,7 +159,8 @@ spawn_and_wait_session() {
|
|
|
157
159
|
fi
|
|
158
160
|
|
|
159
161
|
# Heartbeat monitor (reads progress.json when available, falls back to tail)
|
|
160
|
-
|
|
162
|
+
# Also monitors for stale sessions and auto-kills if no progress for STALE_KILL_THRESHOLD seconds
|
|
163
|
+
start_heartbeat "$cbc_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL" "$STALE_KILL_THRESHOLD"
|
|
161
164
|
local heartbeat_pid="${_HEARTBEAT_PID:-}"
|
|
162
165
|
|
|
163
166
|
# Wait for AI CLI to finish
|
|
@@ -179,6 +182,14 @@ spawn_and_wait_session() {
|
|
|
179
182
|
exit_code=124
|
|
180
183
|
fi
|
|
181
184
|
|
|
185
|
+
# Check for stale-kill marker (heartbeat killed the process due to no progress)
|
|
186
|
+
local stale_kill_marker="$session_dir/logs/stale-kill.json"
|
|
187
|
+
local was_stale_killed=false
|
|
188
|
+
if [[ -f "$stale_kill_marker" ]]; then
|
|
189
|
+
was_stale_killed=true
|
|
190
|
+
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
191
|
+
fi
|
|
192
|
+
|
|
182
193
|
# Show final session summary
|
|
183
194
|
if [[ -f "$session_log" ]]; then
|
|
184
195
|
local final_size=$(wc -c < "$session_log" 2>/dev/null | tr -d ' ')
|
|
@@ -198,6 +209,34 @@ spawn_and_wait_session() {
|
|
|
198
209
|
if [[ $exit_code -eq 124 ]]; then
|
|
199
210
|
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
200
211
|
session_status="timed_out"
|
|
212
|
+
elif [[ "$was_stale_killed" == true ]]; then
|
|
213
|
+
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
214
|
+
# Treat stale-killed as potentially successful — check for commits
|
|
215
|
+
local has_commits=""
|
|
216
|
+
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
217
|
+
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
218
|
+
fi
|
|
219
|
+
if [[ -n "$has_commits" ]]; then
|
|
220
|
+
log_info "Stale-killed session has commits — treating as success"
|
|
221
|
+
session_status="success"
|
|
222
|
+
else
|
|
223
|
+
local uncommitted=""
|
|
224
|
+
uncommitted=$(git -C "$project_root" status --porcelain 2>/dev/null | head -1 || true)
|
|
225
|
+
if [[ -n "$uncommitted" ]]; then
|
|
226
|
+
log_warn "Stale-killed session has uncommitted changes — auto-committing..."
|
|
227
|
+
git -C "$project_root" add -A 2>/dev/null || true
|
|
228
|
+
if git -C "$project_root" commit --no-verify -m "chore($feature_id): auto-commit session work (stale-killed)" 2>/dev/null; then
|
|
229
|
+
log_info "Auto-commit succeeded"
|
|
230
|
+
session_status="success"
|
|
231
|
+
else
|
|
232
|
+
log_warn "Auto-commit failed — no changes to commit"
|
|
233
|
+
session_status="crashed"
|
|
234
|
+
fi
|
|
235
|
+
else
|
|
236
|
+
log_warn "Stale-killed session produced no commits and no changes"
|
|
237
|
+
session_status="crashed"
|
|
238
|
+
fi
|
|
239
|
+
fi
|
|
201
240
|
elif [[ $exit_code -ne 0 ]]; then
|
|
202
241
|
log_warn "Session exited with code $exit_code"
|
|
203
242
|
session_status="crashed"
|
|
@@ -1318,6 +1357,7 @@ show_help() {
|
|
|
1318
1357
|
echo " AI_CLI AI CLI command name (auto-detected: cbc or claude)"
|
|
1319
1358
|
echo " MODEL AI model ID (e.g. claude-opus-4.6, claude-sonnet-4.6, claude-haiku-4.5)"
|
|
1320
1359
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1360
|
+
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1321
1361
|
echo " HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)"
|
|
1322
1362
|
echo " LOG_CLEANUP_ENABLED Run log cleanup before execution (default: 1)"
|
|
1323
1363
|
echo " LOG_RETENTION_DAYS Delete logs older than N days (default: 14)"
|
|
@@ -21,6 +21,7 @@ set -euo pipefail
|
|
|
21
21
|
# PRIZMKIT_PLATFORM Force platform: 'codebuddy' or 'claude' (auto-detected)
|
|
22
22
|
# VERBOSE Set to 1 to enable --verbose on AI CLI
|
|
23
23
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
24
|
+
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
24
25
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
25
26
|
# LOG_CLEANUP_ENABLED Run periodic log cleanup (default: 1)
|
|
26
27
|
# LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
|
|
@@ -40,6 +41,7 @@ MAX_RETRIES=${MAX_RETRIES:-3}
|
|
|
40
41
|
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
41
42
|
HEARTBEAT_STALE_THRESHOLD=${HEARTBEAT_STALE_THRESHOLD:-600}
|
|
42
43
|
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
44
|
+
STALE_KILL_THRESHOLD=${STALE_KILL_THRESHOLD:-900}
|
|
43
45
|
LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
|
|
44
46
|
LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
|
|
45
47
|
LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
|
|
@@ -148,8 +150,8 @@ spawn_and_wait_session() {
|
|
|
148
150
|
watcher_pid=$!
|
|
149
151
|
fi
|
|
150
152
|
|
|
151
|
-
# Heartbeat monitor
|
|
152
|
-
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL"
|
|
153
|
+
# Heartbeat monitor (with stale-kill protection)
|
|
154
|
+
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL" "$STALE_KILL_THRESHOLD"
|
|
153
155
|
local heartbeat_pid="${_HEARTBEAT_PID:-}"
|
|
154
156
|
|
|
155
157
|
# Wait for AI CLI to finish
|
|
@@ -168,6 +170,14 @@ spawn_and_wait_session() {
|
|
|
168
170
|
|
|
169
171
|
[[ $exit_code -eq 143 ]] && exit_code=124
|
|
170
172
|
|
|
173
|
+
# Check for stale-kill marker (heartbeat killed the process due to no progress)
|
|
174
|
+
local stale_kill_marker="$session_dir/logs/stale-kill.json"
|
|
175
|
+
local was_stale_killed=false
|
|
176
|
+
if [[ -f "$stale_kill_marker" ]]; then
|
|
177
|
+
was_stale_killed=true
|
|
178
|
+
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
179
|
+
fi
|
|
180
|
+
|
|
171
181
|
# Session summary
|
|
172
182
|
if [[ -f "$session_log" ]]; then
|
|
173
183
|
local final_size=$(wc -c < "$session_log" 2>/dev/null | tr -d ' ')
|
|
@@ -185,6 +195,33 @@ spawn_and_wait_session() {
|
|
|
185
195
|
if [[ $exit_code -eq 124 ]]; then
|
|
186
196
|
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
187
197
|
session_status="timed_out"
|
|
198
|
+
elif [[ "$was_stale_killed" == true ]]; then
|
|
199
|
+
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
200
|
+
local has_commits=""
|
|
201
|
+
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
202
|
+
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
203
|
+
fi
|
|
204
|
+
if [[ -n "$has_commits" ]]; then
|
|
205
|
+
log_info "Stale-killed session has commits — treating as success"
|
|
206
|
+
session_status="success"
|
|
207
|
+
else
|
|
208
|
+
local uncommitted=""
|
|
209
|
+
uncommitted=$(git -C "$project_root" status --porcelain 2>/dev/null | head -1 || true)
|
|
210
|
+
if [[ -n "$uncommitted" ]]; then
|
|
211
|
+
log_warn "Stale-killed session has uncommitted changes — auto-committing..."
|
|
212
|
+
git -C "$project_root" add -A 2>/dev/null || true
|
|
213
|
+
if git -C "$project_root" commit --no-verify -m "chore($refactor_id): auto-commit session work (stale-killed)" 2>/dev/null; then
|
|
214
|
+
log_info "Auto-commit succeeded"
|
|
215
|
+
session_status="success"
|
|
216
|
+
else
|
|
217
|
+
log_warn "Auto-commit failed — no changes to commit"
|
|
218
|
+
session_status="crashed"
|
|
219
|
+
fi
|
|
220
|
+
else
|
|
221
|
+
log_warn "Stale-killed session produced no commits and no changes"
|
|
222
|
+
session_status="crashed"
|
|
223
|
+
fi
|
|
224
|
+
fi
|
|
188
225
|
elif [[ $exit_code -ne 0 ]]; then
|
|
189
226
|
log_warn "Session exited with code $exit_code"
|
|
190
227
|
session_status="crashed"
|
|
@@ -1129,6 +1166,7 @@ show_help() {
|
|
|
1129
1166
|
echo " VERBOSE Set to 1 for verbose AI CLI output"
|
|
1130
1167
|
echo " STRICT_BEHAVIOR_CHECK Force full test suite after each refactor (default: 1)"
|
|
1131
1168
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1169
|
+
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1132
1170
|
echo " LOG_CLEANUP_ENABLED Run log cleanup before execution (default: 1)"
|
|
1133
1171
|
echo " LOG_RETENTION_DAYS Delete logs older than N days (default: 14)"
|
|
1134
1172
|
echo " LOG_MAX_TOTAL_MB Keep total logs under N MB (default: 1024)"
|
|
@@ -189,6 +189,49 @@ Round 5: 3 failures [test_b, test_d, test_e] ← plateau 3/3 → STOP
|
|
|
189
189
|
|
|
190
190
|
You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
|
|
191
191
|
|
|
192
|
+
**CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
|
|
193
|
+
- You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
|
|
194
|
+
- **NEVER** use Playwright MCP server, Playwright MCP tools, or any MCP-based browser automation
|
|
195
|
+
- If you have Playwright MCP configured, IGNORE it entirely — use the CLI command `playwright-cli` exclusively
|
|
196
|
+
- All browser actions go through `playwright-cli <command>` in the Bash tool, not through any MCP tool call
|
|
197
|
+
|
|
198
|
+
**Step 0 — Playwright CLI Readiness Check (BLOCKING — must pass before any browser action)**:
|
|
199
|
+
|
|
200
|
+
0a. Check if `playwright-cli` is installed:
|
|
201
|
+
```bash
|
|
202
|
+
which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
|
|
203
|
+
```
|
|
204
|
+
If output is `NOT_INSTALLED`, install it:
|
|
205
|
+
```bash
|
|
206
|
+
npm install -g @playwright/cli@latest
|
|
207
|
+
```
|
|
208
|
+
Then verify installation succeeded: `playwright-cli --version`. If installation fails, log `## Browser Verification: SKIPPED — playwright-cli installation failed` in context-snapshot.md and proceed to the next phase.
|
|
209
|
+
|
|
210
|
+
0b. Learn playwright-cli usage (run once per session):
|
|
211
|
+
```bash
|
|
212
|
+
playwright-cli --help
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
0c. Check if playwright-cli skill is installed for the current AI platform:
|
|
216
|
+
```bash
|
|
217
|
+
CURRENT_PLATFORM=""
|
|
218
|
+
if which claude >/dev/null 2>&1; then
|
|
219
|
+
CURRENT_PLATFORM="claude"; SKILL_DIR="$HOME/.claude/skills"
|
|
220
|
+
elif which cbc >/dev/null 2>&1; then
|
|
221
|
+
CURRENT_PLATFORM="codebuddy"; SKILL_DIR="$HOME/.cbc/skills"
|
|
222
|
+
else
|
|
223
|
+
CURRENT_PLATFORM="unknown"
|
|
224
|
+
fi
|
|
225
|
+
if [ -d "$SKILL_DIR/playwright-cli" ] || ls "$SKILL_DIR"/playwright* 2>/dev/null | grep -q .; then
|
|
226
|
+
echo "SKILL_EXISTS"
|
|
227
|
+
else
|
|
228
|
+
echo "SKILL_MISSING"
|
|
229
|
+
fi
|
|
230
|
+
```
|
|
231
|
+
If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform is NOT claude, copy installed skill from `$HOME/.claude/skills/playwright-cli` to `$SKILL_DIR/playwright-cli`.
|
|
232
|
+
|
|
233
|
+
0d. Read the installed playwright-cli skill (SKILL.md) for workflow guidance. Use its recommended patterns to construct your verification flow.
|
|
234
|
+
|
|
192
235
|
**Step 1 — Start Dev Server**:
|
|
193
236
|
|
|
194
237
|
You know this project's tech stack. Detect and start the dev server yourself:
|
|
@@ -196,9 +239,7 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
196
239
|
1. Identify the dev server start command from project config (`package.json` scripts, `Makefile`, `docker-compose.yml`, etc.)
|
|
197
240
|
2. **Detect the dev server port** — use the pre-detected port from pipeline if available, otherwise extract from project config. Do NOT hardcode or guess the port:
|
|
198
241
|
```bash
|
|
199
|
-
# Use pipeline-injected port if available, otherwise extract from package.json
|
|
200
242
|
DEV_PORT={{DEV_PORT}}
|
|
201
|
-
# If DEV_PORT is still a placeholder, detect at runtime:
|
|
202
243
|
if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
|
|
203
244
|
DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')")
|
|
204
245
|
if [ -z "$DEV_PORT" ]; then
|
|
@@ -225,14 +266,14 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
225
266
|
|
|
226
267
|
Use `playwright-cli snapshot` on the running app to discover actual element refs, then verify these goals:
|
|
227
268
|
{{BROWSER_VERIFY_STEPS}}
|
|
228
|
-
Decide the concrete playwright-cli actions (click, fill, assert, etc.) yourself based on the snapshot output and your knowledge of the implemented code. The goals above describe WHAT to verify — you determine HOW.
|
|
229
269
|
|
|
230
|
-
Take a final screenshot
|
|
270
|
+
Construct your verification workflow based on: (1) the playwright-cli skill documentation, (2) the `--help` output, (3) the current task's acceptance criteria. Decide the concrete playwright-cli actions yourself. Take a final screenshot: `playwright-cli screenshot`.
|
|
231
271
|
|
|
232
272
|
**Step 3 — Cleanup (REQUIRED — you started it, you stop it)**:
|
|
233
273
|
|
|
234
|
-
1.
|
|
235
|
-
2.
|
|
274
|
+
1. Close the playwright-cli browser: `playwright-cli close`
|
|
275
|
+
2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
|
|
276
|
+
3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
|
|
236
277
|
|
|
237
278
|
**Step 4 — Reporting**:
|
|
238
279
|
|
|
@@ -241,10 +282,12 @@ Append results to `context-snapshot.md`:
|
|
|
241
282
|
## Browser Verification
|
|
242
283
|
URL: http://localhost:$DEV_PORT
|
|
243
284
|
Dev Server Command: <actual command used>
|
|
244
|
-
|
|
285
|
+
playwright-cli version: <version>
|
|
286
|
+
Steps executed: [list of playwright-cli commands used]
|
|
245
287
|
Screenshot: [path]
|
|
246
288
|
Result: PASS / FAIL (reason)
|
|
247
289
|
Server cleanup: confirmed
|
|
290
|
+
Browser cleanup: confirmed
|
|
248
291
|
```
|
|
249
292
|
|
|
250
293
|
If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
|
|
@@ -287,6 +287,49 @@ If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review
|
|
|
287
287
|
|
|
288
288
|
You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
|
|
289
289
|
|
|
290
|
+
**CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
|
|
291
|
+
- You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
|
|
292
|
+
- **NEVER** use Playwright MCP server, Playwright MCP tools, or any MCP-based browser automation
|
|
293
|
+
- If you have Playwright MCP configured, IGNORE it entirely — use the CLI command `playwright-cli` exclusively
|
|
294
|
+
- All browser actions go through `playwright-cli <command>` in the Bash tool, not through any MCP tool call
|
|
295
|
+
|
|
296
|
+
**Step 0 — Playwright CLI Readiness Check (BLOCKING — must pass before any browser action)**:
|
|
297
|
+
|
|
298
|
+
0a. Check if `playwright-cli` is installed:
|
|
299
|
+
```bash
|
|
300
|
+
which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
|
|
301
|
+
```
|
|
302
|
+
If output is `NOT_INSTALLED`, install it:
|
|
303
|
+
```bash
|
|
304
|
+
npm install -g @playwright/cli@latest
|
|
305
|
+
```
|
|
306
|
+
Then verify installation succeeded: `playwright-cli --version`. If installation fails, log `## Browser Verification: SKIPPED — playwright-cli installation failed` in context-snapshot.md and proceed to the next phase.
|
|
307
|
+
|
|
308
|
+
0b. Learn playwright-cli usage (run once per session):
|
|
309
|
+
```bash
|
|
310
|
+
playwright-cli --help
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
0c. Check if playwright-cli skill is installed for the current AI platform:
|
|
314
|
+
```bash
|
|
315
|
+
CURRENT_PLATFORM=""
|
|
316
|
+
if which claude >/dev/null 2>&1; then
|
|
317
|
+
CURRENT_PLATFORM="claude"; SKILL_DIR="$HOME/.claude/skills"
|
|
318
|
+
elif which cbc >/dev/null 2>&1; then
|
|
319
|
+
CURRENT_PLATFORM="codebuddy"; SKILL_DIR="$HOME/.cbc/skills"
|
|
320
|
+
else
|
|
321
|
+
CURRENT_PLATFORM="unknown"
|
|
322
|
+
fi
|
|
323
|
+
if [ -d "$SKILL_DIR/playwright-cli" ] || ls "$SKILL_DIR"/playwright* 2>/dev/null | grep -q .; then
|
|
324
|
+
echo "SKILL_EXISTS"
|
|
325
|
+
else
|
|
326
|
+
echo "SKILL_MISSING"
|
|
327
|
+
fi
|
|
328
|
+
```
|
|
329
|
+
If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform is NOT claude, copy installed skill from `$HOME/.claude/skills/playwright-cli` to `$SKILL_DIR/playwright-cli`.
|
|
330
|
+
|
|
331
|
+
0d. Read the installed playwright-cli skill (SKILL.md) for workflow guidance. Use its recommended patterns to construct your verification flow.
|
|
332
|
+
|
|
290
333
|
**Step 1 — Start Dev Server**:
|
|
291
334
|
|
|
292
335
|
You know this project's tech stack. Detect and start the dev server yourself:
|
|
@@ -294,9 +337,7 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
294
337
|
1. Identify the dev server start command from project config (`package.json` scripts, `Makefile`, `docker-compose.yml`, etc.)
|
|
295
338
|
2. **Detect the dev server port** — use the pre-detected port from pipeline if available, otherwise extract from project config. Do NOT hardcode or guess the port:
|
|
296
339
|
```bash
|
|
297
|
-
# Use pipeline-injected port if available, otherwise extract from package.json
|
|
298
340
|
DEV_PORT={{DEV_PORT}}
|
|
299
|
-
# If DEV_PORT is still a placeholder, detect at runtime:
|
|
300
341
|
if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
|
|
301
342
|
DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')")
|
|
302
343
|
if [ -z "$DEV_PORT" ]; then
|
|
@@ -323,14 +364,14 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
323
364
|
|
|
324
365
|
Use `playwright-cli snapshot` on the running app to discover actual element refs, then verify these goals:
|
|
325
366
|
{{BROWSER_VERIFY_STEPS}}
|
|
326
|
-
Decide the concrete playwright-cli actions (click, fill, assert, etc.) yourself based on the snapshot output and your knowledge of the implemented code. The goals above describe WHAT to verify — you determine HOW.
|
|
327
367
|
|
|
328
|
-
Take a final screenshot
|
|
368
|
+
Construct your verification workflow based on: (1) the playwright-cli skill documentation, (2) the `--help` output, (3) the current task's acceptance criteria. Decide the concrete playwright-cli actions yourself. Take a final screenshot: `playwright-cli screenshot`.
|
|
329
369
|
|
|
330
370
|
**Step 3 — Cleanup (REQUIRED — you started it, you stop it)**:
|
|
331
371
|
|
|
332
|
-
1.
|
|
333
|
-
2.
|
|
372
|
+
1. Close the playwright-cli browser: `playwright-cli close`
|
|
373
|
+
2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
|
|
374
|
+
3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
|
|
334
375
|
|
|
335
376
|
**Step 4 — Reporting**:
|
|
336
377
|
|
|
@@ -339,10 +380,12 @@ Append results to `context-snapshot.md`:
|
|
|
339
380
|
## Browser Verification
|
|
340
381
|
URL: http://localhost:$DEV_PORT
|
|
341
382
|
Dev Server Command: <actual command used>
|
|
342
|
-
|
|
383
|
+
playwright-cli version: <version>
|
|
384
|
+
Steps executed: [list of playwright-cli commands used]
|
|
343
385
|
Screenshot: [path]
|
|
344
386
|
Result: PASS / FAIL (reason)
|
|
345
387
|
Server cleanup: confirmed
|
|
388
|
+
Browser cleanup: confirmed
|
|
346
389
|
```
|
|
347
390
|
|
|
348
391
|
If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
|
|
@@ -359,6 +359,49 @@ If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review
|
|
|
359
359
|
|
|
360
360
|
You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
|
|
361
361
|
|
|
362
|
+
**CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
|
|
363
|
+
- You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
|
|
364
|
+
- **NEVER** use Playwright MCP server, Playwright MCP tools, or any MCP-based browser automation
|
|
365
|
+
- If you have Playwright MCP configured, IGNORE it entirely — use the CLI command `playwright-cli` exclusively
|
|
366
|
+
- All browser actions go through `playwright-cli <command>` in the Bash tool, not through any MCP tool call
|
|
367
|
+
|
|
368
|
+
**Step 0 — Playwright CLI Readiness Check (BLOCKING — must pass before any browser action)**:
|
|
369
|
+
|
|
370
|
+
0a. Check if `playwright-cli` is installed:
|
|
371
|
+
```bash
|
|
372
|
+
which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
|
|
373
|
+
```
|
|
374
|
+
If output is `NOT_INSTALLED`, install it:
|
|
375
|
+
```bash
|
|
376
|
+
npm install -g @playwright/cli@latest
|
|
377
|
+
```
|
|
378
|
+
Then verify installation succeeded: `playwright-cli --version`. If installation fails, log `## Browser Verification: SKIPPED — playwright-cli installation failed` in context-snapshot.md and proceed to the next phase.
|
|
379
|
+
|
|
380
|
+
0b. Learn playwright-cli usage (run once per session):
|
|
381
|
+
```bash
|
|
382
|
+
playwright-cli --help
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
0c. Check if playwright-cli skill is installed for the current AI platform:
|
|
386
|
+
```bash
|
|
387
|
+
CURRENT_PLATFORM=""
|
|
388
|
+
if which claude >/dev/null 2>&1; then
|
|
389
|
+
CURRENT_PLATFORM="claude"; SKILL_DIR="$HOME/.claude/skills"
|
|
390
|
+
elif which cbc >/dev/null 2>&1; then
|
|
391
|
+
CURRENT_PLATFORM="codebuddy"; SKILL_DIR="$HOME/.cbc/skills"
|
|
392
|
+
else
|
|
393
|
+
CURRENT_PLATFORM="unknown"
|
|
394
|
+
fi
|
|
395
|
+
if [ -d "$SKILL_DIR/playwright-cli" ] || ls "$SKILL_DIR"/playwright* 2>/dev/null | grep -q .; then
|
|
396
|
+
echo "SKILL_EXISTS"
|
|
397
|
+
else
|
|
398
|
+
echo "SKILL_MISSING"
|
|
399
|
+
fi
|
|
400
|
+
```
|
|
401
|
+
If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform is NOT claude, copy installed skill from `$HOME/.claude/skills/playwright-cli` to `$SKILL_DIR/playwright-cli`.
|
|
402
|
+
|
|
403
|
+
0d. Read the installed playwright-cli skill (SKILL.md) for workflow guidance. Use its recommended patterns to construct your verification flow.
|
|
404
|
+
|
|
362
405
|
**Step 1 — Start Dev Server**:
|
|
363
406
|
|
|
364
407
|
You know this project's tech stack. Detect and start the dev server yourself:
|
|
@@ -366,9 +409,7 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
366
409
|
1. Identify the dev server start command from project config (`package.json` scripts, `Makefile`, `docker-compose.yml`, etc.)
|
|
367
410
|
2. **Detect the dev server port** — use the pre-detected port from pipeline if available, otherwise extract from project config. Do NOT hardcode or guess the port:
|
|
368
411
|
```bash
|
|
369
|
-
# Use pipeline-injected port if available, otherwise extract from package.json
|
|
370
412
|
DEV_PORT={{DEV_PORT}}
|
|
371
|
-
# If DEV_PORT is still a placeholder, detect at runtime:
|
|
372
413
|
if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
|
|
373
414
|
DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')")
|
|
374
415
|
if [ -z "$DEV_PORT" ]; then
|
|
@@ -395,14 +436,14 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
395
436
|
|
|
396
437
|
Use `playwright-cli snapshot` on the running app to discover actual element refs, then verify these goals:
|
|
397
438
|
{{BROWSER_VERIFY_STEPS}}
|
|
398
|
-
Decide the concrete playwright-cli actions (click, fill, assert, etc.) yourself based on the snapshot output and your knowledge of the implemented code. The goals above describe WHAT to verify — you determine HOW.
|
|
399
439
|
|
|
400
|
-
Take a final screenshot
|
|
440
|
+
Construct your verification workflow based on: (1) the playwright-cli skill documentation, (2) the `--help` output, (3) the current task's acceptance criteria. Decide the concrete playwright-cli actions yourself. Take a final screenshot: `playwright-cli screenshot`.
|
|
401
441
|
|
|
402
442
|
**Step 3 — Cleanup (REQUIRED — you started it, you stop it)**:
|
|
403
443
|
|
|
404
|
-
1.
|
|
405
|
-
2.
|
|
444
|
+
1. Close the playwright-cli browser: `playwright-cli close`
|
|
445
|
+
2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
|
|
446
|
+
3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
|
|
406
447
|
|
|
407
448
|
**Step 4 — Reporting**:
|
|
408
449
|
|
|
@@ -411,10 +452,12 @@ Append results to `context-snapshot.md`:
|
|
|
411
452
|
## Browser Verification
|
|
412
453
|
URL: http://localhost:$DEV_PORT
|
|
413
454
|
Dev Server Command: <actual command used>
|
|
414
|
-
|
|
455
|
+
playwright-cli version: <version>
|
|
456
|
+
Steps executed: [list of playwright-cli commands used]
|
|
415
457
|
Screenshot: [path]
|
|
416
458
|
Result: PASS / FAIL (reason)
|
|
417
459
|
Server cleanup: confirmed
|
|
460
|
+
Browser cleanup: confirmed
|
|
418
461
|
```
|
|
419
462
|
|
|
420
463
|
If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
|
|
@@ -11,3 +11,23 @@ You are running in **headless non-interactive mode** with a FINITE context windo
|
|
|
11
11
|
5. **Minimize tool output** — Never load full command output into context. First capture to a temp file (`cmd 2>&1 | tee /tmp/out.txt | tail -20`), then scan the head/tail to identify relevant fields, and use targeted filtering (`grep`, `sed`, `awk`) to extract only the information needed for the current task. Only read the filtered result — never the raw full output.
|
|
12
12
|
6. **No intermediate commits** — Do NOT run `git add`/`git commit` during implementation phases. All changes are committed once at the end via `/prizmkit-committer`.
|
|
13
13
|
7. **Capture test output once** — When running test suites, always use `$TEST_CMD 2>&1 | tee /tmp/test-out.txt | tail -20`. Then grep `/tmp/test-out.txt` for details. Never re-run the suite just to apply a different filter.
|
|
14
|
+
8. **Scaffold / generated file awareness (CRITICAL)** — When you run a scaffolding tool or package manager init command (`npm init`, `npx create-*`, `vite create`, `cargo init`, `go mod init`, `rails new`, `django-admin startproject`, `npx shadcn-ui init`, etc.), the output files are **generated boilerplate**. You MUST:
|
|
15
|
+
- Identify and mentally tag all files created by the tool as "scaffold files"
|
|
16
|
+
- Record the list of scaffold-generated files in context-snapshot.md under a `### Scaffold Files (do not re-read)` section
|
|
17
|
+
- **NEVER re-read scaffold files** after initial creation. Their content is standard boilerplate — you already know what they contain from the tool that generated them
|
|
18
|
+
- If you need to modify a scaffold file, make the edit directly without reading it first (you know the standard template content)
|
|
19
|
+
- This applies equally to `node_modules/`, `package-lock.json`, generated config files (`tsconfig.json`, `vite.config.ts`, `tailwind.config.js`, `.eslintrc`, etc.) produced by init commands
|
|
20
|
+
- When passing context to subagents, explicitly tell them which files are scaffold-generated so they skip reading them too
|
|
21
|
+
9. **Package version verification (HARD CONSTRAINT — BLOCKING)** — Before writing ANY dependency version in `package.json`, `requirements.txt`, `Cargo.toml`, `go.mod`, `Gemfile`, `pyproject.toml`, or any other dependency manifest:
|
|
22
|
+
- You MUST verify the real version exists by querying the package registry first:
|
|
23
|
+
- npm/Node.js: `npm view <package> dist-tags.latest 2>/dev/null`
|
|
24
|
+
- Python/pip: `pip index versions <package> 2>/dev/null | head -1`
|
|
25
|
+
- Go: `go list -m -versions <module>@latest 2>/dev/null`
|
|
26
|
+
- Rust: `cargo search <crate> --limit 1 2>/dev/null`
|
|
27
|
+
- **NEVER guess or hallucinate version numbers**. If you cannot verify a version, use `"latest"` or `"*"` as a placeholder, or omit the version constraint entirely and let the package manager resolve it
|
|
28
|
+
- If the registry query fails (network issue, package not found), you MUST either:
|
|
29
|
+
(a) Use a known-safe version you have high confidence in, OR
|
|
30
|
+
(b) Skip that dependency and document it as a manual step, OR
|
|
31
|
+
(c) Use no version constraint (e.g., `"express": "*"`)
|
|
32
|
+
- **This is a BLOCKING gate**: do NOT run `npm install` / `pip install` / `cargo build` / `go mod tidy` until ALL versions in the manifest have been verified or use open constraints
|
|
33
|
+
- Batch version lookups: query multiple packages in parallel to save time (e.g., run multiple `npm view` commands concurrently)
|
|
@@ -2,6 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
|
|
4
4
|
|
|
5
|
+
**CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
|
|
6
|
+
- You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
|
|
7
|
+
- **NEVER** use Playwright MCP server, Playwright MCP tools, or any MCP-based browser automation
|
|
8
|
+
- If you have Playwright MCP configured, IGNORE it entirely — use the CLI command `playwright-cli` exclusively
|
|
9
|
+
- All browser actions go through `playwright-cli <command>` in the Bash tool, not through any MCP tool call
|
|
10
|
+
|
|
11
|
+
**Step 0 — Playwright CLI Readiness Check (BLOCKING — must pass before any browser action)**:
|
|
12
|
+
|
|
13
|
+
0a. Check if `playwright-cli` is installed:
|
|
14
|
+
```bash
|
|
15
|
+
which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
|
|
16
|
+
```
|
|
17
|
+
If output is `NOT_INSTALLED`, install it:
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @playwright/cli@latest
|
|
20
|
+
```
|
|
21
|
+
Then verify installation succeeded:
|
|
22
|
+
```bash
|
|
23
|
+
playwright-cli --version
|
|
24
|
+
```
|
|
25
|
+
If installation fails, log the error in context-snapshot.md under `## Browser Verification: SKIPPED — playwright-cli installation failed` and proceed to the next phase. Do NOT attempt browser verification without playwright-cli.
|
|
26
|
+
|
|
27
|
+
0b. Learn playwright-cli usage (run once per session to understand available commands):
|
|
28
|
+
```bash
|
|
29
|
+
playwright-cli --help
|
|
30
|
+
```
|
|
31
|
+
Use this output to determine the correct commands for your verification steps. Do NOT guess command syntax — refer to the help output.
|
|
32
|
+
|
|
33
|
+
0c. Check if playwright-cli skill is installed for the current AI platform:
|
|
34
|
+
```bash
|
|
35
|
+
# Detect AI CLI platform
|
|
36
|
+
CURRENT_PLATFORM=""
|
|
37
|
+
if which claude >/dev/null 2>&1; then
|
|
38
|
+
CURRENT_PLATFORM="claude"
|
|
39
|
+
SKILL_DIR="$HOME/.claude/skills"
|
|
40
|
+
elif which cbc >/dev/null 2>&1; then
|
|
41
|
+
CURRENT_PLATFORM="codebuddy"
|
|
42
|
+
SKILL_DIR="$HOME/.cbc/skills"
|
|
43
|
+
else
|
|
44
|
+
# Try to detect from environment or config
|
|
45
|
+
CURRENT_PLATFORM="unknown"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Check if playwright-cli skill exists
|
|
49
|
+
if [ -d "$SKILL_DIR/playwright-cli" ] || ls "$SKILL_DIR"/playwright* 2>/dev/null | grep -q .; then
|
|
50
|
+
echo "SKILL_EXISTS"
|
|
51
|
+
else
|
|
52
|
+
echo "SKILL_MISSING"
|
|
53
|
+
fi
|
|
54
|
+
```
|
|
55
|
+
If `SKILL_MISSING`:
|
|
56
|
+
```bash
|
|
57
|
+
# Install playwright-cli skills (defaults to claude platform)
|
|
58
|
+
playwright-cli install --skills
|
|
59
|
+
```
|
|
60
|
+
If the current platform is NOT claude, move the installed skill files to the correct location:
|
|
61
|
+
```bash
|
|
62
|
+
# Skills are installed to claude's default location — move to current platform's skill dir
|
|
63
|
+
if [ "$CURRENT_PLATFORM" != "claude" ] && [ "$CURRENT_PLATFORM" != "unknown" ]; then
|
|
64
|
+
CLAUDE_SKILL_DIR="$HOME/.claude/skills"
|
|
65
|
+
if [ -d "$CLAUDE_SKILL_DIR/playwright-cli" ]; then
|
|
66
|
+
mkdir -p "$SKILL_DIR"
|
|
67
|
+
cp -r "$CLAUDE_SKILL_DIR/playwright-cli" "$SKILL_DIR/"
|
|
68
|
+
echo "Moved playwright-cli skill from claude to $CURRENT_PLATFORM"
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
0d. Read the installed playwright-cli skill for workflow guidance:
|
|
74
|
+
After skill installation, read the skill's SKILL.md to understand recommended workflows and patterns. Use these patterns to construct your verification flow — do NOT invent your own patterns if the skill provides them.
|
|
75
|
+
|
|
5
76
|
**Step 1 — Start Dev Server**:
|
|
6
77
|
|
|
7
78
|
You know this project's tech stack. Detect and start the dev server yourself:
|
|
@@ -39,14 +110,20 @@ You know this project's tech stack. Detect and start the dev server yourself:
|
|
|
39
110
|
Use `playwright-cli snapshot` on the running app to discover actual element refs, then verify these goals:
|
|
40
111
|
{{BROWSER_VERIFY_STEPS}}
|
|
41
112
|
|
|
42
|
-
|
|
113
|
+
Construct your verification workflow based on:
|
|
114
|
+
1. The playwright-cli skill documentation (read in Step 0d)
|
|
115
|
+
2. The `playwright-cli --help` output (captured in Step 0b)
|
|
116
|
+
3. The current task's acceptance criteria and implemented features
|
|
117
|
+
|
|
118
|
+
Decide the concrete playwright-cli actions (click, fill, snapshot, screenshot, etc.) yourself based on the snapshot output and your knowledge of the implemented code. The goals above describe WHAT to verify — you determine HOW using playwright-cli commands.
|
|
43
119
|
|
|
44
|
-
Take a final screenshot for evidence
|
|
120
|
+
Take a final screenshot for evidence: `playwright-cli screenshot`
|
|
45
121
|
|
|
46
122
|
**Step 3 — Cleanup (REQUIRED — you started it, you stop it)**:
|
|
47
123
|
|
|
48
|
-
1.
|
|
49
|
-
2.
|
|
124
|
+
1. Close the playwright-cli browser: `playwright-cli close`
|
|
125
|
+
2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
|
|
126
|
+
3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
|
|
50
127
|
|
|
51
128
|
**Step 4 — Reporting**:
|
|
52
129
|
|
|
@@ -55,10 +132,12 @@ Append results to `context-snapshot.md`:
|
|
|
55
132
|
## Browser Verification
|
|
56
133
|
URL: http://localhost:$DEV_PORT
|
|
57
134
|
Dev Server Command: <actual command used>
|
|
58
|
-
|
|
135
|
+
playwright-cli version: <version>
|
|
136
|
+
Steps executed: [list of playwright-cli commands used]
|
|
59
137
|
Screenshot: [path]
|
|
60
138
|
Result: PASS / FAIL (reason)
|
|
61
139
|
Server cleanup: confirmed
|
|
140
|
+
Browser cleanup: confirmed
|
|
62
141
|
```
|
|
63
142
|
|
|
64
143
|
If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
**Build artifacts rule** (passed to Dev): After any build/compile command (`go build`, `npm run build`, `tsc`, etc.), ensure the output binary or build directory is in `.gitignore`. Never commit compiled binaries, build output, or generated artifacts.
|
|
4
4
|
|
|
5
|
+
**Dependency version gate (BLOCKING — pass to Dev agent)**: Before running ANY package install command (`npm install`, `pip install`, `cargo build`, `go mod tidy`, `bundle install`, etc.):
|
|
6
|
+
1. Every version number in the dependency manifest MUST be verified against the real registry (see Context Budget Rules §9)
|
|
7
|
+
2. If a scaffold tool generated a `package.json` / `requirements.txt` / etc., verify the versions it wrote too — scaffold tools can emit outdated versions
|
|
8
|
+
3. Do NOT proceed with install until all versions are confirmed real. Violation = wasted timeout cycles that can crash the session
|
|
9
|
+
|
|
10
|
+
**Scaffold file rule (pass to Dev agent)**: After running any init/scaffold command, record generated files in context-snapshot.md under `### Scaffold Files (do not re-read)`. Never re-read these files — their content is standard boilerplate (see Context Budget Rules §8). When spawning subagents, explicitly list scaffold files so they skip reading them.
|
|
11
|
+
|
|
5
12
|
**Spawn Agent**:
|
|
6
13
|
| Parameter | Value |
|
|
7
14
|
|-----------|-------|
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
**Build artifacts rule** (passed to Dev): After any build/compile command (`go build`, `npm run build`, `tsc`, etc.), ensure the output binary or build directory is in `.gitignore`. Never commit compiled binaries, build output, or generated artifacts.
|
|
4
4
|
|
|
5
|
+
**Dependency version gate (BLOCKING — pass to Dev agent)**: Before running ANY package install command (`npm install`, `pip install`, `cargo build`, `go mod tidy`, `bundle install`, etc.):
|
|
6
|
+
1. Every version number in the dependency manifest MUST be verified against the real registry (see Context Budget Rules §9)
|
|
7
|
+
2. If a scaffold tool generated a `package.json` / `requirements.txt` / etc., verify the versions it wrote too — scaffold tools can emit outdated versions
|
|
8
|
+
3. Do NOT proceed with install until all versions are confirmed real. Violation = wasted timeout cycles that can crash the session
|
|
9
|
+
|
|
10
|
+
**Scaffold file rule (pass to Dev agent)**: After running any init/scaffold command, record generated files in context-snapshot.md under `### Scaffold Files (do not re-read)`. Never re-read these files — their content is standard boilerplate (see Context Budget Rules §8). When spawning subagents, explicitly list scaffold files so they skip reading them.
|
|
11
|
+
|
|
5
12
|
Before spawning Dev, check plan.md Tasks section:
|
|
6
13
|
```bash
|
|
7
14
|
grep -c '^\- \[ \]' .prizmkit/specs/{{FEATURE_SLUG}}/plan.md 2>/dev/null || true
|
|
@@ -7,6 +7,13 @@ grep -q '^/binary-name$' .gitignore || echo '/binary-name' >> .gitignore
|
|
|
7
7
|
```
|
|
8
8
|
Never commit compiled binaries, build output, or generated artifacts.
|
|
9
9
|
|
|
10
|
+
**Dependency version gate (BLOCKING)**: Before running ANY package install command (`npm install`, `pip install`, `cargo build`, `go mod tidy`, `bundle install`, etc.):
|
|
11
|
+
1. Every version number in your dependency manifest MUST be verified against the real registry (see Context Budget Rules §9)
|
|
12
|
+
2. If you used a scaffold tool that generated a `package.json` / `requirements.txt` / etc., verify the versions it wrote too — scaffold tools can emit outdated versions
|
|
13
|
+
3. Do NOT proceed with install until all versions are confirmed real. Violation = wasted timeout cycles
|
|
14
|
+
|
|
15
|
+
**Scaffold file rule**: After running any init/scaffold command, record generated files in context-snapshot.md under `### Scaffold Files (do not re-read)`. Never re-read these files — their content is standard boilerplate (see Context Budget Rules §8).
|
|
16
|
+
|
|
10
17
|
**3a.** Detect test commands and record baseline:
|
|
11
18
|
|
|
12
19
|
You know this project's tech stack. Identify ALL test commands that apply (e.g., `go test ./...`, `npm test`, `cargo test`, `pytest`, `make test`, etc.). Record them as `TEST_CMDS`. Then record baseline:
|