prizmkit 1.1.98 → 1.1.100
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 +5 -5
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +1 -1
- package/bundled/dev-pipeline/launch-feature-daemon.sh +1 -1
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +1 -1
- package/bundled/dev-pipeline/lib/common.sh +244 -25
- package/bundled/dev-pipeline/reset-bug.sh +32 -2
- package/bundled/dev-pipeline/reset-feature.sh +32 -2
- package/bundled/dev-pipeline/reset-refactor.sh +32 -2
- package/bundled/dev-pipeline/run-bugfix.sh +133 -18
- package/bundled/dev-pipeline/run-feature.sh +134 -18
- package/bundled/dev-pipeline/run-refactor.sh +133 -18
- package/bundled/dev-pipeline/scripts/check-session-status.py +74 -1
- package/bundled/dev-pipeline/scripts/continuation.py +374 -0
- package/bundled/dev-pipeline/scripts/detect-stuck.py +5 -5
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +29 -35
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +19 -25
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +19 -25
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +1 -1
- package/bundled/dev-pipeline/scripts/init-pipeline.py +1 -1
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +1 -1
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +146 -16
- package/bundled/dev-pipeline/scripts/update-bug-status.py +220 -13
- package/bundled/dev-pipeline/scripts/update-feature-status.py +244 -18
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +220 -13
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +3 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +3 -3
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +31 -66
- package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
- package/bundled/dev-pipeline/tests/conftest.py +1 -0
- package/bundled/dev-pipeline/tests/test_auto_skip.py +518 -8
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +103 -0
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +60 -0
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +43 -0
- package/bundled/dev-pipeline-windows/lib/common.ps1 +172 -10
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +95 -11
- package/bundled/dev-pipeline-windows/lib/reset.ps1 +34 -0
- package/bundled/dev-pipeline-windows/reset-bug.ps1 +1 -0
- package/bundled/dev-pipeline-windows/reset-feature.ps1 +1 -0
- package/bundled/dev-pipeline-windows/reset-refactor.ps1 +1 -0
- package/bundled/dev-pipeline-windows/scripts/check-session-status.py +74 -1
- package/bundled/dev-pipeline-windows/scripts/continuation.py +374 -0
- package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +5 -5
- package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +29 -35
- package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +20 -25
- package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +20 -25
- package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +1 -1
- package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +1 -1
- package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +1 -1
- package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +146 -16
- package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +220 -13
- package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +244 -18
- package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +220 -13
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +1 -1
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +2 -2
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +3 -3
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +3 -3
- package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +31 -68
- package/bundled/dev-pipeline-windows/templates/session-status-schema.json +1 -1
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills/recovery-workflow/SKILL.md +2 -2
- package/bundled/skills/recovery-workflow/evals/evals.json +2 -2
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills-windows/recovery-workflow/SKILL.md +2 -2
- package/bundled/skills-windows/recovery-workflow/evals/evals.json +2 -2
- package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +2 -2
- package/package.json +1 -1
- package/bundled/dev-pipeline/scripts/monitor-log.sh +0 -104
- package/bundled/dev-pipeline-windows/scripts/monitor-log.ps1 +0 -102
|
@@ -23,8 +23,7 @@ set -euo pipefail
|
|
|
23
23
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
24
24
|
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
25
25
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
26
|
-
# MAX_LOG_SIZE
|
|
27
|
-
# LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)
|
|
26
|
+
# MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)
|
|
28
27
|
# DEV_BRANCH Custom dev branch name (default: auto-generated bugfix/pipeline-{run_id})
|
|
29
28
|
# AUTO_PUSH Auto-push to remote after successful bug fix (default: 0). Set to 1 to enable.
|
|
30
29
|
# STOP_ON_FAILURE Stop pipeline after a task exhausts all retries (default: 0). Set to 1 to stop.
|
|
@@ -139,6 +138,16 @@ spawn_and_wait_session() {
|
|
|
139
138
|
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
140
139
|
fi
|
|
141
140
|
|
|
141
|
+
local was_context_overflow=false
|
|
142
|
+
if prizm_detect_context_overflow_error "$session_log" "$progress_json"; then
|
|
143
|
+
was_context_overflow=true
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
local was_ai_runtime_error=false
|
|
147
|
+
if prizm_detect_ai_runtime_error "$session_log" "$progress_json"; then
|
|
148
|
+
was_ai_runtime_error=true
|
|
149
|
+
fi
|
|
150
|
+
|
|
142
151
|
local was_infra_error=false
|
|
143
152
|
if [[ $exit_code -ne 0 ]] && prizm_detect_infra_error "$session_log" "$progress_json"; then
|
|
144
153
|
was_infra_error=true
|
|
@@ -162,7 +171,22 @@ spawn_and_wait_session() {
|
|
|
162
171
|
project_root="$PROJECT_ROOT"
|
|
163
172
|
local default_branch="$base_branch"
|
|
164
173
|
|
|
165
|
-
|
|
174
|
+
local has_commits=""
|
|
175
|
+
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
176
|
+
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
if [[ -n "$has_commits" ]]; then
|
|
180
|
+
session_status="success"
|
|
181
|
+
elif [[ "$was_context_overflow" == true ]]; then
|
|
182
|
+
log_warn "Session failed because the AI CLI exceeded the model context window"
|
|
183
|
+
log_warn "Context overflow is retried without consuming code retry budget"
|
|
184
|
+
session_status="context_overflow"
|
|
185
|
+
elif [[ "$was_ai_runtime_error" == true ]]; then
|
|
186
|
+
log_warn "Session failed due to structured AI runtime error"
|
|
187
|
+
log_warn "AI runtime errors are retried without consuming code retry budget"
|
|
188
|
+
session_status="infra_error"
|
|
189
|
+
elif [[ "$was_infra_error" == true ]]; then
|
|
166
190
|
log_warn "Session failed due to AI CLI/provider infrastructure error"
|
|
167
191
|
log_warn "Infrastructure errors are retried without consuming code retry budget"
|
|
168
192
|
session_status="infra_error"
|
|
@@ -273,6 +297,12 @@ finalize_bug_status_after_branch_return() {
|
|
|
273
297
|
local session_status="$4"
|
|
274
298
|
local max_retries="$5"
|
|
275
299
|
local max_infra_retries="$6"
|
|
300
|
+
local base_branch="${7:-main}"
|
|
301
|
+
local active_dev_branch="${8:-}"
|
|
302
|
+
local fatal_error_code="${9:-}"
|
|
303
|
+
local continuation_summary_path="${10:-}"
|
|
304
|
+
local no_progress_count="${11:-0}"
|
|
305
|
+
local progress_fingerprint="${12:-}"
|
|
276
306
|
|
|
277
307
|
# Update bug status on the original branch. The caller commits the resulting
|
|
278
308
|
# bug-list diff immediately after this helper returns.
|
|
@@ -285,6 +315,12 @@ finalize_bug_status_after_branch_return() {
|
|
|
285
315
|
--session-id "$session_id" \
|
|
286
316
|
--max-retries "$max_retries" \
|
|
287
317
|
--max-infra-retries "$max_infra_retries" \
|
|
318
|
+
--active-dev-branch "$active_dev_branch" \
|
|
319
|
+
--base-branch "$base_branch" \
|
|
320
|
+
--last-fatal-error-code "$fatal_error_code" \
|
|
321
|
+
--continuation-summary-path "$continuation_summary_path" \
|
|
322
|
+
--no-progress-count "$no_progress_count" \
|
|
323
|
+
--progress-fingerprint "$progress_fingerprint" \
|
|
288
324
|
--action update) || {
|
|
289
325
|
log_error "Failed to update bug status: $update_output"
|
|
290
326
|
update_output=""
|
|
@@ -519,7 +555,7 @@ sys.exit(1)
|
|
|
519
555
|
log_info "Removed $dev_team_dir"
|
|
520
556
|
fi
|
|
521
557
|
|
|
522
|
-
local bug_state_dir="$STATE_DIR
|
|
558
|
+
local bug_state_dir="$STATE_DIR/$bug_id"
|
|
523
559
|
if [[ -d "$bug_state_dir" ]]; then
|
|
524
560
|
rm -rf "$bug_state_dir"
|
|
525
561
|
log_info "Removed $bug_state_dir"
|
|
@@ -544,7 +580,7 @@ sys.exit(1)
|
|
|
544
580
|
local run_id session_id session_dir bootstrap_prompt
|
|
545
581
|
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
546
582
|
session_id="${bug_id}-$(date +%Y%m%d%H%M%S)"
|
|
547
|
-
session_dir="$STATE_DIR
|
|
583
|
+
session_dir="$STATE_DIR/$bug_id/sessions/$session_id"
|
|
548
584
|
mkdir -p "$session_dir/logs"
|
|
549
585
|
|
|
550
586
|
bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
@@ -553,7 +589,7 @@ sys.exit(1)
|
|
|
553
589
|
local retry_count
|
|
554
590
|
retry_count=$(python3 -c "
|
|
555
591
|
import json, os
|
|
556
|
-
status_path = os.path.join('$STATE_DIR', '
|
|
592
|
+
status_path = os.path.join('$STATE_DIR', '$bug_id', 'status.json')
|
|
557
593
|
if os.path.isfile(status_path):
|
|
558
594
|
with open(status_path) as f:
|
|
559
595
|
d = json.load(f)
|
|
@@ -564,7 +600,7 @@ else:
|
|
|
564
600
|
local resume_phase
|
|
565
601
|
resume_phase=$(python3 -c "
|
|
566
602
|
import json, os
|
|
567
|
-
status_path = os.path.join('$STATE_DIR', '
|
|
603
|
+
status_path = os.path.join('$STATE_DIR', '$bug_id', 'status.json')
|
|
568
604
|
if os.path.isfile(status_path):
|
|
569
605
|
with open(status_path) as f:
|
|
570
606
|
d = json.load(f)
|
|
@@ -723,6 +759,11 @@ else:
|
|
|
723
759
|
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$bug_model" "$_ORIGINAL_BRANCH"
|
|
724
760
|
local session_status="$_SPAWN_RESULT"
|
|
725
761
|
|
|
762
|
+
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
763
|
+
local continuation_summary_path=""
|
|
764
|
+
local no_progress_count=0
|
|
765
|
+
local progress_after=""
|
|
766
|
+
|
|
726
767
|
# Merge dev branch back to original on success
|
|
727
768
|
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
728
769
|
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
@@ -742,7 +783,7 @@ else:
|
|
|
742
783
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
743
784
|
|
|
744
785
|
finalize_bug_status_after_branch_return \
|
|
745
|
-
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES"
|
|
786
|
+
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
746
787
|
|
|
747
788
|
# Commit bug status update on the original branch (after guaranteed return)
|
|
748
789
|
if ! git -C "$_proj_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
@@ -991,13 +1032,21 @@ DEPLOY_PROMPT_EOF
|
|
|
991
1032
|
fi
|
|
992
1033
|
|
|
993
1034
|
# Parse bug info
|
|
994
|
-
local bug_id bug_title bug_severity retry_count infra_error_count resume_phase
|
|
1035
|
+
local bug_id bug_title bug_severity retry_count infra_error_count resume_phase active_dev_branch base_branch continuation_pending continuation_reason context_overflow_count continuation_count previous_session_id no_progress_count
|
|
995
1036
|
bug_id=$(echo "$next_bug" | jq -r '.bug_id')
|
|
996
1037
|
bug_title=$(echo "$next_bug" | jq -r '.title')
|
|
997
1038
|
bug_severity=$(echo "$next_bug" | jq -r '.severity')
|
|
998
1039
|
retry_count=$(echo "$next_bug" | jq -r '.retry_count // 0')
|
|
999
1040
|
infra_error_count=$(echo "$next_bug" | jq -r '.infra_error_count // 0')
|
|
1000
1041
|
resume_phase=$(echo "$next_bug" | jq -r '.resume_from_phase // "null"')
|
|
1042
|
+
active_dev_branch=$(echo "$next_bug" | jq -r '.active_dev_branch // ""')
|
|
1043
|
+
base_branch=$(echo "$next_bug" | jq -r '.base_branch // ""')
|
|
1044
|
+
continuation_pending=$(echo "$next_bug" | jq -r '.continuation_pending // false')
|
|
1045
|
+
continuation_reason=$(echo "$next_bug" | jq -r '.continuation_reason // ""')
|
|
1046
|
+
context_overflow_count=$(echo "$next_bug" | jq -r '.context_overflow_count // 0')
|
|
1047
|
+
continuation_count=$(echo "$next_bug" | jq -r '.continuation_count // 0')
|
|
1048
|
+
previous_session_id=$(echo "$next_bug" | jq -r '.last_context_overflow_session_id // ""')
|
|
1049
|
+
no_progress_count=$(echo "$next_bug" | jq -r '.no_progress_count // 0')
|
|
1001
1050
|
|
|
1002
1051
|
echo ""
|
|
1003
1052
|
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
@@ -1008,6 +1057,10 @@ DEPLOY_PROMPT_EOF
|
|
|
1008
1057
|
if [[ "$resume_phase" != "null" ]]; then
|
|
1009
1058
|
log_info "Resuming from Phase $resume_phase"
|
|
1010
1059
|
fi
|
|
1060
|
+
if [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1061
|
+
log_info "Continuation pending (${continuation_reason:-context_overflow}); reusing dev branch: $active_dev_branch"
|
|
1062
|
+
log_info "Continuation count: $continuation_count (context overflows: $context_overflow_count)"
|
|
1063
|
+
fi
|
|
1011
1064
|
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
1012
1065
|
|
|
1013
1066
|
# Auto-commit any uncommitted workspace changes before starting the pipeline.
|
|
@@ -1040,8 +1093,20 @@ DEPLOY_PROMPT_EOF
|
|
|
1040
1093
|
prizm_git_commit_paths "$_proj_root" "chore($bug_id): mark in_progress" "$bug_list"
|
|
1041
1094
|
fi
|
|
1042
1095
|
|
|
1043
|
-
#
|
|
1044
|
-
|
|
1096
|
+
# Continuation base branch from runtime state is authoritative for branch reuse.
|
|
1097
|
+
if [[ "$continuation_pending" == "true" && -n "$base_branch" ]]; then
|
|
1098
|
+
_ORIGINAL_BRANCH="$base_branch"
|
|
1099
|
+
fi
|
|
1100
|
+
|
|
1101
|
+
# Create or reuse per-bug dev branch (from the now-updated original branch)
|
|
1102
|
+
local _bug_branch
|
|
1103
|
+
if [[ -n "$DEV_BRANCH" ]]; then
|
|
1104
|
+
_bug_branch="$DEV_BRANCH"
|
|
1105
|
+
elif [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1106
|
+
_bug_branch="$active_dev_branch"
|
|
1107
|
+
else
|
|
1108
|
+
_bug_branch="bugfix/${bug_id}-$(date +%Y%m%d%H%M)"
|
|
1109
|
+
fi
|
|
1045
1110
|
if branch_create "$_proj_root" "$_bug_branch" "$_ORIGINAL_BRANCH"; then
|
|
1046
1111
|
_DEV_BRANCH_NAME="$_bug_branch"
|
|
1047
1112
|
log_info "Dev branch: $_bug_branch"
|
|
@@ -1051,15 +1116,17 @@ DEPLOY_PROMPT_EOF
|
|
|
1051
1116
|
break
|
|
1052
1117
|
fi
|
|
1053
1118
|
|
|
1119
|
+
while true; do
|
|
1054
1120
|
# Generate session
|
|
1055
1121
|
local session_id run_id
|
|
1056
1122
|
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
1057
1123
|
session_id="${bug_id}-$(date +%Y%m%d%H%M%S)"
|
|
1058
1124
|
|
|
1059
|
-
local session_dir="$STATE_DIR
|
|
1125
|
+
local session_dir="$STATE_DIR/$bug_id/sessions/$session_id"
|
|
1060
1126
|
mkdir -p "$session_dir/logs"
|
|
1061
1127
|
|
|
1062
1128
|
local bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
1129
|
+
local continuation_summary_path=".prizmkit/bugfix/${bug_id}/continuation-summary.md"
|
|
1063
1130
|
|
|
1064
1131
|
local main_prompt_args=(
|
|
1065
1132
|
--bug-list "$bug_list"
|
|
@@ -1072,6 +1139,19 @@ DEPLOY_PROMPT_EOF
|
|
|
1072
1139
|
--output "$bootstrap_prompt"
|
|
1073
1140
|
)
|
|
1074
1141
|
|
|
1142
|
+
if [[ "$continuation_pending" == "true" ]]; then
|
|
1143
|
+
main_prompt_args+=(
|
|
1144
|
+
--continuation-mode "${continuation_reason:-context_overflow}"
|
|
1145
|
+
--previous-session-id "$previous_session_id"
|
|
1146
|
+
--continuation-count "$continuation_count"
|
|
1147
|
+
--context-overflow-count "$context_overflow_count"
|
|
1148
|
+
--task-type "bugfix"
|
|
1149
|
+
--active-dev-branch "$active_dev_branch"
|
|
1150
|
+
--base-branch "$base_branch"
|
|
1151
|
+
--continuation-summary-path "$continuation_summary_path"
|
|
1152
|
+
)
|
|
1153
|
+
fi
|
|
1154
|
+
|
|
1075
1155
|
# Support PIPELINE_MODE env var (set by launch-bugfix-daemon.sh --mode)
|
|
1076
1156
|
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
1077
1157
|
main_prompt_args+=(--mode "$PIPELINE_MODE")
|
|
@@ -1089,7 +1169,7 @@ DEPLOY_PROMPT_EOF
|
|
|
1089
1169
|
log_error "Failed to generate bootstrap prompt for $bug_id"
|
|
1090
1170
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1091
1171
|
_DEV_BRANCH_NAME=""
|
|
1092
|
-
continue
|
|
1172
|
+
continue 2
|
|
1093
1173
|
}
|
|
1094
1174
|
local bug_model pipeline_mode agent_count critic_enabled
|
|
1095
1175
|
bug_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
@@ -1111,6 +1191,11 @@ DEPLOY_PROMPT_EOF
|
|
|
1111
1191
|
log_info "Bug model: $bug_model"
|
|
1112
1192
|
fi
|
|
1113
1193
|
|
|
1194
|
+
local continuation_artifact_dir=".prizmkit/bugfix/${bug_id}"
|
|
1195
|
+
local continuation_checkpoint_path="$continuation_artifact_dir/workflow-checkpoint.json"
|
|
1196
|
+
local progress_before progress_after
|
|
1197
|
+
progress_before=$(prizm_context_progress_fingerprint "$_proj_root" "bugfix" "$bug_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1198
|
+
|
|
1114
1199
|
# Spawn session
|
|
1115
1200
|
log_info "Spawning AI CLI session: $session_id"
|
|
1116
1201
|
_SPAWN_RESULT=""
|
|
@@ -1123,7 +1208,37 @@ DEPLOY_PROMPT_EOF
|
|
|
1123
1208
|
local session_status="$_SPAWN_RESULT"
|
|
1124
1209
|
|
|
1125
1210
|
# Merge per-bug dev branch back to original on success
|
|
1126
|
-
|
|
1211
|
+
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
1212
|
+
if [[ "$session_status" == "context_overflow" ]]; then
|
|
1213
|
+
progress_after=$(prizm_context_progress_fingerprint "$_proj_root" "bugfix" "$bug_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1214
|
+
if prizm_context_progress_changed "$progress_before" "$progress_after"; then
|
|
1215
|
+
no_progress_count=0
|
|
1216
|
+
log_info "Context-overflow session made observable progress; continuing on $_DEV_BRANCH_NAME"
|
|
1217
|
+
else
|
|
1218
|
+
no_progress_count=$((no_progress_count + 1))
|
|
1219
|
+
log_warn "Context-overflow session made no observable progress ($no_progress_count consecutive)"
|
|
1220
|
+
fi
|
|
1221
|
+
if [[ "$no_progress_count" -ge 2 ]]; then
|
|
1222
|
+
log_warn "Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress"
|
|
1223
|
+
session_status="stalled_context_continuation"
|
|
1224
|
+
else
|
|
1225
|
+
finalize_bug_status_after_branch_return \
|
|
1226
|
+
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "$progress_after"
|
|
1227
|
+
session_count=$((session_count + 1))
|
|
1228
|
+
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1229
|
+
continuation_pending="true"
|
|
1230
|
+
continuation_reason="context_overflow"
|
|
1231
|
+
previous_session_id="$session_id"
|
|
1232
|
+
active_dev_branch="$_DEV_BRANCH_NAME"
|
|
1233
|
+
base_branch="$_ORIGINAL_BRANCH"
|
|
1234
|
+
context_overflow_count=$((context_overflow_count + 1))
|
|
1235
|
+
continuation_count=$((continuation_count + 1))
|
|
1236
|
+
log_info "Launching automatic continuation for $bug_id on same branch/worktree"
|
|
1237
|
+
continue
|
|
1238
|
+
fi
|
|
1239
|
+
fi
|
|
1240
|
+
|
|
1241
|
+
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1127
1242
|
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
1128
1243
|
_DEV_BRANCH_NAME=""
|
|
1129
1244
|
else
|
|
@@ -1134,14 +1249,13 @@ DEPLOY_PROMPT_EOF
|
|
|
1134
1249
|
elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1135
1250
|
# Session failed — preserve dev branch for inspection
|
|
1136
1251
|
log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
|
|
1137
|
-
_DEV_BRANCH_NAME=""
|
|
1138
1252
|
fi
|
|
1139
1253
|
|
|
1140
1254
|
# GUARANTEED: always return to original branch regardless of success/failure/merge outcome
|
|
1141
1255
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1142
1256
|
|
|
1143
1257
|
finalize_bug_status_after_branch_return \
|
|
1144
|
-
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES"
|
|
1258
|
+
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
1145
1259
|
local item_status_after_session="${_SPAWN_ITEM_STATUS:-}"
|
|
1146
1260
|
|
|
1147
1261
|
# Commit bug status update on the original branch (after guaranteed return)
|
|
@@ -1151,6 +1265,8 @@ DEPLOY_PROMPT_EOF
|
|
|
1151
1265
|
|
|
1152
1266
|
session_count=$((session_count + 1))
|
|
1153
1267
|
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1268
|
+
break
|
|
1269
|
+
done
|
|
1154
1270
|
|
|
1155
1271
|
# Stop-on-failure: abort only after the task is actually marked failed.
|
|
1156
1272
|
# Pending retry outcomes, including infrastructure errors, keep running.
|
|
@@ -1229,8 +1345,7 @@ show_help() {
|
|
|
1229
1345
|
echo " VERBOSE Set to 1 for verbose AI CLI output"
|
|
1230
1346
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1231
1347
|
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1232
|
-
echo " MAX_LOG_SIZE
|
|
1233
|
-
echo " LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)"
|
|
1348
|
+
echo " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
|
|
1234
1349
|
echo " STOP_ON_FAILURE Stop pipeline when a task exhausts retries: 0|1 (default: 0)"
|
|
1235
1350
|
echo ""
|
|
1236
1351
|
echo "Examples:"
|
|
@@ -25,8 +25,7 @@ set -euo pipefail
|
|
|
25
25
|
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
26
26
|
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
27
27
|
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
28
|
-
# MAX_LOG_SIZE
|
|
29
|
-
# LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)
|
|
28
|
+
# MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)
|
|
30
29
|
# PIPELINE_MODE Override mode for all features: lite|standard|full (used by daemon)
|
|
31
30
|
# DEV_BRANCH Custom dev branch name (default: auto-generated dev/{feature_id}-YYYYMMDDHHmm)
|
|
32
31
|
# AUTO_PUSH Auto-push to remote after successful feature (default: 0). Set to 1 to enable.
|
|
@@ -150,6 +149,11 @@ spawn_and_wait_session() {
|
|
|
150
149
|
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
151
150
|
fi
|
|
152
151
|
|
|
152
|
+
local was_context_overflow=false
|
|
153
|
+
if prizm_detect_context_overflow_error "$session_log" "$progress_json"; then
|
|
154
|
+
was_context_overflow=true
|
|
155
|
+
fi
|
|
156
|
+
|
|
153
157
|
local was_infra_error=false
|
|
154
158
|
if [[ $exit_code -ne 0 ]] && prizm_detect_infra_error "$session_log" "$progress_json"; then
|
|
155
159
|
was_infra_error=true
|
|
@@ -187,13 +191,17 @@ spawn_and_wait_session() {
|
|
|
187
191
|
semantic_finalized=true
|
|
188
192
|
semantic_feature_slug="$PRIZM_SEMANTIC_FEATURE_SLUG"
|
|
189
193
|
semantic_commit_sha="$PRIZM_SEMANTIC_COMMIT_SHA"
|
|
190
|
-
if [[ $exit_code -ne 0 || "$was_stale_killed" == true || "$was_ai_runtime_error" == true ]]; then
|
|
194
|
+
if [[ $exit_code -ne 0 || "$was_stale_killed" == true || "$was_context_overflow" == true || "$was_ai_runtime_error" == true ]]; then
|
|
191
195
|
log_warn "Session ended with a failure signal after semantic completion; treating as finalized success"
|
|
192
196
|
log_warn "Semantic completion commit: ${semantic_commit_sha:-unknown}"
|
|
193
197
|
fi
|
|
194
198
|
session_status="success"
|
|
199
|
+
elif [[ "$was_context_overflow" == true ]]; then
|
|
200
|
+
log_warn "Session failed because the AI CLI exceeded the model context window"
|
|
201
|
+
log_warn "Context overflow is retried without consuming code retry budget"
|
|
202
|
+
session_status="context_overflow"
|
|
195
203
|
elif [[ "$was_ai_runtime_error" == true ]]; then
|
|
196
|
-
log_warn "Session failed due to structured AI runtime
|
|
204
|
+
log_warn "Session failed due to structured AI runtime error"
|
|
197
205
|
log_warn "AI runtime errors are retried without consuming code retry budget"
|
|
198
206
|
session_status="infra_error"
|
|
199
207
|
elif [[ "$was_infra_error" == true ]]; then
|
|
@@ -368,6 +376,11 @@ finalize_feature_status_after_branch_return() {
|
|
|
368
376
|
local max_infra_retries="$6"
|
|
369
377
|
local session_dir="$7"
|
|
370
378
|
local base_branch="${8:-main}"
|
|
379
|
+
local active_dev_branch="${9:-}"
|
|
380
|
+
local fatal_error_code="${10:-}"
|
|
381
|
+
local continuation_summary_path="${11:-}"
|
|
382
|
+
local no_progress_count="${12:-0}"
|
|
383
|
+
local progress_fingerprint="${13:-}"
|
|
371
384
|
|
|
372
385
|
local feature_slug="${_SPAWN_FEATURE_SLUG:-}"
|
|
373
386
|
local progress_json="$session_dir/logs/progress.json"
|
|
@@ -404,6 +417,12 @@ finalize_feature_status_after_branch_return() {
|
|
|
404
417
|
--session-id "$session_id" \
|
|
405
418
|
--max-retries "$max_retries" \
|
|
406
419
|
--max-infra-retries "$max_infra_retries" \
|
|
420
|
+
--active-dev-branch "$active_dev_branch" \
|
|
421
|
+
--base-branch "$base_branch" \
|
|
422
|
+
--last-fatal-error-code "$fatal_error_code" \
|
|
423
|
+
--continuation-summary-path "$continuation_summary_path" \
|
|
424
|
+
--no-progress-count "$no_progress_count" \
|
|
425
|
+
--progress-fingerprint "$progress_fingerprint" \
|
|
407
426
|
--action update) || {
|
|
408
427
|
log_error "Failed to update feature status: $update_output"
|
|
409
428
|
log_error ".prizmkit/plans/feature-list.json may be out of sync. Manual intervention needed."
|
|
@@ -698,7 +717,7 @@ sys.exit(1)
|
|
|
698
717
|
log_info "Removed $dev_team_dir"
|
|
699
718
|
fi
|
|
700
719
|
|
|
701
|
-
local feature_state_dir="$STATE_DIR
|
|
720
|
+
local feature_state_dir="$STATE_DIR/$feature_id"
|
|
702
721
|
if [[ -d "$feature_state_dir" ]]; then
|
|
703
722
|
rm -rf "$feature_state_dir"
|
|
704
723
|
log_info "Removed $feature_state_dir"
|
|
@@ -724,7 +743,7 @@ sys.exit(1)
|
|
|
724
743
|
local run_id session_id session_dir bootstrap_prompt
|
|
725
744
|
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
726
745
|
session_id="${feature_id}-$(date +%Y%m%d%H%M%S)"
|
|
727
|
-
session_dir="$STATE_DIR
|
|
746
|
+
session_dir="$STATE_DIR/$feature_id/sessions/$session_id"
|
|
728
747
|
mkdir -p "$session_dir/logs"
|
|
729
748
|
|
|
730
749
|
bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
@@ -733,7 +752,7 @@ sys.exit(1)
|
|
|
733
752
|
local retry_count
|
|
734
753
|
retry_count=$(python3 -c "
|
|
735
754
|
import json, os
|
|
736
|
-
status_path = os.path.join('$STATE_DIR', '
|
|
755
|
+
status_path = os.path.join('$STATE_DIR', '$feature_id', 'status.json')
|
|
737
756
|
if os.path.isfile(status_path):
|
|
738
757
|
with open(status_path) as f:
|
|
739
758
|
d = json.load(f)
|
|
@@ -916,6 +935,11 @@ else:
|
|
|
916
935
|
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$feature_model" "$_ORIGINAL_BRANCH"
|
|
917
936
|
local session_status="$_SPAWN_RESULT"
|
|
918
937
|
|
|
938
|
+
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
939
|
+
local continuation_summary_path=""
|
|
940
|
+
local no_progress_count=0
|
|
941
|
+
local progress_after=""
|
|
942
|
+
|
|
919
943
|
# Merge dev branch back to original on success
|
|
920
944
|
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
921
945
|
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
@@ -935,7 +959,7 @@ else:
|
|
|
935
959
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
936
960
|
|
|
937
961
|
finalize_feature_status_after_branch_return \
|
|
938
|
-
"$feature_id" "$feature_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$session_dir" "$_ORIGINAL_BRANCH"
|
|
962
|
+
"$feature_id" "$feature_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$session_dir" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
939
963
|
|
|
940
964
|
# Commit feature status update on the original branch (after guaranteed return)
|
|
941
965
|
if ! git -C "$_proj_root" diff --quiet "$feature_list" 2>/dev/null; then
|
|
@@ -1212,12 +1236,20 @@ DEPLOY_PROMPT_EOF
|
|
|
1212
1236
|
fi
|
|
1213
1237
|
|
|
1214
1238
|
# Parse feature info
|
|
1215
|
-
local feature_id feature_title retry_count infra_error_count resume_phase
|
|
1239
|
+
local feature_id feature_title retry_count infra_error_count resume_phase active_dev_branch base_branch continuation_pending continuation_reason context_overflow_count continuation_count previous_session_id no_progress_count
|
|
1216
1240
|
feature_id=$(echo "$next_feature" | jq -r '.feature_id')
|
|
1217
1241
|
feature_title=$(echo "$next_feature" | jq -r '.title')
|
|
1218
1242
|
retry_count=$(echo "$next_feature" | jq -r '.retry_count // 0')
|
|
1219
1243
|
infra_error_count=$(echo "$next_feature" | jq -r '.infra_error_count // 0')
|
|
1220
1244
|
resume_phase=$(echo "$next_feature" | jq -r '.resume_from_phase // "null"')
|
|
1245
|
+
active_dev_branch=$(echo "$next_feature" | jq -r '.active_dev_branch // ""')
|
|
1246
|
+
base_branch=$(echo "$next_feature" | jq -r '.base_branch // ""')
|
|
1247
|
+
continuation_pending=$(echo "$next_feature" | jq -r '.continuation_pending // false')
|
|
1248
|
+
continuation_reason=$(echo "$next_feature" | jq -r '.continuation_reason // ""')
|
|
1249
|
+
context_overflow_count=$(echo "$next_feature" | jq -r '.context_overflow_count // 0')
|
|
1250
|
+
continuation_count=$(echo "$next_feature" | jq -r '.continuation_count // 0')
|
|
1251
|
+
previous_session_id=$(echo "$next_feature" | jq -r '.last_context_overflow_session_id // ""')
|
|
1252
|
+
no_progress_count=$(echo "$next_feature" | jq -r '.no_progress_count // 0')
|
|
1221
1253
|
|
|
1222
1254
|
echo ""
|
|
1223
1255
|
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
@@ -1227,6 +1259,10 @@ DEPLOY_PROMPT_EOF
|
|
|
1227
1259
|
if [[ "$resume_phase" != "null" ]]; then
|
|
1228
1260
|
log_info "Resuming from Phase $resume_phase"
|
|
1229
1261
|
fi
|
|
1262
|
+
if [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1263
|
+
log_info "Continuation pending (${continuation_reason:-context_overflow}); reusing dev branch: $active_dev_branch"
|
|
1264
|
+
log_info "Continuation count: $continuation_count (context overflows: $context_overflow_count)"
|
|
1265
|
+
fi
|
|
1230
1266
|
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
1231
1267
|
|
|
1232
1268
|
# Auto-commit any uncommitted workspace changes before starting the pipeline.
|
|
@@ -1259,8 +1295,20 @@ DEPLOY_PROMPT_EOF
|
|
|
1259
1295
|
prizm_git_commit_paths "$_proj_root" "chore($feature_id): mark in_progress" "$feature_list"
|
|
1260
1296
|
fi
|
|
1261
1297
|
|
|
1262
|
-
#
|
|
1263
|
-
|
|
1298
|
+
# Continuation base branch from runtime state is authoritative for branch reuse.
|
|
1299
|
+
if [[ "$continuation_pending" == "true" && -n "$base_branch" ]]; then
|
|
1300
|
+
_ORIGINAL_BRANCH="$base_branch"
|
|
1301
|
+
fi
|
|
1302
|
+
|
|
1303
|
+
# Create or reuse per-feature dev branch (from the now-updated original branch)
|
|
1304
|
+
local _feature_branch
|
|
1305
|
+
if [[ -n "$DEV_BRANCH" ]]; then
|
|
1306
|
+
_feature_branch="$DEV_BRANCH"
|
|
1307
|
+
elif [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1308
|
+
_feature_branch="$active_dev_branch"
|
|
1309
|
+
else
|
|
1310
|
+
_feature_branch="dev/${feature_id}-$(date +%Y%m%d%H%M)"
|
|
1311
|
+
fi
|
|
1264
1312
|
if branch_create "$_proj_root" "$_feature_branch" "$_ORIGINAL_BRANCH"; then
|
|
1265
1313
|
_DEV_BRANCH_NAME="$_feature_branch"
|
|
1266
1314
|
log_info "Dev branch: $_feature_branch"
|
|
@@ -1270,15 +1318,33 @@ DEPLOY_PROMPT_EOF
|
|
|
1270
1318
|
break
|
|
1271
1319
|
fi
|
|
1272
1320
|
|
|
1321
|
+
while true; do
|
|
1273
1322
|
# Generate session ID and bootstrap prompt
|
|
1274
1323
|
local session_id run_id
|
|
1275
1324
|
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
1276
1325
|
session_id="${feature_id}-$(date +%Y%m%d%H%M%S)"
|
|
1277
1326
|
|
|
1278
|
-
local session_dir="$STATE_DIR
|
|
1327
|
+
local session_dir="$STATE_DIR/$feature_id/sessions/$session_id"
|
|
1279
1328
|
mkdir -p "$session_dir/logs"
|
|
1280
1329
|
|
|
1281
1330
|
local bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
1331
|
+
local continuation_summary_path
|
|
1332
|
+
continuation_summary_path=$(python3 -c "
|
|
1333
|
+
import json, re, sys
|
|
1334
|
+
feature_list, feature_id = sys.argv[1], sys.argv[2]
|
|
1335
|
+
with open(feature_list) as f:
|
|
1336
|
+
data = json.load(f)
|
|
1337
|
+
for feature in data.get('features', []):
|
|
1338
|
+
if feature.get('id') == feature_id:
|
|
1339
|
+
numeric = feature_id.replace('F-', '').replace('f-', '').zfill(3)
|
|
1340
|
+
title = feature.get('title', '').lower()
|
|
1341
|
+
title = re.sub(r'[^a-z0-9\s-]', '', title)
|
|
1342
|
+
title = re.sub(r'[\s]+', '-', title.strip())
|
|
1343
|
+
title = re.sub(r'-+', '-', title).strip('-')
|
|
1344
|
+
print(f'.prizmkit/specs/{numeric}-{title}/continuation-summary.md')
|
|
1345
|
+
sys.exit(0)
|
|
1346
|
+
sys.exit(1)
|
|
1347
|
+
" "$feature_list" "$feature_id" 2>/dev/null || echo "")
|
|
1282
1348
|
|
|
1283
1349
|
local main_prompt_args=(
|
|
1284
1350
|
--feature-list "$feature_list"
|
|
@@ -1291,6 +1357,21 @@ DEPLOY_PROMPT_EOF
|
|
|
1291
1357
|
--output "$bootstrap_prompt"
|
|
1292
1358
|
)
|
|
1293
1359
|
|
|
1360
|
+
if [[ "$continuation_pending" == "true" ]]; then
|
|
1361
|
+
main_prompt_args+=(
|
|
1362
|
+
--continuation-mode "${continuation_reason:-context_overflow}"
|
|
1363
|
+
--previous-session-id "$previous_session_id"
|
|
1364
|
+
--continuation-count "$continuation_count"
|
|
1365
|
+
--context-overflow-count "$context_overflow_count"
|
|
1366
|
+
--task-type "feature"
|
|
1367
|
+
--active-dev-branch "$active_dev_branch"
|
|
1368
|
+
--base-branch "$base_branch"
|
|
1369
|
+
)
|
|
1370
|
+
if [[ -n "$continuation_summary_path" ]]; then
|
|
1371
|
+
main_prompt_args+=(--continuation-summary-path "$continuation_summary_path")
|
|
1372
|
+
fi
|
|
1373
|
+
fi
|
|
1374
|
+
|
|
1294
1375
|
# Support PIPELINE_MODE env var (set by launch-feature-daemon.sh --mode)
|
|
1295
1376
|
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
1296
1377
|
main_prompt_args+=(--mode "$PIPELINE_MODE")
|
|
@@ -1308,7 +1389,7 @@ DEPLOY_PROMPT_EOF
|
|
|
1308
1389
|
log_error "Failed to generate bootstrap prompt for $feature_id"
|
|
1309
1390
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1310
1391
|
_DEV_BRANCH_NAME=""
|
|
1311
|
-
continue
|
|
1392
|
+
continue 2
|
|
1312
1393
|
}
|
|
1313
1394
|
local feature_model pipeline_mode agent_count critic_enabled
|
|
1314
1395
|
feature_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
@@ -1327,6 +1408,11 @@ DEPLOY_PROMPT_EOF
|
|
|
1327
1408
|
log_info "Pipeline mode: ${BOLD}$pipeline_mode${NC} ($_mode_desc)"
|
|
1328
1409
|
log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
|
|
1329
1410
|
|
|
1411
|
+
local continuation_artifact_dir="${continuation_summary_path%/continuation-summary.md}"
|
|
1412
|
+
local continuation_checkpoint_path="$continuation_artifact_dir/workflow-checkpoint.json"
|
|
1413
|
+
local progress_before progress_after
|
|
1414
|
+
progress_before=$(prizm_context_progress_fingerprint "$_proj_root" "feature" "$feature_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1415
|
+
|
|
1330
1416
|
# Spawn session and wait
|
|
1331
1417
|
prizm_log_bootstrap_prompt "$bootstrap_prompt" "$feature_id"
|
|
1332
1418
|
log_info "Spawning AI CLI session: $session_id"
|
|
@@ -1342,7 +1428,37 @@ DEPLOY_PROMPT_EOF
|
|
|
1342
1428
|
local session_status="$_SPAWN_RESULT"
|
|
1343
1429
|
|
|
1344
1430
|
# Merge per-feature dev branch back to original on success
|
|
1345
|
-
|
|
1431
|
+
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
1432
|
+
if [[ "$session_status" == "context_overflow" ]]; then
|
|
1433
|
+
progress_after=$(prizm_context_progress_fingerprint "$_proj_root" "feature" "$feature_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1434
|
+
if prizm_context_progress_changed "$progress_before" "$progress_after"; then
|
|
1435
|
+
no_progress_count=0
|
|
1436
|
+
log_info "Context-overflow session made observable progress; continuing on $_DEV_BRANCH_NAME"
|
|
1437
|
+
else
|
|
1438
|
+
no_progress_count=$((no_progress_count + 1))
|
|
1439
|
+
log_warn "Context-overflow session made no observable progress ($no_progress_count consecutive)"
|
|
1440
|
+
fi
|
|
1441
|
+
if [[ "$no_progress_count" -ge 2 ]]; then
|
|
1442
|
+
log_warn "Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress"
|
|
1443
|
+
session_status="stalled_context_continuation"
|
|
1444
|
+
else
|
|
1445
|
+
finalize_feature_status_after_branch_return \
|
|
1446
|
+
"$feature_id" "$feature_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$session_dir" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "$progress_after"
|
|
1447
|
+
session_count=$((session_count + 1))
|
|
1448
|
+
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1449
|
+
continuation_pending="true"
|
|
1450
|
+
continuation_reason="context_overflow"
|
|
1451
|
+
previous_session_id="$session_id"
|
|
1452
|
+
active_dev_branch="$_DEV_BRANCH_NAME"
|
|
1453
|
+
base_branch="$_ORIGINAL_BRANCH"
|
|
1454
|
+
context_overflow_count=$((context_overflow_count + 1))
|
|
1455
|
+
continuation_count=$((continuation_count + 1))
|
|
1456
|
+
log_info "Launching automatic continuation for $feature_id on same branch/worktree"
|
|
1457
|
+
continue
|
|
1458
|
+
fi
|
|
1459
|
+
fi
|
|
1460
|
+
|
|
1461
|
+
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1346
1462
|
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
1347
1463
|
_DEV_BRANCH_NAME=""
|
|
1348
1464
|
else
|
|
@@ -1353,14 +1469,13 @@ DEPLOY_PROMPT_EOF
|
|
|
1353
1469
|
elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1354
1470
|
# Session failed — preserve dev branch for inspection
|
|
1355
1471
|
log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
|
|
1356
|
-
_DEV_BRANCH_NAME=""
|
|
1357
1472
|
fi
|
|
1358
1473
|
|
|
1359
1474
|
# GUARANTEED: always return to original branch regardless of success/failure/merge outcome
|
|
1360
1475
|
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1361
1476
|
|
|
1362
1477
|
finalize_feature_status_after_branch_return \
|
|
1363
|
-
"$feature_id" "$feature_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$session_dir" "$_ORIGINAL_BRANCH"
|
|
1478
|
+
"$feature_id" "$feature_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$session_dir" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
1364
1479
|
local item_status_after_session="${_SPAWN_ITEM_STATUS:-}"
|
|
1365
1480
|
|
|
1366
1481
|
# Commit feature status update on the original branch (after guaranteed return)
|
|
@@ -1370,6 +1485,8 @@ DEPLOY_PROMPT_EOF
|
|
|
1370
1485
|
|
|
1371
1486
|
session_count=$((session_count + 1))
|
|
1372
1487
|
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1488
|
+
break
|
|
1489
|
+
done
|
|
1373
1490
|
|
|
1374
1491
|
# Stop-on-failure: abort only after the task is actually marked failed.
|
|
1375
1492
|
# Pending retry outcomes keep running; both code and infra failures have
|
|
@@ -1435,8 +1552,7 @@ show_help() {
|
|
|
1435
1552
|
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1436
1553
|
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1437
1554
|
echo " HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)"
|
|
1438
|
-
echo " MAX_LOG_SIZE
|
|
1439
|
-
echo " LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)"
|
|
1555
|
+
echo " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
|
|
1440
1556
|
echo " PIPELINE_MODE Override mode for all features: lite|standard|full"
|
|
1441
1557
|
echo " ENABLE_CRITIC Enable critic review for all features: true|false"
|
|
1442
1558
|
echo " STOP_ON_FAILURE Stop pipeline when a task exhausts retries: 0|1 (default: 0)"
|