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.
Files changed (79) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/README.md +5 -5
  3. package/bundled/dev-pipeline/launch-bugfix-daemon.sh +1 -1
  4. package/bundled/dev-pipeline/launch-feature-daemon.sh +1 -1
  5. package/bundled/dev-pipeline/launch-refactor-daemon.sh +1 -1
  6. package/bundled/dev-pipeline/lib/common.sh +244 -25
  7. package/bundled/dev-pipeline/reset-bug.sh +32 -2
  8. package/bundled/dev-pipeline/reset-feature.sh +32 -2
  9. package/bundled/dev-pipeline/reset-refactor.sh +32 -2
  10. package/bundled/dev-pipeline/run-bugfix.sh +133 -18
  11. package/bundled/dev-pipeline/run-feature.sh +134 -18
  12. package/bundled/dev-pipeline/run-refactor.sh +133 -18
  13. package/bundled/dev-pipeline/scripts/check-session-status.py +74 -1
  14. package/bundled/dev-pipeline/scripts/continuation.py +374 -0
  15. package/bundled/dev-pipeline/scripts/detect-stuck.py +5 -5
  16. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +29 -35
  17. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +19 -25
  18. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +19 -25
  19. package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +1 -1
  20. package/bundled/dev-pipeline/scripts/init-pipeline.py +1 -1
  21. package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +1 -1
  22. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +146 -16
  23. package/bundled/dev-pipeline/scripts/update-bug-status.py +220 -13
  24. package/bundled/dev-pipeline/scripts/update-feature-status.py +244 -18
  25. package/bundled/dev-pipeline/scripts/update-refactor-status.py +220 -13
  26. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +1 -1
  27. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +2 -2
  28. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +3 -3
  29. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +3 -3
  30. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
  31. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
  32. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +31 -66
  33. package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
  34. package/bundled/dev-pipeline/tests/conftest.py +1 -0
  35. package/bundled/dev-pipeline/tests/test_auto_skip.py +518 -8
  36. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +103 -0
  37. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +60 -0
  38. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +43 -0
  39. package/bundled/dev-pipeline-windows/lib/common.ps1 +172 -10
  40. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +95 -11
  41. package/bundled/dev-pipeline-windows/lib/reset.ps1 +34 -0
  42. package/bundled/dev-pipeline-windows/reset-bug.ps1 +1 -0
  43. package/bundled/dev-pipeline-windows/reset-feature.ps1 +1 -0
  44. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +1 -0
  45. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +74 -1
  46. package/bundled/dev-pipeline-windows/scripts/continuation.py +374 -0
  47. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +5 -5
  48. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +29 -35
  49. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +20 -25
  50. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +20 -25
  51. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +1 -1
  52. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +1 -1
  53. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +1 -1
  54. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +146 -16
  55. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +220 -13
  56. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +244 -18
  57. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +220 -13
  58. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +1 -1
  59. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +2 -2
  60. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +3 -3
  61. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +3 -3
  62. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +1 -1
  63. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +3 -3
  64. package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +31 -68
  65. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +1 -1
  66. package/bundled/skills/_metadata.json +1 -1
  67. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +2 -2
  68. package/bundled/skills/feature-pipeline-launcher/SKILL.md +2 -2
  69. package/bundled/skills/recovery-workflow/SKILL.md +2 -2
  70. package/bundled/skills/recovery-workflow/evals/evals.json +2 -2
  71. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +2 -2
  72. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +2 -2
  73. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +2 -2
  74. package/bundled/skills-windows/recovery-workflow/SKILL.md +2 -2
  75. package/bundled/skills-windows/recovery-workflow/evals/evals.json +2 -2
  76. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +2 -2
  77. package/package.json +1 -1
  78. package/bundled/dev-pipeline/scripts/monitor-log.sh +0 -104
  79. 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 Session log size threshold for compact warning (default: 2097152 = 2MB, set 0 to disable)
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 refactor/pipeline-{run_id})
29
28
  # AUTO_PUSH Auto-push to remote after successful refactor (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.
@@ -140,6 +139,16 @@ spawn_and_wait_session() {
140
139
  log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
141
140
  fi
142
141
 
142
+ local was_context_overflow=false
143
+ if prizm_detect_context_overflow_error "$session_log" "$progress_json"; then
144
+ was_context_overflow=true
145
+ fi
146
+
147
+ local was_ai_runtime_error=false
148
+ if prizm_detect_ai_runtime_error "$session_log" "$progress_json"; then
149
+ was_ai_runtime_error=true
150
+ fi
151
+
143
152
  local was_infra_error=false
144
153
  if [[ $exit_code -ne 0 ]] && prizm_detect_infra_error "$session_log" "$progress_json"; then
145
154
  was_infra_error=true
@@ -163,7 +172,22 @@ spawn_and_wait_session() {
163
172
  project_root="$PROJECT_ROOT"
164
173
  local default_branch="$base_branch"
165
174
 
166
- if [[ "$was_infra_error" == true ]]; then
175
+ local has_commits=""
176
+ if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
177
+ has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
178
+ fi
179
+
180
+ if [[ -n "$has_commits" ]]; then
181
+ session_status="success"
182
+ elif [[ "$was_context_overflow" == true ]]; then
183
+ log_warn "Session failed because the AI CLI exceeded the model context window"
184
+ log_warn "Context overflow is retried without consuming code retry budget"
185
+ session_status="context_overflow"
186
+ elif [[ "$was_ai_runtime_error" == true ]]; then
187
+ log_warn "Session failed due to structured AI runtime error"
188
+ log_warn "AI runtime errors are retried without consuming code retry budget"
189
+ session_status="infra_error"
190
+ elif [[ "$was_infra_error" == true ]]; then
167
191
  log_warn "Session failed due to AI CLI/provider infrastructure error"
168
192
  log_warn "Infrastructure errors are retried without consuming code retry budget"
169
193
  session_status="infra_error"
@@ -299,6 +323,12 @@ finalize_refactor_status_after_branch_return() {
299
323
  local session_status="$4"
300
324
  local max_retries="$5"
301
325
  local max_infra_retries="$6"
326
+ local base_branch="${7:-main}"
327
+ local active_dev_branch="${8:-}"
328
+ local fatal_error_code="${9:-}"
329
+ local continuation_summary_path="${10:-}"
330
+ local no_progress_count="${11:-0}"
331
+ local progress_fingerprint="${12:-}"
302
332
 
303
333
  # Update refactor status on the original branch. The caller commits the
304
334
  # resulting refactor-list diff immediately after this helper returns.
@@ -311,6 +341,12 @@ finalize_refactor_status_after_branch_return() {
311
341
  --session-id "$session_id" \
312
342
  --max-retries "$max_retries" \
313
343
  --max-infra-retries "$max_infra_retries" \
344
+ --active-dev-branch "$active_dev_branch" \
345
+ --base-branch "$base_branch" \
346
+ --last-fatal-error-code "$fatal_error_code" \
347
+ --continuation-summary-path "$continuation_summary_path" \
348
+ --no-progress-count "$no_progress_count" \
349
+ --progress-fingerprint "$progress_fingerprint" \
314
350
  --action update) || {
315
351
  log_error "Failed to update refactor status: $update_output"
316
352
  update_output=""
@@ -544,7 +580,7 @@ sys.exit(1)
544
580
  log_info "Removed $dev_team_dir"
545
581
  fi
546
582
 
547
- local refactor_state_dir="$STATE_DIR/refactors/$refactor_id"
583
+ local refactor_state_dir="$STATE_DIR/$refactor_id"
548
584
  if [[ -d "$refactor_state_dir" ]]; then
549
585
  rm -rf "$refactor_state_dir"
550
586
  log_info "Removed $refactor_state_dir"
@@ -569,7 +605,7 @@ sys.exit(1)
569
605
  local run_id session_id session_dir bootstrap_prompt
570
606
  run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
571
607
  session_id="${refactor_id}-$(date +%Y%m%d%H%M%S)"
572
- session_dir="$STATE_DIR/refactors/$refactor_id/sessions/$session_id"
608
+ session_dir="$STATE_DIR/$refactor_id/sessions/$session_id"
573
609
  mkdir -p "$session_dir/logs"
574
610
 
575
611
  bootstrap_prompt="$session_dir/bootstrap-prompt.md"
@@ -578,7 +614,7 @@ sys.exit(1)
578
614
  local retry_count
579
615
  retry_count=$(python3 -c "
580
616
  import json, os
581
- status_path = os.path.join('$STATE_DIR', 'refactors', '$refactor_id', 'status.json')
617
+ status_path = os.path.join('$STATE_DIR', '$refactor_id', 'status.json')
582
618
  if os.path.isfile(status_path):
583
619
  with open(status_path) as f:
584
620
  d = json.load(f)
@@ -589,7 +625,7 @@ else:
589
625
  local resume_phase
590
626
  resume_phase=$(python3 -c "
591
627
  import json, os
592
- status_path = os.path.join('$STATE_DIR', 'refactors', '$refactor_id', 'status.json')
628
+ status_path = os.path.join('$STATE_DIR', '$refactor_id', 'status.json')
593
629
  if os.path.isfile(status_path):
594
630
  with open(status_path) as f:
595
631
  d = json.load(f)
@@ -751,6 +787,11 @@ else:
751
787
  "$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$refactor_model" "$_ORIGINAL_BRANCH"
752
788
  local session_status="$_SPAWN_RESULT"
753
789
 
790
+ local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
791
+ local continuation_summary_path=""
792
+ local no_progress_count=0
793
+ local progress_after=""
794
+
754
795
  # Merge dev branch back to original on success
755
796
  if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
756
797
  if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
@@ -770,7 +811,7 @@ else:
770
811
  branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
771
812
 
772
813
  finalize_refactor_status_after_branch_return \
773
- "$refactor_id" "$refactor_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES"
814
+ "$refactor_id" "$refactor_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:-}"
774
815
 
775
816
  # Commit refactor status update on the original branch (after guaranteed return)
776
817
  if ! git -C "$_proj_root" diff --quiet "$refactor_list" 2>/dev/null; then
@@ -1024,13 +1065,21 @@ DEPLOY_PROMPT_EOF
1024
1065
  fi
1025
1066
 
1026
1067
  # Parse refactor info
1027
- local refactor_id refactor_title refactor_complexity retry_count infra_error_count resume_phase
1068
+ local refactor_id refactor_title refactor_complexity 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
1028
1069
  refactor_id=$(echo "$next_refactor" | jq -r '.refactor_id')
1029
1070
  refactor_title=$(echo "$next_refactor" | jq -r '.title')
1030
1071
  refactor_complexity=$(echo "$next_refactor" | jq -r '.complexity')
1031
1072
  retry_count=$(echo "$next_refactor" | jq -r '.retry_count // 0')
1032
1073
  infra_error_count=$(echo "$next_refactor" | jq -r '.infra_error_count // 0')
1033
1074
  resume_phase=$(echo "$next_refactor" | jq -r '.resume_from_phase // "null"')
1075
+ active_dev_branch=$(echo "$next_refactor" | jq -r '.active_dev_branch // ""')
1076
+ base_branch=$(echo "$next_refactor" | jq -r '.base_branch // ""')
1077
+ continuation_pending=$(echo "$next_refactor" | jq -r '.continuation_pending // false')
1078
+ continuation_reason=$(echo "$next_refactor" | jq -r '.continuation_reason // ""')
1079
+ context_overflow_count=$(echo "$next_refactor" | jq -r '.context_overflow_count // 0')
1080
+ continuation_count=$(echo "$next_refactor" | jq -r '.continuation_count // 0')
1081
+ previous_session_id=$(echo "$next_refactor" | jq -r '.last_context_overflow_session_id // ""')
1082
+ no_progress_count=$(echo "$next_refactor" | jq -r '.no_progress_count // 0')
1034
1083
 
1035
1084
  echo ""
1036
1085
  echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
@@ -1041,6 +1090,10 @@ DEPLOY_PROMPT_EOF
1041
1090
  if [[ "$resume_phase" != "null" ]]; then
1042
1091
  log_info "Resuming from Phase $resume_phase"
1043
1092
  fi
1093
+ if [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
1094
+ log_info "Continuation pending (${continuation_reason:-context_overflow}); reusing dev branch: $active_dev_branch"
1095
+ log_info "Continuation count: $continuation_count (context overflows: $context_overflow_count)"
1096
+ fi
1044
1097
  echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
1045
1098
 
1046
1099
  # Auto-commit any uncommitted workspace changes before starting the pipeline.
@@ -1073,8 +1126,20 @@ DEPLOY_PROMPT_EOF
1073
1126
  prizm_git_commit_paths "$_proj_root" "chore($refactor_id): mark in_progress" "$refactor_list"
1074
1127
  fi
1075
1128
 
1076
- # Create per-refactor dev branch (from the now-updated original branch)
1077
- local _refactor_branch="${DEV_BRANCH:-refactor/${refactor_id}-$(date +%Y%m%d%H%M)}"
1129
+ # Continuation base branch from runtime state is authoritative for branch reuse.
1130
+ if [[ "$continuation_pending" == "true" && -n "$base_branch" ]]; then
1131
+ _ORIGINAL_BRANCH="$base_branch"
1132
+ fi
1133
+
1134
+ # Create or reuse per-refactor dev branch (from the now-updated original branch)
1135
+ local _refactor_branch
1136
+ if [[ -n "$DEV_BRANCH" ]]; then
1137
+ _refactor_branch="$DEV_BRANCH"
1138
+ elif [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
1139
+ _refactor_branch="$active_dev_branch"
1140
+ else
1141
+ _refactor_branch="refactor/${refactor_id}-$(date +%Y%m%d%H%M)"
1142
+ fi
1078
1143
  if branch_create "$_proj_root" "$_refactor_branch" "$_ORIGINAL_BRANCH"; then
1079
1144
  _DEV_BRANCH_NAME="$_refactor_branch"
1080
1145
  log_info "Dev branch: $_refactor_branch"
@@ -1084,15 +1149,17 @@ DEPLOY_PROMPT_EOF
1084
1149
  break
1085
1150
  fi
1086
1151
 
1152
+ while true; do
1087
1153
  # Generate session
1088
1154
  local session_id run_id
1089
1155
  run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
1090
1156
  session_id="${refactor_id}-$(date +%Y%m%d%H%M%S)"
1091
1157
 
1092
- local session_dir="$STATE_DIR/refactors/$refactor_id/sessions/$session_id"
1158
+ local session_dir="$STATE_DIR/$refactor_id/sessions/$session_id"
1093
1159
  mkdir -p "$session_dir/logs"
1094
1160
 
1095
1161
  local bootstrap_prompt="$session_dir/bootstrap-prompt.md"
1162
+ local continuation_summary_path=".prizmkit/refactor/${refactor_id}/continuation-summary.md"
1096
1163
 
1097
1164
  local main_prompt_args=(
1098
1165
  --refactor-list "$refactor_list"
@@ -1105,6 +1172,19 @@ DEPLOY_PROMPT_EOF
1105
1172
  --output "$bootstrap_prompt"
1106
1173
  )
1107
1174
 
1175
+ if [[ "$continuation_pending" == "true" ]]; then
1176
+ main_prompt_args+=(
1177
+ --continuation-mode "${continuation_reason:-context_overflow}"
1178
+ --previous-session-id "$previous_session_id"
1179
+ --continuation-count "$continuation_count"
1180
+ --context-overflow-count "$context_overflow_count"
1181
+ --task-type "refactor"
1182
+ --active-dev-branch "$active_dev_branch"
1183
+ --base-branch "$base_branch"
1184
+ --continuation-summary-path "$continuation_summary_path"
1185
+ )
1186
+ fi
1187
+
1108
1188
  # Support PIPELINE_MODE env var (set by launch-refactor-daemon.sh --mode)
1109
1189
  if [[ -n "${PIPELINE_MODE:-}" ]]; then
1110
1190
  main_prompt_args+=(--mode "$PIPELINE_MODE")
@@ -1122,7 +1202,7 @@ DEPLOY_PROMPT_EOF
1122
1202
  log_error "Failed to generate bootstrap prompt for $refactor_id"
1123
1203
  branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
1124
1204
  _DEV_BRANCH_NAME=""
1125
- continue
1205
+ continue 2
1126
1206
  }
1127
1207
  local refactor_model pipeline_mode agent_count critic_enabled
1128
1208
  refactor_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
@@ -1145,6 +1225,11 @@ DEPLOY_PROMPT_EOF
1145
1225
  log_info "Refactor model: $refactor_model"
1146
1226
  fi
1147
1227
 
1228
+ local continuation_artifact_dir=".prizmkit/refactor/${refactor_id}"
1229
+ local continuation_checkpoint_path="$continuation_artifact_dir/workflow-checkpoint.json"
1230
+ local progress_before progress_after
1231
+ progress_before=$(prizm_context_progress_fingerprint "$_proj_root" "refactor" "$refactor_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
1232
+
1148
1233
  # Spawn session
1149
1234
  log_info "Spawning AI CLI session: $session_id"
1150
1235
  _SPAWN_RESULT=""
@@ -1167,7 +1252,37 @@ DEPLOY_PROMPT_EOF
1167
1252
  local session_status="$_SPAWN_RESULT"
1168
1253
 
1169
1254
  # Merge per-refactor dev branch back to original on success
1170
- if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
1255
+ local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
1256
+ if [[ "$session_status" == "context_overflow" ]]; then
1257
+ progress_after=$(prizm_context_progress_fingerprint "$_proj_root" "refactor" "$refactor_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
1258
+ if prizm_context_progress_changed "$progress_before" "$progress_after"; then
1259
+ no_progress_count=0
1260
+ log_info "Context-overflow session made observable progress; continuing on $_DEV_BRANCH_NAME"
1261
+ else
1262
+ no_progress_count=$((no_progress_count + 1))
1263
+ log_warn "Context-overflow session made no observable progress ($no_progress_count consecutive)"
1264
+ fi
1265
+ if [[ "$no_progress_count" -ge 2 ]]; then
1266
+ log_warn "Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress"
1267
+ session_status="stalled_context_continuation"
1268
+ else
1269
+ finalize_refactor_status_after_branch_return \
1270
+ "$refactor_id" "$refactor_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"
1271
+ session_count=$((session_count + 1))
1272
+ total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
1273
+ continuation_pending="true"
1274
+ continuation_reason="context_overflow"
1275
+ previous_session_id="$session_id"
1276
+ active_dev_branch="$_DEV_BRANCH_NAME"
1277
+ base_branch="$_ORIGINAL_BRANCH"
1278
+ context_overflow_count=$((context_overflow_count + 1))
1279
+ continuation_count=$((continuation_count + 1))
1280
+ log_info "Launching automatic continuation for $refactor_id on same branch/worktree"
1281
+ continue
1282
+ fi
1283
+ fi
1284
+
1285
+ if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
1171
1286
  if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
1172
1287
  _DEV_BRANCH_NAME=""
1173
1288
  else
@@ -1178,14 +1293,13 @@ DEPLOY_PROMPT_EOF
1178
1293
  elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
1179
1294
  # Session failed — preserve dev branch for inspection
1180
1295
  log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
1181
- _DEV_BRANCH_NAME=""
1182
1296
  fi
1183
1297
 
1184
1298
  # GUARANTEED: always return to original branch regardless of success/failure/merge outcome
1185
1299
  branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
1186
1300
 
1187
1301
  finalize_refactor_status_after_branch_return \
1188
- "$refactor_id" "$refactor_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES"
1302
+ "$refactor_id" "$refactor_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:-}"
1189
1303
  local item_status_after_session="${_SPAWN_ITEM_STATUS:-}"
1190
1304
 
1191
1305
  # Commit refactor status update on the original branch (after guaranteed return)
@@ -1205,6 +1319,8 @@ DEPLOY_PROMPT_EOF
1205
1319
 
1206
1320
  session_count=$((session_count + 1))
1207
1321
  total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
1322
+ break
1323
+ done
1208
1324
 
1209
1325
  # Stop-on-failure: abort only after the task is actually marked failed.
1210
1326
  # Pending retry outcomes, including infrastructure errors, keep running.
@@ -1263,8 +1379,7 @@ show_help() {
1263
1379
  echo " STRICT_BEHAVIOR_CHECK Force full test suite after each refactor (default: 1)"
1264
1380
  echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
1265
1381
  echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
1266
- echo " MAX_LOG_SIZE Session log size threshold for compact warning (default: 2097152 = 2MB, set 0 to disable)"
1267
- echo " LOG_MONITOR_POLL_INTERVAL Log monitor poll interval in seconds (default: 30)"
1382
+ echo " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
1268
1383
  echo " STOP_ON_FAILURE Stop pipeline when a task exhausts retries: 0|1 (default: 0)"
1269
1384
  echo ""
1270
1385
  echo "Examples:"
@@ -22,6 +22,77 @@ ID_FIELDS = ["feature_id", "bug_id", "refactor_id"]
22
22
 
23
23
  LOGGER = setup_logging("check-session-status")
24
24
 
25
+ CONTEXT_OVERFLOW_CODE = "context_overflow"
26
+ CONTEXT_CODE_VALUES = {
27
+ "context_overflow",
28
+ "context_too_large",
29
+ "context_length_exceeded",
30
+ "model_context_window_exceeded",
31
+ }
32
+ CONTEXT_TEXT_PATTERNS = (
33
+ "input exceeds the context window",
34
+ "context window of this model",
35
+ "context window exceeded",
36
+ "maximum context length exceeded",
37
+ "prompt is too long",
38
+ "too many tokens",
39
+ "input token count exceeds",
40
+ )
41
+ REQUEST_TOO_LARGE_TEXT = "request too large"
42
+ REQUEST_TOO_LARGE_SEMANTICS = ("context", "token", "tokens", "prompt", "input", "model")
43
+ ERROR_LIKE_STATUSES = {"failed", "crashed", "timed_out", "context_overflow"}
44
+
45
+
46
+ def _flatten_values(value):
47
+ if isinstance(value, dict):
48
+ values = []
49
+ for child in value.values():
50
+ values.extend(_flatten_values(child))
51
+ return values
52
+ if isinstance(value, list):
53
+ values = []
54
+ for child in value:
55
+ values.extend(_flatten_values(child))
56
+ return values
57
+ if value is None:
58
+ return []
59
+ return [str(value)]
60
+
61
+
62
+ def _is_error_like_status(data):
63
+ status = str(data.get("status", "")).lower()
64
+ if status in ERROR_LIKE_STATUSES:
65
+ return True
66
+ if data.get("last_result_is_error") is True or data.get("is_error") is True:
67
+ return True
68
+ if data.get("api_error_status") not in (None, ""):
69
+ return True
70
+ errors = data.get("errors")
71
+ return isinstance(errors, list) and len(errors) > 0
72
+
73
+
74
+ def has_context_overflow_signal(data):
75
+ """Return true when session-status data carries a context overflow signal.
76
+
77
+ Success remains success: direct status handling happens before this helper.
78
+ Exact machine codes are accepted only from structured code fields. Natural
79
+ language context/token phrases require a failed/error-like status or an
80
+ explicit error field to avoid prompt/documentation false positives.
81
+ """
82
+ if not isinstance(data, dict):
83
+ return False
84
+ for field in ("fatal_error_code", "api_error_code", "error_code", "stop_reason"):
85
+ value = data.get(field)
86
+ if isinstance(value, str) and value.lower() in CONTEXT_CODE_VALUES:
87
+ return True
88
+ if not _is_error_like_status(data):
89
+ return False
90
+ text = " ".join(_flatten_values(data)).lower()
91
+ if any(pattern in text for pattern in CONTEXT_TEXT_PATTERNS):
92
+ return True
93
+ return REQUEST_TOO_LARGE_TEXT in text and any(
94
+ semantic in text for semantic in REQUEST_TOO_LARGE_SEMANTICS
95
+ )
25
96
 
26
97
  def parse_args():
27
98
  parser = argparse.ArgumentParser(
@@ -79,12 +150,14 @@ def determine_status(data):
79
150
  """Determine the single-line status string from the parsed data.
80
151
 
81
152
  Returns one of: success, partial_resumable, partial_not_resumable,
82
- failed, commit_missing, docs_missing, merge_conflict.
153
+ failed, commit_missing, docs_missing, merge_conflict, context_overflow.
83
154
  """
84
155
  status = data.get("status", "")
85
156
 
86
157
  if status == "success":
87
158
  return "success"
159
+ if status == "context_overflow" or has_context_overflow_signal(data):
160
+ return "context_overflow"
88
161
  elif status == "partial":
89
162
  can_resume = data.get("can_resume", False)
90
163
  if can_resume: