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
|
@@ -42,6 +42,8 @@ SESSION_STATUS_VALUES = [
|
|
|
42
42
|
"crashed",
|
|
43
43
|
"timed_out",
|
|
44
44
|
"infra_error",
|
|
45
|
+
"context_overflow",
|
|
46
|
+
"stalled_context_continuation",
|
|
45
47
|
"commit_missing",
|
|
46
48
|
"docs_missing",
|
|
47
49
|
"merge_conflict",
|
|
@@ -78,6 +80,12 @@ def parse_args():
|
|
|
78
80
|
parser.add_argument("--max-retries", type=int, default=3, help="Maximum code retry count (default: 3)")
|
|
79
81
|
parser.add_argument("--max-infra-retries", type=int, default=3, help="Maximum infrastructure retry count (default: 3)")
|
|
80
82
|
parser.add_argument("--project-root", default=None, help="Project root directory. Required for 'clean' action.")
|
|
83
|
+
parser.add_argument("--active-dev-branch", default=None, help="Development branch preserved for continuation after context overflow.")
|
|
84
|
+
parser.add_argument("--base-branch", default=None, help="Original/base branch for continuation branch reuse.")
|
|
85
|
+
parser.add_argument("--last-fatal-error-code", default=None, help="Fatal runtime error code associated with continuation.")
|
|
86
|
+
parser.add_argument("--continuation-summary-path", default=None, help="Optional continuation summary artifact path.")
|
|
87
|
+
parser.add_argument("--no-progress-count", type=int, default=None, help="Consecutive context-overflow sessions without objective progress.")
|
|
88
|
+
parser.add_argument("--progress-fingerprint", default=None, help="JSON progress fingerprint captured after the session.")
|
|
81
89
|
return parser.parse_args()
|
|
82
90
|
|
|
83
91
|
|
|
@@ -92,7 +100,7 @@ def load_bug_status(state_dir, bug_id):
|
|
|
92
100
|
The 'status' field is NOT included — status lives exclusively
|
|
93
101
|
in bug-fix-list.json.
|
|
94
102
|
"""
|
|
95
|
-
status_path = os.path.join(state_dir,
|
|
103
|
+
status_path = os.path.join(state_dir, bug_id, "status.json")
|
|
96
104
|
if not os.path.isfile(status_path):
|
|
97
105
|
now = now_iso()
|
|
98
106
|
return {
|
|
@@ -133,7 +141,7 @@ def save_bug_status(state_dir, bug_id, status_data):
|
|
|
133
141
|
"""Write the status.json for a bug (runtime fields only)."""
|
|
134
142
|
# Defensively strip status — it belongs in bug-fix-list.json
|
|
135
143
|
status_data.pop("status", None)
|
|
136
|
-
status_path = os.path.join(state_dir,
|
|
144
|
+
status_path = os.path.join(state_dir, bug_id, "status.json")
|
|
137
145
|
return write_json_file(status_path, status_data)
|
|
138
146
|
|
|
139
147
|
|
|
@@ -164,6 +172,128 @@ def update_bug_in_list(bug_list_path, bug_id, new_status):
|
|
|
164
172
|
return write_json_file(bug_list_path, data)
|
|
165
173
|
|
|
166
174
|
|
|
175
|
+
CONTINUATION_PENDING_FIELDS = [
|
|
176
|
+
"active_dev_branch",
|
|
177
|
+
"base_branch",
|
|
178
|
+
"continuation_pending",
|
|
179
|
+
"continuation_reason",
|
|
180
|
+
"last_context_overflow_session_id",
|
|
181
|
+
"previous_session_id",
|
|
182
|
+
"last_fatal_error_code",
|
|
183
|
+
"continuation_summary_path",
|
|
184
|
+
"no_progress_count",
|
|
185
|
+
"last_progress_fingerprint",
|
|
186
|
+
"needs_attention",
|
|
187
|
+
"stalled_context_continuation",
|
|
188
|
+
"stalled_reason",
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
CONTINUATION_COUNTER_FIELDS = [
|
|
192
|
+
"context_overflow_count",
|
|
193
|
+
"continuation_count",
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def has_pending_continuation_metadata(status_data):
|
|
198
|
+
"""Return True when runtime state still has pending continuation metadata."""
|
|
199
|
+
return any(key in status_data for key in CONTINUATION_PENDING_FIELDS)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def clear_pending_continuation_metadata(status_data):
|
|
203
|
+
"""Clear branch/pending continuation fields while preserving observability counters."""
|
|
204
|
+
for key in CONTINUATION_PENDING_FIELDS:
|
|
205
|
+
status_data.pop(key, None)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def reset_continuation_metadata(status_data):
|
|
209
|
+
"""Clear all continuation runtime metadata, including manual-reset counters."""
|
|
210
|
+
clear_pending_continuation_metadata(status_data)
|
|
211
|
+
for key in CONTINUATION_COUNTER_FIELDS:
|
|
212
|
+
status_data.pop(key, None)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
STALL_REASON = "context_overflow_without_git_checkpoint_or_artifact_progress"
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _load_progress_fingerprint(raw):
|
|
219
|
+
if not raw:
|
|
220
|
+
return None
|
|
221
|
+
try:
|
|
222
|
+
return json.loads(raw)
|
|
223
|
+
except (TypeError, ValueError):
|
|
224
|
+
return {"unparsed": str(raw)}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _set_continuation_common(status_data, args, session_id):
|
|
228
|
+
if args.active_dev_branch:
|
|
229
|
+
status_data["active_dev_branch"] = args.active_dev_branch
|
|
230
|
+
if args.base_branch:
|
|
231
|
+
status_data["base_branch"] = args.base_branch
|
|
232
|
+
status_data["last_context_overflow_session_id"] = session_id
|
|
233
|
+
status_data["previous_session_id"] = session_id
|
|
234
|
+
status_data["last_fatal_error_code"] = args.last_fatal_error_code or "context_overflow"
|
|
235
|
+
if args.continuation_summary_path:
|
|
236
|
+
status_data["continuation_summary_path"] = args.continuation_summary_path
|
|
237
|
+
else:
|
|
238
|
+
status_data.pop("continuation_summary_path", None)
|
|
239
|
+
if args.no_progress_count is not None:
|
|
240
|
+
status_data["no_progress_count"] = max(0, args.no_progress_count)
|
|
241
|
+
fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
|
|
242
|
+
if fingerprint is not None:
|
|
243
|
+
status_data["last_progress_fingerprint"] = fingerprint
|
|
244
|
+
status_data["last_infra_error_session_id"] = None
|
|
245
|
+
status_data["resume_from_phase"] = None
|
|
246
|
+
if session_id:
|
|
247
|
+
status_data["last_session_id"] = session_id
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def set_context_overflow_continuation_metadata(status_data, args, session_id):
|
|
251
|
+
"""Record continuation metadata for a context-overflow outcome in status.json."""
|
|
252
|
+
status_data["context_overflow_count"] = status_data.get("context_overflow_count", 0) + 1
|
|
253
|
+
status_data["continuation_count"] = status_data.get("continuation_count", 0) + 1
|
|
254
|
+
status_data["continuation_pending"] = True
|
|
255
|
+
status_data["continuation_reason"] = "context_overflow"
|
|
256
|
+
status_data.pop("needs_attention", None)
|
|
257
|
+
status_data.pop("stalled_context_continuation", None)
|
|
258
|
+
status_data.pop("stalled_reason", None)
|
|
259
|
+
_set_continuation_common(status_data, args, session_id)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def set_stalled_context_continuation_metadata(status_data, args, session_id):
|
|
263
|
+
"""Record no-progress context-overflow stall without consuming retry budgets."""
|
|
264
|
+
status_data["context_overflow_count"] = status_data.get("context_overflow_count", 0) + 1
|
|
265
|
+
status_data["continuation_count"] = status_data.get("continuation_count", 0) + 1
|
|
266
|
+
_set_continuation_common(status_data, args, session_id)
|
|
267
|
+
status_data["continuation_pending"] = False
|
|
268
|
+
status_data["continuation_reason"] = STALL_REASON
|
|
269
|
+
status_data["needs_attention"] = True
|
|
270
|
+
status_data["stalled_context_continuation"] = True
|
|
271
|
+
status_data["stalled_reason"] = STALL_REASON
|
|
272
|
+
if args.no_progress_count is None or args.no_progress_count < 2:
|
|
273
|
+
status_data["no_progress_count"] = 2
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def continuation_metadata_summary(status_data):
|
|
277
|
+
"""Return additive continuation fields for CLI JSON outputs."""
|
|
278
|
+
return {
|
|
279
|
+
"active_dev_branch": status_data.get("active_dev_branch"),
|
|
280
|
+
"base_branch": status_data.get("base_branch"),
|
|
281
|
+
"continuation_pending": status_data.get("continuation_pending", False),
|
|
282
|
+
"continuation_reason": status_data.get("continuation_reason"),
|
|
283
|
+
"last_context_overflow_session_id": status_data.get("last_context_overflow_session_id"),
|
|
284
|
+
"last_fatal_error_code": status_data.get("last_fatal_error_code"),
|
|
285
|
+
"previous_session_id": status_data.get("previous_session_id"),
|
|
286
|
+
"context_overflow_count": status_data.get("context_overflow_count", 0),
|
|
287
|
+
"continuation_count": status_data.get("continuation_count", 0),
|
|
288
|
+
"no_progress_count": status_data.get("no_progress_count", 0),
|
|
289
|
+
"last_progress_fingerprint": status_data.get("last_progress_fingerprint"),
|
|
290
|
+
"needs_attention": status_data.get("needs_attention", False),
|
|
291
|
+
"stalled_context_continuation": status_data.get("stalled_context_continuation", False),
|
|
292
|
+
"stalled_reason": status_data.get("stalled_reason"),
|
|
293
|
+
"continuation_summary_path": status_data.get("continuation_summary_path"),
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
167
297
|
# ---------------------------------------------------------------------------
|
|
168
298
|
# Action: get_next
|
|
169
299
|
# ---------------------------------------------------------------------------
|
|
@@ -244,6 +374,7 @@ def action_get_next(bug_list_data, state_dir):
|
|
|
244
374
|
"infra_error_count": chosen_status_data.get("infra_error_count", 0),
|
|
245
375
|
"resume_from_phase": chosen_status_data.get("resume_from_phase", None),
|
|
246
376
|
}
|
|
377
|
+
result.update(continuation_metadata_summary(chosen_status_data))
|
|
247
378
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
248
379
|
|
|
249
380
|
|
|
@@ -267,12 +398,15 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
267
398
|
|
|
268
399
|
bs = load_bug_status(state_dir, bug_id)
|
|
269
400
|
|
|
401
|
+
current_list_status = get_bug_status_from_list(bug_list_path, bug_id)
|
|
402
|
+
|
|
270
403
|
# Track what status we write to bug-fix-list.json
|
|
271
|
-
new_status =
|
|
404
|
+
new_status = current_list_status
|
|
272
405
|
|
|
273
406
|
if session_status == "success":
|
|
274
407
|
bs["infra_error_count"] = 0
|
|
275
408
|
bs["last_infra_error_session_id"] = None
|
|
409
|
+
clear_pending_continuation_metadata(bs)
|
|
276
410
|
new_status = "completed"
|
|
277
411
|
bs["resume_from_phase"] = None
|
|
278
412
|
err = update_bug_in_list(bug_list_path, bug_id, "completed")
|
|
@@ -304,7 +438,7 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
304
438
|
bs["infra_error_count"] = infra_error_count
|
|
305
439
|
bs["last_infra_error_session_id"] = session_id
|
|
306
440
|
bs["max_infra_retries"] = max_infra_retries
|
|
307
|
-
bs["degraded_reason"] =
|
|
441
|
+
bs["degraded_reason"] = session_status
|
|
308
442
|
if session_id:
|
|
309
443
|
bs["last_session_id"] = session_id
|
|
310
444
|
bs["resume_from_phase"] = None
|
|
@@ -316,6 +450,23 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
316
450
|
else:
|
|
317
451
|
new_status = "pending"
|
|
318
452
|
|
|
453
|
+
err = update_bug_in_list(bug_list_path, bug_id, new_status)
|
|
454
|
+
if err:
|
|
455
|
+
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
456
|
+
return
|
|
457
|
+
elif session_status == "context_overflow":
|
|
458
|
+
# Context overflow is continuation state, not code or infra retry state.
|
|
459
|
+
set_context_overflow_continuation_metadata(bs, args, session_id)
|
|
460
|
+
new_status = "in_progress"
|
|
461
|
+
if current_list_status != "in_progress":
|
|
462
|
+
err = update_bug_in_list(bug_list_path, bug_id, "in_progress")
|
|
463
|
+
if err:
|
|
464
|
+
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
465
|
+
return
|
|
466
|
+
elif session_status == "stalled_context_continuation":
|
|
467
|
+
# No-progress context-overflow stall pauses automation without consuming retry budgets.
|
|
468
|
+
set_stalled_context_continuation_metadata(bs, args, session_id)
|
|
469
|
+
new_status = "needs_info"
|
|
319
470
|
err = update_bug_in_list(bug_list_path, bug_id, new_status)
|
|
320
471
|
if err:
|
|
321
472
|
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
@@ -375,6 +526,14 @@ def action_update(args, bug_list_path, state_dir):
|
|
|
375
526
|
summary["restart_policy"] = "infra_retry"
|
|
376
527
|
summary["infra_error_count"] = bs.get("infra_error_count", 0)
|
|
377
528
|
summary["artifacts_preserved"] = True
|
|
529
|
+
elif session_status == "context_overflow":
|
|
530
|
+
summary["restart_policy"] = "context_overflow_continuation"
|
|
531
|
+
summary.update(continuation_metadata_summary(bs))
|
|
532
|
+
summary["artifacts_preserved"] = True
|
|
533
|
+
elif session_status == "stalled_context_continuation":
|
|
534
|
+
summary["restart_policy"] = "needs_attention"
|
|
535
|
+
summary.update(continuation_metadata_summary(bs))
|
|
536
|
+
summary["artifacts_preserved"] = True
|
|
378
537
|
elif session_status != "success":
|
|
379
538
|
summary["restart_policy"] = "full_restart"
|
|
380
539
|
summary["cleanup_performed"] = cleaned
|
|
@@ -402,7 +561,7 @@ def cleanup_bug_artifacts(state_dir, bug_id, project_root=None):
|
|
|
402
561
|
cleaned = []
|
|
403
562
|
|
|
404
563
|
# 1) Remove all session history
|
|
405
|
-
sessions_dir = os.path.join(state_dir,
|
|
564
|
+
sessions_dir = os.path.join(state_dir, bug_id, "sessions")
|
|
406
565
|
sessions_deleted = 0
|
|
407
566
|
if os.path.isdir(sessions_dir):
|
|
408
567
|
for entry in os.listdir(sessions_dir):
|
|
@@ -413,7 +572,7 @@ def cleanup_bug_artifacts(state_dir, bug_id, project_root=None):
|
|
|
413
572
|
cleaned.append("Deleted {} session(s) from {}".format(sessions_deleted, sessions_dir))
|
|
414
573
|
|
|
415
574
|
# 2) Remove transient files under bug dir (keep status.json)
|
|
416
|
-
bug_dir = os.path.join(state_dir,
|
|
575
|
+
bug_dir = os.path.join(state_dir, bug_id)
|
|
417
576
|
if os.path.isdir(bug_dir):
|
|
418
577
|
for entry in os.listdir(bug_dir):
|
|
419
578
|
if entry == "status.json" or entry == "sessions":
|
|
@@ -445,9 +604,47 @@ def cleanup_bug_artifacts(state_dir, bug_id, project_root=None):
|
|
|
445
604
|
return cleaned
|
|
446
605
|
|
|
447
606
|
|
|
607
|
+
def _resolve_project_file(project_root, path):
|
|
608
|
+
if not path:
|
|
609
|
+
return None
|
|
610
|
+
if os.path.isabs(path):
|
|
611
|
+
target = os.path.abspath(path)
|
|
612
|
+
else:
|
|
613
|
+
target = os.path.abspath(os.path.join(project_root, path))
|
|
614
|
+
root = os.path.abspath(project_root)
|
|
615
|
+
try:
|
|
616
|
+
rel = os.path.relpath(target, root)
|
|
617
|
+
except ValueError:
|
|
618
|
+
return None
|
|
619
|
+
if rel == os.pardir or rel.startswith(os.pardir + os.sep):
|
|
620
|
+
return None
|
|
621
|
+
return target
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def cleanup_continuation_artifacts(project_root, status_data, candidate_paths=None):
|
|
625
|
+
"""Delete durable continuation handoff files for a manual clean reset."""
|
|
626
|
+
candidates = []
|
|
627
|
+
if isinstance(status_data, dict):
|
|
628
|
+
candidates.append(status_data.get("continuation_summary_path"))
|
|
629
|
+
candidates.extend(candidate_paths or [])
|
|
630
|
+
|
|
631
|
+
cleaned = []
|
|
632
|
+
seen = set()
|
|
633
|
+
for candidate in candidates:
|
|
634
|
+
target = _resolve_project_file(project_root, candidate)
|
|
635
|
+
if not target or target in seen:
|
|
636
|
+
continue
|
|
637
|
+
seen.add(target)
|
|
638
|
+
if os.path.basename(target) != "continuation-summary.md":
|
|
639
|
+
continue
|
|
640
|
+
if os.path.isfile(target):
|
|
641
|
+
os.remove(target)
|
|
642
|
+
cleaned.append("Deleted continuation artifact {}".format(target))
|
|
643
|
+
return cleaned
|
|
644
|
+
|
|
645
|
+
|
|
448
646
|
def load_session_status(state_dir, bug_id, session_id):
|
|
449
|
-
session_status_path = os.path.join(
|
|
450
|
-
state_dir, "bugs", bug_id, "sessions",
|
|
647
|
+
session_status_path = os.path.join(state_dir, bug_id, "sessions",
|
|
451
648
|
session_id, "session-status.json"
|
|
452
649
|
)
|
|
453
650
|
data, err = load_json_file(session_status_path)
|
|
@@ -609,6 +806,7 @@ def action_reset(args, bug_list_path, state_dir):
|
|
|
609
806
|
bs["sessions"] = []
|
|
610
807
|
bs["last_session_id"] = None
|
|
611
808
|
bs["resume_from_phase"] = None
|
|
809
|
+
reset_continuation_metadata(bs)
|
|
612
810
|
bs["updated_at"] = now_iso()
|
|
613
811
|
|
|
614
812
|
err = save_bug_status(state_dir, bug_id, bs)
|
|
@@ -649,7 +847,7 @@ def action_clean(args, bug_list_path, state_dir):
|
|
|
649
847
|
cleaned = []
|
|
650
848
|
|
|
651
849
|
# 1. Delete session history
|
|
652
|
-
sessions_dir = os.path.join(state_dir,
|
|
850
|
+
sessions_dir = os.path.join(state_dir, bug_id, "sessions")
|
|
653
851
|
sessions_deleted = 0
|
|
654
852
|
if os.path.isdir(sessions_dir):
|
|
655
853
|
for entry in os.listdir(sessions_dir):
|
|
@@ -680,12 +878,19 @@ def action_clean(args, bug_list_path, state_dir):
|
|
|
680
878
|
old_status = get_bug_status_from_list(bug_list_path, bug_id)
|
|
681
879
|
old_retry = bs.get("retry_count", 0)
|
|
682
880
|
|
|
881
|
+
continuation_candidates = [
|
|
882
|
+
os.path.join(".prizmkit", "bugfix", bug_id, "continuation-summary.md"),
|
|
883
|
+
os.path.join(".prizmkit", "specs", bug_id, "continuation-summary.md"),
|
|
884
|
+
]
|
|
885
|
+
cleaned.extend(cleanup_continuation_artifacts(project_root, bs, continuation_candidates))
|
|
886
|
+
|
|
683
887
|
bs["retry_count"] = 0
|
|
684
888
|
bs["infra_error_count"] = 0
|
|
685
889
|
bs["last_infra_error_session_id"] = None
|
|
686
890
|
bs["sessions"] = []
|
|
687
891
|
bs["last_session_id"] = None
|
|
688
892
|
bs["resume_from_phase"] = None
|
|
893
|
+
reset_continuation_metadata(bs)
|
|
689
894
|
bs["updated_at"] = now_iso()
|
|
690
895
|
|
|
691
896
|
err = save_bug_status(state_dir, bug_id, bs)
|
|
@@ -761,10 +966,11 @@ def action_start(args, bug_list_path, state_dir):
|
|
|
761
966
|
error_out("Failed to save bug status: {}".format(err))
|
|
762
967
|
return
|
|
763
968
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
969
|
+
if old_status != "in_progress":
|
|
970
|
+
err = update_bug_in_list(bug_list_path, bug_id, "in_progress")
|
|
971
|
+
if err:
|
|
972
|
+
error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
|
|
973
|
+
return
|
|
768
974
|
|
|
769
975
|
result = {
|
|
770
976
|
"action": "start",
|
|
@@ -854,6 +1060,7 @@ def action_unskip(args, bug_list_path, state_dir):
|
|
|
854
1060
|
bs["sessions"] = []
|
|
855
1061
|
bs["last_session_id"] = None
|
|
856
1062
|
bs["resume_from_phase"] = None
|
|
1063
|
+
reset_continuation_metadata(bs)
|
|
857
1064
|
bs["updated_at"] = now_iso()
|
|
858
1065
|
save_bug_status(state_dir, bid, bs)
|
|
859
1066
|
|