prizmkit 1.1.120 → 1.1.121

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 (45) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +23 -25
  3. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +8 -2
  4. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +10 -1
  5. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +43 -29
  6. package/bundled/dev-pipeline/scripts/continuation.py +51 -6
  7. package/bundled/dev-pipeline/scripts/update-bug-status.py +57 -14
  8. package/bundled/dev-pipeline/scripts/update-feature-status.py +54 -5
  9. package/bundled/dev-pipeline/scripts/update-refactor-status.py +57 -14
  10. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +2 -2
  11. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +2 -1
  12. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +2 -2
  13. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
  14. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +3 -3
  15. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -4
  16. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
  17. package/bundled/dev-pipeline/tests/test_auto_skip.py +5 -5
  18. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +10 -3
  19. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +9 -2
  20. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +9 -1
  21. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +222 -18
  22. package/bundled/dev-pipeline/tests/test_unified_cli.py +14 -10
  23. package/bundled/skills/_metadata.json +4 -4
  24. package/bundled/skills/prizmkit-code-review/SKILL.md +49 -48
  25. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +13 -8
  26. package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +46 -32
  27. package/bundled/skills/prizmkit-code-review/references/reviewer-workspace-protocol.md +90 -0
  28. package/bundled/skills/prizmkit-test/SKILL.md +159 -155
  29. package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +420 -0
  30. package/bundled/skills/prizmkit-test/assets/behavior-risk-matrix.schema.json +116 -0
  31. package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +112 -0
  32. package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +97 -0
  33. package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +76 -192
  34. package/bundled/skills/prizmkit-test/references/contract-mock-protocol.md +65 -0
  35. package/bundled/skills/prizmkit-test/references/evidence-protocol.md +194 -0
  36. package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +78 -0
  37. package/bundled/skills/prizmkit-test/references/examples.md +65 -108
  38. package/bundled/skills/prizmkit-test/references/service-boundary-test-catalog.md +10 -7
  39. package/bundled/skills/prizmkit-test/references/test-generation-steps.md +90 -82
  40. package/bundled/skills/prizmkit-test/references/test-report-template.md +77 -98
  41. package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +97 -0
  42. package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +723 -0
  43. package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +1426 -0
  44. package/package.json +1 -1
  45. package/bundled/skills/prizmkit-test/scripts/validate_boundary_report.py +0 -347
@@ -381,6 +381,33 @@ def _set_continuation_common(status_data, args, session_id):
381
381
  status_data["last_session_id"] = session_id
382
382
 
383
383
 
384
+ def _set_ai_error_continuation_metadata(status_data, args, session_id, reason):
385
+ """Preserve durable task/session state for any retryable launched AI error."""
386
+ if args.active_dev_branch:
387
+ status_data["active_dev_branch"] = args.active_dev_branch
388
+ if args.base_branch:
389
+ status_data["base_branch"] = args.base_branch
390
+ status_data["continuation_pending"] = True
391
+ status_data["continuation_reason"] = reason
392
+ status_data["continuation_count"] = status_data.get("continuation_count", 0) + 1
393
+ status_data["previous_session_id"] = session_id
394
+ status_data["last_fatal_error_code"] = args.last_fatal_error_code or reason
395
+ if args.continuation_summary_path:
396
+ status_data["continuation_summary_path"] = args.continuation_summary_path
397
+ if args.no_progress_count is not None:
398
+ status_data["no_progress_count"] = max(0, args.no_progress_count)
399
+ fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
400
+ if fingerprint is not None:
401
+ status_data["last_progress_fingerprint"] = fingerprint
402
+ status_data["resume_from_phase"] = None
403
+ if session_id:
404
+ sessions = status_data.get("sessions", [])
405
+ if session_id not in sessions:
406
+ sessions.append(session_id)
407
+ status_data["sessions"] = sessions
408
+ status_data["last_session_id"] = session_id
409
+
410
+
384
411
  def set_context_overflow_continuation_metadata(status_data, args, session_id):
385
412
  """Record continuation metadata for a context-overflow outcome in status.json."""
386
413
  status_data["context_overflow_count"] = status_data.get("context_overflow_count", 0) + 1
@@ -848,6 +875,18 @@ def action_update(args, feature_list_path, state_dir):
848
875
 
849
876
  # Track what status we write to feature-list.json
850
877
  new_status = current_list_status
878
+ if args.active_dev_branch:
879
+ fs["active_dev_branch"] = args.active_dev_branch
880
+ if args.base_branch:
881
+ fs["base_branch"] = args.base_branch
882
+ if args.last_fatal_error_code:
883
+ fs["last_fatal_error_code"] = args.last_fatal_error_code
884
+ if args.continuation_summary_path:
885
+ fs["continuation_summary_path"] = args.continuation_summary_path
886
+ fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
887
+ if fingerprint is not None:
888
+ fs["last_progress_fingerprint"] = fingerprint
889
+
851
890
 
852
891
  if session_status == "success":
853
892
  fs["infra_error_count"] = 0
@@ -923,10 +962,14 @@ def action_update(args, feature_list_path, state_dir):
923
962
 
924
963
  if infra_error_count >= max_infra_retries:
925
964
  new_status = "failed"
965
+ fs["continuation_pending"] = False
966
+ fs["continuation_reason"] = session_status
967
+ fs["needs_attention"] = True
926
968
  if session_id:
927
969
  fs["last_failed_session_id"] = session_id
928
970
  else:
929
- new_status = "pending"
971
+ new_status = "in_progress"
972
+ _set_ai_error_continuation_metadata(fs, args, session_id, session_status)
930
973
 
931
974
  err = update_feature_in_list(feature_list_path, feature_id, new_status)
932
975
  if err:
@@ -955,8 +998,12 @@ def action_update(args, feature_list_path, state_dir):
955
998
 
956
999
  if fs["retry_count"] >= max_retries:
957
1000
  new_status = "failed"
1001
+ fs["continuation_pending"] = False
1002
+ fs["continuation_reason"] = session_status
1003
+ fs["needs_attention"] = True
958
1004
  else:
959
- new_status = "pending"
1005
+ new_status = "in_progress"
1006
+ _set_ai_error_continuation_metadata(fs, args, session_id, session_status)
960
1007
 
961
1008
  fs["resume_from_phase"] = None
962
1009
  if session_id:
@@ -969,7 +1016,7 @@ def action_update(args, feature_list_path, state_dir):
969
1016
  error_out("Failed to update .prizmkit/plans/feature-list.json: {}".format(err))
970
1017
  return
971
1018
 
972
- if session_status == "success" and session_id:
1019
+ if session_id:
973
1020
  sessions = fs.get("sessions", [])
974
1021
  if session_id not in sessions:
975
1022
  sessions.append(session_id)
@@ -1013,8 +1060,9 @@ def action_update(args, feature_list_path, state_dir):
1013
1060
  summary["degraded_reason"] = session_status
1014
1061
  summary["restart_policy"] = "finalization_retry"
1015
1062
  elif session_status == "infra_error":
1016
- summary["restart_policy"] = "infra_retry"
1063
+ summary["restart_policy"] = "in_process_ai_error_continuation" if new_status == "in_progress" else "needs_attention"
1017
1064
  summary["infra_error_count"] = fs.get("infra_error_count", 0)
1065
+ summary.update(continuation_metadata_summary(fs))
1018
1066
  summary["artifacts_preserved"] = True
1019
1067
  elif session_status == "context_overflow":
1020
1068
  summary["restart_policy"] = "context_overflow_continuation"
@@ -1025,7 +1073,8 @@ def action_update(args, feature_list_path, state_dir):
1025
1073
  summary.update(continuation_metadata_summary(fs))
1026
1074
  summary["artifacts_preserved"] = True
1027
1075
  elif session_status != "success":
1028
- summary["restart_policy"] = "preserve_and_retry"
1076
+ summary["restart_policy"] = "in_process_ai_error_continuation" if new_status == "in_progress" else "needs_attention"
1077
+ summary.update(continuation_metadata_summary(fs))
1029
1078
  summary["artifacts_preserved"] = True
1030
1079
 
1031
1080
  print(json.dumps(summary, indent=2, ensure_ascii=False))
@@ -275,6 +275,33 @@ def _set_continuation_common(status_data, args, session_id):
275
275
  status_data["last_session_id"] = session_id
276
276
 
277
277
 
278
+ def _set_ai_error_continuation_metadata(status_data, args, session_id, reason):
279
+ """Preserve durable task/session state for any retryable launched AI error."""
280
+ if args.active_dev_branch:
281
+ status_data["active_dev_branch"] = args.active_dev_branch
282
+ if args.base_branch:
283
+ status_data["base_branch"] = args.base_branch
284
+ status_data["continuation_pending"] = True
285
+ status_data["continuation_reason"] = reason
286
+ status_data["continuation_count"] = status_data.get("continuation_count", 0) + 1
287
+ status_data["previous_session_id"] = session_id
288
+ status_data["last_fatal_error_code"] = args.last_fatal_error_code or reason
289
+ if args.continuation_summary_path:
290
+ status_data["continuation_summary_path"] = args.continuation_summary_path
291
+ if args.no_progress_count is not None:
292
+ status_data["no_progress_count"] = max(0, args.no_progress_count)
293
+ fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
294
+ if fingerprint is not None:
295
+ status_data["last_progress_fingerprint"] = fingerprint
296
+ status_data["resume_from_phase"] = None
297
+ if session_id:
298
+ sessions = status_data.get("sessions", [])
299
+ if session_id not in sessions:
300
+ sessions.append(session_id)
301
+ status_data["sessions"] = sessions
302
+ status_data["last_session_id"] = session_id
303
+
304
+
278
305
  def set_context_overflow_continuation_metadata(status_data, args, session_id):
279
306
  """Record continuation metadata for a context-overflow outcome in status.json."""
280
307
  status_data["context_overflow_count"] = status_data.get("context_overflow_count", 0) + 1
@@ -460,6 +487,18 @@ def action_update(args, refactor_list_path, state_dir):
460
487
 
461
488
  # Track what status we write to refactor-list.json
462
489
  new_status = current_list_status
490
+ if args.active_dev_branch:
491
+ rs["active_dev_branch"] = args.active_dev_branch
492
+ if args.base_branch:
493
+ rs["base_branch"] = args.base_branch
494
+ if args.last_fatal_error_code:
495
+ rs["last_fatal_error_code"] = args.last_fatal_error_code
496
+ if args.continuation_summary_path:
497
+ rs["continuation_summary_path"] = args.continuation_summary_path
498
+ fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
499
+ if fingerprint is not None:
500
+ rs["last_progress_fingerprint"] = fingerprint
501
+
463
502
 
464
503
  if session_status == "success":
465
504
  rs["infra_error_count"] = 0
@@ -503,10 +542,14 @@ def action_update(args, refactor_list_path, state_dir):
503
542
 
504
543
  if infra_error_count >= max_infra_retries:
505
544
  new_status = "failed"
545
+ rs["continuation_pending"] = False
546
+ rs["continuation_reason"] = session_status
547
+ rs["needs_attention"] = True
506
548
  if session_id:
507
549
  rs["last_failed_session_id"] = session_id
508
550
  else:
509
- new_status = "pending"
551
+ new_status = "in_progress"
552
+ _set_ai_error_continuation_metadata(rs, args, session_id, session_status)
510
553
 
511
554
  err = update_refactor_in_list(refactor_list_path, refactor_id, new_status)
512
555
  if err:
@@ -532,27 +575,25 @@ def action_update(args, refactor_list_path, state_dir):
532
575
  else:
533
576
  rs["retry_count"] = rs.get("retry_count", 0) + 1
534
577
 
535
- cleaned = cleanup_refactor_artifacts(
536
- state_dir=state_dir,
537
- refactor_id=refactor_id,
538
- project_root=args.project_root,
539
- )
540
-
541
578
  if rs["retry_count"] >= max_retries:
542
579
  new_status = "failed"
580
+ rs["continuation_pending"] = False
581
+ rs["continuation_reason"] = session_status
582
+ rs["needs_attention"] = True
543
583
  else:
544
- new_status = "pending"
584
+ new_status = "in_progress"
585
+ _set_ai_error_continuation_metadata(rs, args, session_id, session_status)
545
586
 
546
587
  rs["resume_from_phase"] = None
547
- rs["sessions"] = []
548
- rs["last_session_id"] = None
588
+ if session_id:
589
+ rs["last_failed_session_id"] = session_id
549
590
 
550
591
  err = update_refactor_in_list(refactor_list_path, refactor_id, new_status)
551
592
  if err:
552
593
  error_out("Failed to update .prizmkit/plans/refactor-list.json: {}".format(err))
553
594
  return
554
595
 
555
- if session_status == "success" and session_id:
596
+ if session_id:
556
597
  sessions = rs.get("sessions", [])
557
598
  if session_id not in sessions:
558
599
  sessions.append(session_id)
@@ -594,8 +635,9 @@ def action_update(args, refactor_list_path, state_dir):
594
635
  summary["degraded_reason"] = session_status
595
636
  summary["restart_policy"] = "finalization_retry"
596
637
  elif session_status == "infra_error":
597
- summary["restart_policy"] = "infra_retry"
638
+ summary["restart_policy"] = "in_process_ai_error_continuation" if new_status == "in_progress" else "needs_attention"
598
639
  summary["infra_error_count"] = rs.get("infra_error_count", 0)
640
+ summary.update(continuation_metadata_summary(rs))
599
641
  summary["artifacts_preserved"] = True
600
642
  elif session_status == "context_overflow":
601
643
  summary["restart_policy"] = "context_overflow_continuation"
@@ -606,8 +648,9 @@ def action_update(args, refactor_list_path, state_dir):
606
648
  summary.update(continuation_metadata_summary(rs))
607
649
  summary["artifacts_preserved"] = True
608
650
  elif session_status != "success":
609
- summary["restart_policy"] = "full_restart"
610
- summary["cleanup_performed"] = cleaned
651
+ summary["restart_policy"] = "in_process_ai_error_continuation" if new_status == "in_progress" else "needs_attention"
652
+ summary.update(continuation_metadata_summary(rs))
653
+ summary["artifacts_preserved"] = True
611
654
 
612
655
  print(json.dumps(summary, indent=2, ensure_ascii=False))
613
656
 
@@ -240,7 +240,7 @@ For each Verification Gate from the Task Contract, write one evidence line to Im
240
240
 
241
241
  Review the completed implementation before the scoped feature test gate runs. Use `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` so the code-review skill can read spec, plan, context snapshot, implementation log, and current diff artifacts. Do not require or read a prior `/prizmkit-test` report here; test generation and test-fix looping happen in the next phase.
242
242
 
243
- Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The code-review skill must launch Reviewer in `current-workspace / active-checkout / no-worktree` mode so it reviews the active checkout rather than an isolated copy; do not request worktree isolation or use `.claude/worktrees/...` / `.prizmkit/state/worktrees/...`. Do not set `USE_WORKTREE` for reviewer launches.
243
+ Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The skill chooses a platform-supported independent Reviewer strategy and verifies that the Reviewer's snapshot is equivalent to the current workspace under its skill-owned workspace protocol. Do not prescribe Agent launch parameters from this bootstrap prompt.
244
244
 
245
245
  The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory.
246
246
 
@@ -253,7 +253,7 @@ If GATE:MISSING:
253
253
  - Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
254
254
  - Perform one bounded status check; retry at most once: inspect the skill output, `review-report.md` path, and any Reviewer agent spawn messages.
255
255
  - If the missing report is caused by Reviewer agent spawn or review skill error, retry `/prizmkit-code-review` at most once only if it appears transient.
256
- - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then either perform a safe inline fallback review (spec/plan/diff/tests → write `review-report.md` with `## Verdict`) or stop with a clear recovery failure.
256
+ - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then stop with a clear recovery failure. Do not synthesize a passing report through Main-Agent self-review.
257
257
 
258
258
  Read `review-report.md` and check the Verdict:
259
259
  - `PASS` → proceed to next phase
@@ -180,6 +180,7 @@ After implement completes, verify:
180
180
  If `FAST_PATH=true` (≤ 2 tasks, obvious root cause), skip this phase entirely and mark checkpoint step `prizmkit-code-review` as `skipped` before continuing.
181
181
 
182
182
  Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/bugfix/{{BUG_ID}}/`:
183
+ - The skill chooses a platform-supported independent Reviewer strategy and verifies a workspace-equivalent snapshot under its skill-owned protocol
183
184
  - The skill runs an internal review-fix loop (Reviewer → filter → orchestrator fix, max 3 rounds) and writes `review-report.md`
184
185
  - `review-report.md` must contain `## Verdict`
185
186
 
@@ -191,7 +192,7 @@ After `/prizmkit-code-review` returns, verify the review report:
191
192
  If GATE:MISSING:
192
193
  - Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
193
194
  - Perform one bounded status check; retry `/prizmkit-code-review` at most once only if the missing report appears caused by a transient team/config/lock error.
194
- - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then either perform a safe inline fallback review (spec/plan/diff/tests write `review-report.md` with `## Verdict`) or stop with a clear recovery failure.
195
+ - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then stop with a clear recovery failure. Do not replace the independent Reviewer with Main-Agent self-review.
195
196
 
196
197
  Read `review-report.md` and check the Verdict:
197
198
  - `PASS` → proceed
@@ -139,7 +139,7 @@ Apply the browser behavior preservation protocol where UI behavior can be affect
139
139
 
140
140
  ### Phase 4: Review — Code Review & Behavior Verification
141
141
 
142
- Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/refactor/{{REFACTOR_ID}}/` directly from the main orchestrator.
142
+ Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/refactor/{{REFACTOR_ID}}/` directly from the main orchestrator. The skill loads its skill-owned `references/reviewer-agent-prompt.md` and `references/reviewer-workspace-protocol.md`, chooses a platform-supported independent Reviewer strategy, and verifies a workspace-equivalent snapshot.
143
143
 
144
144
  Review requirements:
145
145
  - verify refactor quality against spec.md and plan.md;
@@ -147,7 +147,7 @@ Review requirements:
147
147
  - run or confirm relevant tests;
148
148
  - write `.prizmkit/refactor/{{REFACTOR_ID}}/review-report.md` with `## Verdict`.
149
149
 
150
- If the report is missing after one bounded status check, write `failure-log.md` and either perform a safe inline fallback review or stop with a clear recovery failure.
150
+ If the report is missing after one bounded status check, write `failure-log.md` and stop with a clear recovery failure. Do not replace the independent Reviewer with Main-Agent self-review.
151
151
 
152
152
  **Checkpoint update**: set step `prizmkit-code-review` to `completed` in `{{CHECKPOINT_PATH}}`.
153
153
 
@@ -12,9 +12,9 @@ If `FAST_PATH=true`, skip this phase intentionally:
12
12
 
13
13
  Then continue to the next checkpoint step.
14
14
 
15
- Otherwise, run `/prizmkit-code-review` with `artifact_dir=.prizmkit/bugfix/{{BUG_ID}}/`. The code-review skill loads its skill-owned `references/reviewer-agent-prompt.md` prompt and launches the internal reviewer in `current-workspace / active-checkout / no-worktree` mode.
15
+ Otherwise, run `/prizmkit-code-review` with `artifact_dir=.prizmkit/bugfix/{{BUG_ID}}/`. The skill loads its skill-owned Reviewer prompt and workspace protocol, chooses a platform-supported subagent strategy, and verifies that the Reviewer's snapshot is equivalent to the current workspace before review.
16
16
 
17
- The skill runs its internal Reviewer Agent → filter → orchestrator fix loop and writes `review-report.md`. Do not request worktree isolation or use `.claude/worktrees/...` / `.prizmkit/state/worktrees/...`; outer runner `USE_WORKTREE` settings do not permit review subagent isolation.
17
+ The skill runs its internal Reviewer Agent → filter → orchestrator fix loop and writes `review-report.md`. Do not prescribe Agent launch parameters from this pipeline template; the review skill owns strategy selection and workspace-equivalence verification.
18
18
 
19
19
  **Gate Check — Review Report**:
20
20
 
@@ -24,6 +24,6 @@ The skill runs its internal Reviewer Agent → filter → orchestrator fix loop
24
24
 
25
25
  - `PASS` → proceed.
26
26
  - `NEEDS_FIXES` → the skill exhausted its internal rounds; log remaining findings and proceed only when they do not block acceptance criteria.
27
- - Missing report → one bounded retry or safe inline fallback review, then write `failure-log.md` if still blocked.
27
+ - Missing report → one bounded retry, then write `failure-log.md` and stop if the independent review protocol remains blocked; do not replace it with Main-Agent self-review.
28
28
 
29
29
  **Checkpoint update**: Set step `prizmkit-code-review` to `completed` when review is complete, or `skipped` for FAST_PATH.
@@ -2,9 +2,9 @@
2
2
 
3
3
  Review the completed implementation before the scoped feature test gate runs. Use `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` so the code-review skill can read spec, plan, context snapshot, implementation log, and current diff artifacts. Do not require or read a prior `/prizmkit-test` report here; test generation and test-fix looping happen in the next phase.
4
4
 
5
- Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The code-review skill loads its skill-owned `references/reviewer-agent-prompt.md` prompt and launches the internal reviewer in `current-workspace / active-checkout / no-worktree` mode.
5
+ Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The skill loads its skill-owned Reviewer prompt and workspace protocol, chooses a platform-supported subagent strategy, and verifies that the Reviewer's snapshot is equivalent to the current workspace before review.
6
6
 
7
- The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory. Do not request worktree isolation or use `.claude/worktrees/...` / `.prizmkit/state/worktrees/...`; outer runner `USE_WORKTREE` settings do not permit review subagent isolation.
7
+ The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory. Do not prescribe Agent launch parameters from this pipeline template; the review skill owns strategy selection and workspace-equivalence verification.
8
8
 
9
9
  **Gate Check — Review Report**:
10
10
  After `/prizmkit-code-review` returns, verify the review report:
@@ -15,7 +15,7 @@ If GATE:MISSING:
15
15
  - Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
16
16
  - Perform one bounded status check; retry at most once: inspect the skill output, `review-report.md` path, and any Reviewer agent spawn messages.
17
17
  - If the missing report is caused by team/config/lock errors from the Reviewer agent spawn or review skill error, retry `/prizmkit-code-review` at most once only if it appears transient.
18
- - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then either perform a safe inline fallback review (spec/plan/diff/tests → write `review-report.md` with `## Verdict`) or stop with a clear recovery failure.
18
+ - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then stop with a clear recovery failure. Do not synthesize a passing report through Main-Agent self-review.
19
19
 
20
20
  Read `review-report.md` and check the Verdict:
21
21
  - `PASS` → proceed to next phase
@@ -2,11 +2,11 @@
2
2
 
3
3
  Review the completed implementation before the scoped feature test gate runs. Use `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` so the code-review skill can read spec, plan, context snapshot, implementation log, and current diff artifacts. Do not require or read a prior `/prizmkit-test` report here; test generation and test-fix looping happen in the next phase.
4
4
 
5
- Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The code-review skill loads its skill-owned `references/reviewer-agent-prompt.md` prompt and launches the internal reviewer in `current-workspace / active-checkout / no-worktree` mode.
5
+ Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. The skill loads its skill-owned Reviewer prompt and workspace protocol, chooses a platform-supported subagent strategy, and verifies that the Reviewer's snapshot is equivalent to the current workspace before review.
6
6
 
7
- If the reviewer spawn fails with team/config/lock errors, retry at most once. If the second attempt fails, do not keep spawning variants and do not enter report-polling loops for review markers; write `failure-log.md` with the spawn error and use the documented inline fallback only when safe.
7
+ If the independent Reviewer cannot start or verify the snapshot because of a transient platform error, retry at most once. If the second attempt fails, do not keep spawning variants or enter report-polling loops; write `failure-log.md` with the observable error and let the skill report the unresolved verification blocker. Do not replace the independent Reviewer with Main-Agent self-review.
8
8
 
9
- The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory. Do not request worktree isolation or use `.claude/worktrees/...` / `.prizmkit/state/worktrees/...`; outer runner `USE_WORKTREE` settings do not permit review subagent isolation.
9
+ The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory. Do not prescribe Agent launch parameters from this pipeline template; the review skill owns strategy selection and workspace-equivalence verification.
10
10
 
11
11
  **Gate Check — Review Report**:
12
12
  After `/prizmkit-code-review` returns, verify the review report:
@@ -17,7 +17,7 @@ If GATE:MISSING:
17
17
  - Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
18
18
  - Perform one bounded status check; retry at most once: inspect the skill output, `review-report.md` path, and any Reviewer agent spawn messages.
19
19
  - If the missing report is caused by team/config/lock errors from the Reviewer agent spawn or review skill error, retry `/prizmkit-code-review` at most once only if it appears transient.
20
- - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then either perform a safe inline fallback review (spec/plan/diff/tests → write `review-report.md` with `## Verdict`) or stop with a clear recovery failure.
20
+ - If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then stop with a clear recovery failure. Do not synthesize a passing report through Main-Agent self-review.
21
21
 
22
22
  Read `review-report.md` and check the Verdict:
23
23
  - `PASS` → proceed to next phase
@@ -1,8 +1,8 @@
1
1
  ### Phase 3: Review — Code Review & Behavior Verification
2
2
 
3
- Run `/prizmkit-code-review` directly with `artifact_dir=.prizmkit/refactor/{{REFACTOR_ID}}/`. The code-review skill loads its skill-owned `references/reviewer-agent-prompt.md` prompt and launches the internal reviewer in `current-workspace / active-checkout / no-worktree` mode.
3
+ Run `/prizmkit-code-review` directly with `artifact_dir=.prizmkit/refactor/{{REFACTOR_ID}}/`. The skill loads its skill-owned `references/reviewer-agent-prompt.md` and `references/reviewer-workspace-protocol.md`, chooses a platform-supported subagent strategy, and verifies that the Reviewer's snapshot is equivalent to the current workspace before review.
4
4
 
5
- Do not spawn a top-level Reviewer subagent. The code-review skill owns its internal Reviewer Agent → filter → orchestrator fix loop. Do not request worktree isolation or use `.claude/worktrees/...` / `.prizmkit/state/worktrees/...`; outer runner `USE_WORKTREE` settings do not permit review subagent isolation.
5
+ Do not spawn a top-level Reviewer subagent. The code-review skill owns its internal Reviewer Agent → filter → orchestrator fix loop. Do not prescribe Agent launch parameters from this pipeline template; the review skill owns strategy selection and workspace-equivalence verification.
6
6
 
7
7
  **Gate Check — Review Report**:
8
8
 
@@ -12,7 +12,7 @@ Do not spawn a top-level Reviewer subagent. The code-review skill owns its inter
12
12
 
13
13
  - `PASS` → proceed.
14
14
  - `NEEDS_FIXES` → the skill exhausted its internal rounds; log remaining findings and proceed only when they do not block behavior preservation.
15
- - Missing report → one bounded retry or safe inline fallback review, then write `failure-log.md` if still blocked.
15
+ - Missing report → one bounded retry, then write `failure-log.md` and stop if the independent review protocol remains blocked; do not replace it with Main-Agent self-review.
16
16
 
17
17
  Verify the review explicitly checks behavior preservation, public API compatibility, imports, tests, and rollback assumptions.
18
18
 
@@ -1195,7 +1195,7 @@ def _run_update(fl_path, state_dir, feature_id, session_status, session_id="sess
1195
1195
 
1196
1196
 
1197
1197
  class TestInfraErrorUpdate:
1198
- def test_infra_error_below_budget_keeps_pending_without_consuming_retry(self, tmp_path):
1198
+ def test_infra_error_below_budget_keeps_in_progress_without_consuming_retry(self, tmp_path):
1199
1199
  features = [_make_feature("F-001", "Root", status="in_progress")]
1200
1200
  fl_path = _write_fl(tmp_path, features)
1201
1201
  state_dir = _init_state(tmp_path, ["F-001"])
@@ -1214,12 +1214,12 @@ class TestInfraErrorUpdate:
1214
1214
  max_infra_retries=3,
1215
1215
  )
1216
1216
 
1217
- assert result["new_status"] == "pending"
1217
+ assert result["new_status"] == "in_progress"
1218
1218
  assert result["retry_count"] == 2
1219
1219
  assert result["infra_error_count"] == 1
1220
1220
  assert result["max_infra_retries"] == 3
1221
- assert result["restart_policy"] == "infra_retry"
1222
- assert _read_statuses(fl_path)["F-001"] == "pending"
1221
+ assert result["restart_policy"] == "in_process_ai_error_continuation"
1222
+ assert _read_statuses(fl_path)["F-001"] == "in_progress"
1223
1223
 
1224
1224
  fs = load_feature_status(state_dir, "F-001")
1225
1225
  assert fs["retry_count"] == 2
@@ -1250,7 +1250,7 @@ class TestInfraErrorUpdate:
1250
1250
  assert result["new_status"] == "failed"
1251
1251
  assert result["retry_count"] == 1
1252
1252
  assert result["infra_error_count"] == 3
1253
- assert result["restart_policy"] == "infra_retry"
1253
+ assert result["restart_policy"] == "needs_attention"
1254
1254
  assert _read_statuses(fl_path)["F-001"] == "failed"
1255
1255
 
1256
1256
  fs = load_feature_status(state_dir, "F-001")
@@ -921,7 +921,14 @@ class TestContinuationHandoff:
921
921
  args = Namespace(
922
922
  output=str(tmp_path / ".prizmkit/state/features/F-123/sessions/F-123-new/bootstrap-prompt.md"),
923
923
  state_dir=str(tmp_path / ".prizmkit/state/features"),
924
- continuation_mode="context_overflow",
924
+ continuation_mode="ai_error",
925
+ failure_classification="ai_runtime_or_provider_error",
926
+ code_retry_count="1",
927
+ infra_error_count="2",
928
+ max_code_retries="3",
929
+ max_infra_retries="3",
930
+ no_progress_count="0",
931
+ progress_fingerprint=json.dumps({"git_diff_fingerprint": "diff", "head_commit": "abc", "checkpoint_cursor": "S03:pending"}),
925
932
  previous_session_id="F-123-old",
926
933
  continuation_count="2",
927
934
  context_overflow_count="2",
@@ -942,11 +949,11 @@ class TestContinuationHandoff:
942
949
 
943
950
  assert rendered.startswith("NORMAL BOOTSTRAP")
944
951
  assert "## Continuation Addendum" in rendered
945
- assert "This is an automatic continuation after context overflow." in rendered
952
+ assert "This is an automatic continuation after the previous launched AI session ended with `ai_runtime_or_provider_error`." in rendered
946
953
  assert "This is a fresh headless AI CLI session for the same task." in rendered
947
954
  assert "Continue on the current branch/worktree." in rendered
948
955
  assert "Do not reset, clean, switch branches, or discard work." in rendered
949
- assert "Start with `git status` and `git diff`." in rendered
956
+ assert "Inspect `git status` and `git diff` before editing." in rendered
950
957
  assert "Treat completed/skipped checkpoint steps as already done." in rendered
951
958
  assert "Do not read the previous full `session.log` unless explicitly necessary." in rendered
952
959
  assert "prefer synthesized artifacts and summaries over logs" in rendered
@@ -265,7 +265,14 @@ class TestBugfixContinuationHandoff:
265
265
  args = Namespace(
266
266
  output=str(tmp_path / ".prizmkit/state/bugfix/B-007/sessions/B-007-new/bootstrap-prompt.md"),
267
267
  state_dir=str(tmp_path / ".prizmkit/state/bugfix"),
268
- continuation_mode="context_overflow",
268
+ continuation_mode="ai_error",
269
+ failure_classification="ai_runtime_or_provider_error",
270
+ code_retry_count="1",
271
+ infra_error_count="2",
272
+ max_code_retries="3",
273
+ max_infra_retries="3",
274
+ no_progress_count="0",
275
+ progress_fingerprint=json.dumps({"git_diff_fingerprint": "diff", "head_commit": "abc", "checkpoint_cursor": "S03:pending"}),
269
276
  previous_session_id="B-007-old",
270
277
  continuation_count="1",
271
278
  context_overflow_count="1",
@@ -279,7 +286,7 @@ class TestBugfixContinuationHandoff:
279
286
  )
280
287
 
281
288
  assert prompt.startswith("BUGFIX PROMPT")
282
- assert "This is an automatic continuation after context overflow." in prompt
289
+ assert "This is an automatic continuation after the previous launched AI session ended with `ai_runtime_or_provider_error`." in prompt
283
290
  assert "Do not attempt `/compact` as the recovery mechanism." not in prompt
284
291
  assert ("Log " + "monitor") not in prompt
285
292
  assert ("log-" + "monitor") not in prompt
@@ -1,5 +1,6 @@
1
1
  """Tests for generate-refactor-prompt.py continuation behavior."""
2
2
 
3
+ import json
3
4
  from argparse import Namespace
4
5
  from pathlib import Path
5
6
  import os
@@ -20,7 +21,14 @@ class TestRefactorContinuationHandoff:
20
21
  args = Namespace(
21
22
  output=str(tmp_path / ".prizmkit/state/refactor/R-007/sessions/R-007-new/bootstrap-prompt.md"),
22
23
  state_dir=str(tmp_path / ".prizmkit/state/refactor"),
23
- continuation_mode="context_overflow",
24
+ continuation_mode="ai_error",
25
+ failure_classification="ai_runtime_or_provider_error",
26
+ code_retry_count="1",
27
+ infra_error_count="2",
28
+ max_code_retries="3",
29
+ max_infra_retries="3",
30
+ no_progress_count="0",
31
+ progress_fingerprint=json.dumps({"git_diff_fingerprint": "diff", "head_commit": "abc", "checkpoint_cursor": "S03:pending"}),
24
32
  previous_session_id="R-007-old",
25
33
  continuation_count="1",
26
34
  context_overflow_count="1",