prizmkit 1.1.154 → 1.1.156

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 (164) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codex/skill-adapter.js +1 -1
  3. package/bundled/adapters/pi/skill-adapter.js +2 -1
  4. package/bundled/dev-pipeline/.env.example +2 -6
  5. package/bundled/dev-pipeline/README.md +21 -27
  6. package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +341 -15
  7. package/bundled/dev-pipeline/prizmkit_runtime/cli.py +0 -3
  8. package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +1 -15
  9. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +48 -14
  10. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +50 -2
  11. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -9
  12. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +3 -3
  13. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +120 -22
  14. package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +482 -0
  15. package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +64 -11
  16. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +145 -367
  17. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +91 -62
  18. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +105 -69
  19. package/bundled/dev-pipeline/scripts/prompt_framework.py +36 -41
  20. package/bundled/dev-pipeline/scripts/update-bug-status.py +1 -4
  21. package/bundled/dev-pipeline/scripts/update-checkpoint.py +61 -13
  22. package/bundled/dev-pipeline/scripts/update-feature-status.py +1 -4
  23. package/bundled/dev-pipeline/scripts/update-refactor-status.py +1 -4
  24. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +22 -27
  25. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +71 -104
  26. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +59 -111
  27. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +37 -72
  28. package/bundled/dev-pipeline/templates/sections/artifact-manifest.md +39 -0
  29. package/bundled/dev-pipeline/templates/sections/bugfix-critical-paths.md +3 -1
  30. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +8 -25
  31. package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +3 -3
  32. package/bundled/dev-pipeline/templates/sections/bugfix-phase-implement.md +2 -2
  33. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
  34. package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +2 -2
  35. package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +4 -4
  36. package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +0 -1
  37. package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +7 -4
  38. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +14 -27
  39. package/bundled/dev-pipeline/templates/sections/feature-completion-summary.md +20 -0
  40. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -71
  41. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -7
  42. package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +3 -3
  43. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -4
  44. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +5 -17
  45. package/bundled/dev-pipeline/templates/sections/refactor-critical-paths.md +3 -1
  46. package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +10 -23
  47. package/bundled/dev-pipeline/templates/sections/refactor-phase-implement.md +2 -2
  48. package/bundled/dev-pipeline/templates/sections/refactor-phase-plan.md +2 -2
  49. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
  50. package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +2 -2
  51. package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +7 -7
  52. package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +0 -1
  53. package/bundled/dev-pipeline/templates/sections/retrospective.md +12 -0
  54. package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +35 -0
  55. package/bundled/dev-pipeline/templates/session-status-schema.json +45 -62
  56. package/bundled/dev-pipeline/tests/test_checkpoint_state.py +469 -18
  57. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +262 -175
  58. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +62 -23
  59. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +76 -28
  60. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +168 -18
  61. package/bundled/dev-pipeline/tests/test_recovery_workflow.py +111 -0
  62. package/bundled/dev-pipeline/tests/test_reset_preserve.py +0 -2
  63. package/bundled/dev-pipeline/tests/test_runtime_commit.py +608 -0
  64. package/bundled/dev-pipeline/tests/test_unified_cli.py +167 -25
  65. package/bundled/skills/_metadata.json +9 -9
  66. package/bundled/skills/app-planner/SKILL.md +3 -3
  67. package/bundled/skills/app-planner/references/generated-plan-review.md +2 -1
  68. package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +56 -64
  69. package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +85 -240
  70. package/bundled/skills/app-planner/references/rules/backend/question-bank.md +25 -25
  71. package/bundled/skills/app-planner/references/rules/backend/question-manifest.json +16 -7
  72. package/bundled/skills/app-planner/references/rules/backend/template.md +74 -92
  73. package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +93 -93
  74. package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +66 -173
  75. package/bundled/skills/app-planner/references/rules/database/question-bank.md +31 -26
  76. package/bundled/skills/app-planner/references/rules/database/question-manifest.json +13 -4
  77. package/bundled/skills/app-planner/references/rules/database/template.md +76 -98
  78. package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +68 -95
  79. package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +93 -166
  80. package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +46 -36
  81. package/bundled/skills/app-planner/references/rules/frontend/question-manifest.json +11 -2
  82. package/bundled/skills/app-planner/references/rules/frontend/template.md +79 -257
  83. package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +91 -99
  84. package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +73 -246
  85. package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +17 -17
  86. package/bundled/skills/app-planner/references/rules/mobile/question-manifest.json +17 -2
  87. package/bundled/skills/app-planner/references/rules/mobile/template.md +73 -85
  88. package/bundled/skills/app-planner/references/rules-configuration.md +133 -65
  89. package/bundled/skills/app-planner/scripts/validate-rules-configuration.py +291 -0
  90. package/bundled/skills/prizmkit/SKILL.md +17 -18
  91. package/bundled/skills/prizmkit/references/workflow-state-protocol.md +22 -18
  92. package/bundled/skills/prizmkit-code-review/SKILL.md +22 -58
  93. package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +6 -6
  94. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +2 -2
  95. package/bundled/skills/prizmkit-committer/SKILL.md +82 -132
  96. package/bundled/skills/prizmkit-deploy/SKILL.md +27 -11
  97. package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +89 -0
  98. package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +44 -14
  99. package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +19 -3
  100. package/bundled/skills/prizmkit-deploy/references/database-setup.md +22 -12
  101. package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +3 -1
  102. package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +22 -6
  103. package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +49 -0
  104. package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +1 -1
  105. package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +164 -0
  106. package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +9 -8
  107. package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +6 -6
  108. package/bundled/skills/prizmkit-implement/SKILL.md +30 -66
  109. package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +4 -4
  110. package/bundled/skills/prizmkit-init/SKILL.md +4 -0
  111. package/bundled/skills/prizmkit-plan/SKILL.md +21 -64
  112. package/bundled/skills/prizmkit-plan/references/artifact-identity.md +38 -0
  113. package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +4 -4
  114. package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +5 -5
  115. package/bundled/skills/prizmkit-prizm-docs/SKILL.md +75 -11
  116. package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +191 -56
  117. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +18 -18
  118. package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +14 -8
  119. package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +12 -5
  120. package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +23 -12
  121. package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -9
  122. package/bundled/skills/prizmkit-retrospective/SKILL.md +94 -97
  123. package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +79 -37
  124. package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
  125. package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +111 -54
  126. package/bundled/skills/prizmkit-test/SKILL.md +64 -51
  127. package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +206 -0
  128. package/bundled/skills/prizmkit-test/references/independent-test-review.md +17 -9
  129. package/bundled/skills/prizmkit-test/references/test-coverage-model.md +45 -21
  130. package/bundled/skills/prizmkit-test/references/test-report-template.md +20 -13
  131. package/bundled/skills/prizmkit-workflow/SKILL.md +35 -37
  132. package/bundled/skills/prizmkit-workflow/references/artifact-identity.md +34 -0
  133. package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +22 -18
  134. package/bundled/skills/recovery-workflow/SKILL.md +2 -1
  135. package/bundled/skills/recovery-workflow/references/detection.md +4 -3
  136. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +15 -5
  137. package/bundled/templates/hooks/validate-prizm-docs.py +124 -12
  138. package/package.json +1 -1
  139. package/src/scaffold.js +33 -22
  140. package/bundled/dev-pipeline/templates/sections/bugfix-artifacts.md +0 -16
  141. package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +0 -31
  142. package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -7
  143. package/bundled/dev-pipeline/templates/sections/critical-paths-lite.md +0 -7
  144. package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +0 -9
  145. package/bundled/dev-pipeline/templates/sections/directory-convention-lite.md +0 -6
  146. package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +0 -15
  147. package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -61
  148. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -24
  149. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -12
  150. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +0 -44
  151. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -25
  152. package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +0 -20
  153. package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +0 -20
  154. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +0 -20
  155. package/bundled/dev-pipeline/templates/sections/refactor-artifacts.md +0 -17
  156. package/bundled/dev-pipeline/templates/sections/refactor-session-status.md +0 -28
  157. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +0 -52
  158. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +0 -52
  159. package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +0 -174
  160. package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +0 -174
  161. package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +0 -174
  162. package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +0 -174
  163. package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +0 -174
  164. package/bundled/skills/prizmkit-test/references/external-contract-mock-guidance.md +0 -119
@@ -20,7 +20,6 @@ from prompt_framework import (
20
20
  generate_checkpoint_from_sections,
21
21
  load_section,
22
22
  merge_checkpoint_state,
23
- normalize_mode,
24
23
  pipeline_checkpoint_metadata,
25
24
  read_text_file,
26
25
  render_from_sections,
@@ -81,11 +80,17 @@ REFACTOR_SECTION_TO_SKILL = {
81
80
  ),
82
81
  "phase-browser": checkpoint_step("browser-verification", "Browser Verification", []),
83
82
  "refactor-phase-commit-report": checkpoint_group([
84
- ("prizmkit-retrospective", "Retrospective", []),
85
- ("prizmkit-committer", "Commit", []),
86
83
  ("refactor-report", "Generate Refactor Report", [".prizmkit/refactor/{slug}/refactor-report.md"]),
87
84
  ("completion-summary", "Completion Summary", [".prizmkit/refactor/{slug}/completion-summary.json"]),
88
85
  ]),
86
+ "retrospective": checkpoint_step(
87
+ "prizmkit-retrospective", "Retrospective",
88
+ [".prizmkit/refactor/{slug}/retrospective-result.json"],
89
+ ),
90
+ "runtime-commit-handoff": checkpoint_step(
91
+ "prizmkit-committer", "Runtime Commit Handoff",
92
+ [".prizmkit/refactor/{slug}/runtime-commit-request.json"],
93
+ ),
89
94
  }
90
95
 
91
96
  REFACTOR_SPLIT_STEPS = {}
@@ -107,8 +112,12 @@ def parse_args():
107
112
  parser.add_argument("--state-dir", default=None, help="State directory (default: .prizmkit/state/refactor)")
108
113
  parser.add_argument("--output", required=True, help="Output path for the rendered prompt")
109
114
  parser.add_argument("--project-root", default=None, help="AI-visible project root used for rendered prompt paths")
115
+ parser.add_argument(
116
+ "--no-checkpoint-write",
117
+ action="store_true",
118
+ help="Render and validate a preview without creating or updating checkpoint state",
119
+ )
110
120
  parser.add_argument("--template", default=None, help="Custom legacy template path. Defaults to section assembly.")
111
- parser.add_argument("--mode", choices=["lite", "standard", "full"], default=None, help="Pipeline execution mode override")
112
121
  add_continuation_args(parser, "refactor")
113
122
  return parser.parse_args()
114
123
 
@@ -189,15 +198,39 @@ def format_scope_modules(scope):
189
198
  return _format_scope_list(scope, "modules")
190
199
 
191
200
 
201
+ def _test_path_list(value):
202
+ if not isinstance(value, list):
203
+ return []
204
+ return [str(item) for item in value if str(item).strip()]
205
+
206
+
207
+ def format_existing_tests(value):
208
+ if isinstance(value, bool):
209
+ coverage = "yes" if value else "no"
210
+ return "- Coverage declared: {} (specific test paths not supplied)".format(coverage)
211
+ tests = _test_path_list(value)
212
+ if tests:
213
+ return "\n".join("- `{}`".format(test) for test in tests)
214
+ return "- (none specified)"
215
+
216
+
192
217
  def format_behavior_preservation(bp):
193
218
  if not bp or not isinstance(bp, dict):
194
219
  return "- (no behavior preservation details)"
195
220
  lines = ["- **Strategy**: {}".format(bp.get("strategy", "unknown"))]
196
- existing_tests = bp.get("existing_tests", [])
197
- if existing_tests:
198
- lines.append("- **Existing Tests**:")
199
- lines.extend(" - `{}`".format(test) for test in existing_tests)
200
- new_tests_needed = bp.get("new_tests_needed", [])
221
+ existing_tests = bp.get("existing_tests")
222
+ if isinstance(existing_tests, bool):
223
+ lines.append(
224
+ "- **Existing Tests Cover Scope**: {}".format(
225
+ "yes" if existing_tests else "no"
226
+ )
227
+ )
228
+ else:
229
+ tests = _test_path_list(existing_tests)
230
+ if tests:
231
+ lines.append("- **Existing Tests**:")
232
+ lines.extend(" - `{}`".format(test) for test in tests)
233
+ new_tests_needed = _test_path_list(bp.get("new_tests_needed"))
201
234
  if new_tests_needed:
202
235
  lines.append("- **New Tests Needed**:")
203
236
  lines.extend(" - {}".format(test) for test in new_tests_needed)
@@ -289,46 +322,24 @@ def _args_project_root(args, script_dir):
289
322
  return resolve_project_root(script_dir)
290
323
 
291
324
 
292
- def determine_refactor_mode(args, refactor):
293
- if args.mode:
294
- return args.mode
295
- priority = str(refactor.get("priority", "medium")).lower()
296
- complexity = str(refactor.get("complexity", "medium")).lower()
297
- if priority == "critical" and complexity in ("high", "critical"):
298
- return "full"
299
- if complexity in ("high", "critical"):
300
- return "standard"
301
- return normalize_mode({"low": "lite", "medium": "lite"}.get(complexity, "lite"))
302
-
303
-
304
325
  def build_replacements(args, refactor, refactors, global_context, script_dir):
305
326
  project_root = _args_project_root(args, script_dir)
306
327
  resolve_prompt_platform(project_root)
307
328
 
308
- state_dir = (
309
- os.path.abspath(args.state_dir)
310
- if args.state_dir
311
- else os.path.join(project_root, ".prizmkit", "state", "refactor")
312
- )
313
- session_status_path = os.path.join(state_dir, args.refactor_id, "sessions", args.session_id, "session-status.json")
314
-
315
329
  scope = refactor.get("scope", {})
316
330
  bp = refactor.get("behavior_preservation", {})
317
331
  behavior_strategy = bp.get("strategy", "test-gate") if isinstance(bp, dict) else "test-gate"
318
- existing_tests = bp.get("existing_tests", []) if isinstance(bp, dict) else []
319
- if not isinstance(existing_tests, list):
320
- existing_tests = []
321
- new_tests_needed = bp.get("new_tests_needed", []) if isinstance(bp, dict) else []
322
- if not isinstance(new_tests_needed, list):
323
- new_tests_needed = []
324
- existing_tests_str = "\n".join("- `{}`".format(test) for test in existing_tests) if existing_tests else "- (none specified)"
332
+ existing_tests = bp.get("existing_tests") if isinstance(bp, dict) else None
333
+ new_tests_needed = _test_path_list(
334
+ bp.get("new_tests_needed") if isinstance(bp, dict) else None
335
+ )
336
+ existing_tests_str = format_existing_tests(existing_tests)
325
337
  new_tests_str = "\n".join("- {}".format(test) for test in new_tests_needed) if new_tests_needed else "- (none specified)"
326
338
 
327
339
  browser_enabled, browser_tool, browser_verify_steps, browser_blocking = browser_enabled_from_item(refactor)
328
340
  dev_port = detect_dev_server_port(project_root)
329
341
  dev_url = "http://localhost:{}".format(dev_port) if dev_port.isdigit() else "<UNKNOWN_DETECT_FROM_PROJECT_CONFIG>"
330
342
 
331
- pipeline_mode = determine_refactor_mode(args, refactor)
332
343
  replacements = {
333
344
  "{{SESSION_LOG_PATH}}": os.path.join(".prizmkit", "state", "refactor", args.refactor_id, "sessions", args.session_id, "logs", "session.log"),
334
345
  "{{RUN_ID}}": args.run_id,
@@ -346,16 +357,15 @@ def build_replacements(args, refactor, refactors, global_context, script_dir):
346
357
  "{{NEW_TESTS_NEEDED}}": new_tests_str,
347
358
  "{{PRIORITY}}": refactor.get("priority", "medium"),
348
359
  "{{COMPLEXITY}}": refactor.get("complexity", "medium"),
349
- "{{PIPELINE_MODE}}": pipeline_mode,
350
360
  "{{REFACTOR_DESCRIPTION}}": refactor.get("description", ""),
351
361
  "{{USER_CONTEXT}}": format_user_context(refactor.get("user_context", [])),
352
362
  "{{ACCEPTANCE_CRITERIA}}": format_acceptance_criteria(refactor.get("acceptance_criteria", [])),
353
363
  "{{AC_CHECKLIST}}": format_ac_checklist(refactor.get("acceptance_criteria", [])),
354
364
  "{{DEPENDENCIES}}": format_dependencies(refactor.get("dependencies", []), refactors),
355
365
  "{{GLOBAL_CONTEXT}}": format_global_context(global_context, project_root),
356
- "{{SESSION_STATUS_PATH}}": session_status_path,
357
366
  "{{PROJECT_ROOT}}": project_root,
358
367
  "{{ARTIFACT_DIR}}": ".prizmkit/refactor/{}".format(args.refactor_id),
368
+ "{{FAMILY_ARTIFACTS}}": "├── refactor-report.md\n├── completion-summary.json",
359
369
  "{{CHECKPOINT_PATH}}": os.path.join(".prizmkit", "refactor", args.refactor_id, "workflow-checkpoint.json"),
360
370
  "{{CHECKPOINT_SYSTEM}}": read_checkpoint_system_section(script_dir),
361
371
  "{{TIMESTAMP}}": "",
@@ -404,24 +414,22 @@ def render_template(template_content, replacements, resume_phase, refactor):
404
414
  return replace_placeholders(process_conditional_blocks(template_content, resume_phase, refactor), replacements)
405
415
 
406
416
 
407
- def _refactor_header(pipeline_mode):
408
- title = "# Dev-Pipeline Refactor Session Bootstrap — {}\n".format(pipeline_mode.title())
409
- desc = {
410
- "lite": "**Tier 1 — Scoped Refactor Guidance**: use the active skills and runtime contracts for planning, implementation, review, and behavior verification.",
411
- "standard": "**Tier 2 Refactor Review Gates**: use the active skills and runtime contracts for planning, implementation, review, and behavior verification.",
412
- "full": "**Tier 3 — Full Refactor Guardrails**: use the active skills and runtime contracts for planning, implementation, review, recovery, and behavior verification.",
413
- }.get(pipeline_mode, "**Refactor pipeline**")
414
- return title + "\n" + desc + "\n"
417
+ def _refactor_header():
418
+ return (
419
+ "# Dev-Pipeline Refactor Session Bootstrap — Canonical Guidance\n\n"
420
+ "Use the active skills and runtime contracts for planning, implementation, "
421
+ "review, behavior verification, retrospective, and runtime-owned commit execution.\n"
422
+ )
415
423
 
416
424
 
417
- def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, browser_tool="auto"):
425
+ def assemble_refactor_sections(sections_dir, browser_enabled, browser_tool="auto"):
418
426
  sections = [
419
- ("header", _refactor_header(pipeline_mode)),
427
+ ("header", _refactor_header()),
420
428
  ("refactor-session-context", load_section(sections_dir, "refactor-session-context.md")),
421
429
  ("mission", load_section(sections_dir, "refactor-mission.md")),
422
430
  ("refactor-task-contract", load_section(sections_dir, "refactor-task-contract.md")),
423
431
  ("context-budget-rules", load_section(sections_dir, "context-budget-rules.md")),
424
- ("refactor-artifacts", load_section(sections_dir, "refactor-artifacts.md")),
432
+ ("artifact-manifest", load_section(sections_dir, "artifact-manifest.md")),
425
433
  ("checkpoint-system", load_section(sections_dir, "checkpoint-system.md")),
426
434
  ("execution-header", "---\n\n## Execution\n"),
427
435
  ("refactor-phase-init", load_section(sections_dir, "refactor-phase-init.md")),
@@ -430,7 +438,6 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, bro
430
438
  sections.extend([
431
439
  ("refactor-phase-implement", load_section(sections_dir, "refactor-phase-implement.md")),
432
440
  ("refactor-phase-review", load_section(sections_dir, "refactor-phase-review.md")),
433
- ("refactor-phase-test", load_section(sections_dir, "refactor-phase-test.md")),
434
441
  ])
435
442
  if browser_enabled:
436
443
  browser_section_file = {
@@ -439,9 +446,10 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, bro
439
446
  }.get(browser_tool, "phase-browser-verification-auto.md")
440
447
  sections.append(("phase-browser", load_section(sections_dir, browser_section_file)))
441
448
  sections.extend([
442
- ("headless-commit-authorization", load_section(sections_dir, "headless-commit-authorization.md")),
449
+ ("refactor-phase-test", load_section(sections_dir, "refactor-phase-test.md")),
443
450
  ("refactor-phase-commit-report", load_section(sections_dir, "refactor-phase-commit-report.md")),
444
- ("refactor-session-status", load_section(sections_dir, "refactor-session-status.md")),
451
+ ("retrospective", load_section(sections_dir, "retrospective.md")),
452
+ ("runtime-commit-handoff", load_section(sections_dir, "runtime-commit-handoff.md")),
445
453
  ("refactor-critical-paths", load_section(sections_dir, "refactor-critical-paths.md")),
446
454
  ("failure-capture", load_section(sections_dir, "failure-capture.md")),
447
455
  ("refactor-reminders", load_section(sections_dir, "refactor-reminders.md")),
@@ -449,20 +457,27 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, bro
449
457
  return sections
450
458
 
451
459
 
452
- def generate_refactor_checkpoint(refactor_id, session_id, pipeline_mode="standard", sections=None):
460
+ def generate_refactor_checkpoint(
461
+ refactor_id, session_id, sections=None, *, browser_enabled=False,
462
+ ):
453
463
  if sections is None:
454
464
  sections = [
455
465
  ("refactor-phase-init", ""),
456
466
  ("refactor-phase-plan", ""),
457
467
  ("refactor-phase-implement", ""),
458
468
  ("refactor-phase-review", ""),
469
+ ]
470
+ if browser_enabled:
471
+ sections.append(("phase-browser", ""))
472
+ sections.extend([
459
473
  ("refactor-phase-test", ""),
460
474
  ("refactor-phase-commit-report", ""),
461
- ]
475
+ ("retrospective", ""),
476
+ ("runtime-commit-handoff", ""),
477
+ ])
462
478
  return generate_checkpoint_from_sections(
463
479
  sections,
464
480
  REFACTOR_SECTION_TO_SKILL,
465
- pipeline_mode,
466
481
  "refactor-pipeline",
467
482
  refactor_id,
468
483
  refactor_id,
@@ -504,7 +519,6 @@ def main():
504
519
  global_context = {}
505
520
 
506
521
  replacements = build_replacements(args, refactor, refactors, global_context, script_dir)
507
- pipeline_mode = replacements["{{PIPELINE_MODE}}"]
508
522
  browser_enabled = replacements["{{BROWSER_ENABLED}}"] == "true"
509
523
 
510
524
  use_sections = os.path.isdir(sections_dir) and not args.template
@@ -512,16 +526,17 @@ def main():
512
526
  if use_sections:
513
527
  try:
514
528
  sections = assemble_refactor_sections(
515
- pipeline_mode, sections_dir, browser_enabled,
529
+ sections_dir, browser_enabled,
516
530
  browser_tool=replacements["{{BROWSER_TOOL}}"],
517
531
  )
518
532
  rendered = render_from_sections(sections, replacements)
519
533
  except FileNotFoundError as exc:
520
- LOGGER.warning("Refactor section assembly failed (%s), falling back to legacy template", exc)
521
- use_sections = False
534
+ emit_failure("Refactor section assembly failed: {}".format(exc))
522
535
 
523
536
  if not use_sections:
524
- template_path = args.template or os.path.join(templates_dir, "refactor-bootstrap-prompt.md")
537
+ if not args.template:
538
+ emit_failure("Canonical Refactor prompt sections are unavailable")
539
+ template_path = args.template
525
540
  template_content, err = read_text_file(template_path)
526
541
  if err:
527
542
  emit_failure("Template error: {}".format(err))
@@ -537,7 +552,7 @@ def main():
537
552
  logger=LOGGER,
538
553
  )
539
554
  if not is_valid:
540
- LOGGER.error("Rendered refactor prompt failed validation: %s", "; ".join(errors))
555
+ emit_failure("Rendered refactor prompt failed validation: {}".format("; ".join(errors)))
541
556
 
542
557
  err = write_output(args.output, rendered)
543
558
  if err:
@@ -545,9 +560,13 @@ def main():
545
560
 
546
561
  project_root = _args_project_root(args, script_dir)
547
562
  checkpoint_path = os.path.join(project_root, replacements["{{CHECKPOINT_PATH}}"])
548
- os.makedirs(os.path.dirname(checkpoint_path), exist_ok=True)
563
+ if not args.no_checkpoint_write:
564
+ os.makedirs(os.path.dirname(checkpoint_path), exist_ok=True)
549
565
  checkpoint = generate_refactor_checkpoint(
550
- args.refactor_id, args.session_id, pipeline_mode, sections if use_sections else None,
566
+ args.refactor_id,
567
+ args.session_id,
568
+ sections if use_sections else None,
569
+ browser_enabled=browser_enabled,
551
570
  )
552
571
  if not any(step.get("skill") == "prizmkit-test" for step in checkpoint["steps"]):
553
572
  emit_failure("Refactor checkpoint is missing the mandatory prizmkit-test stage")
@@ -562,7 +581,7 @@ def main():
562
581
  resume_from="prizmkit-implement",
563
582
  )
564
583
 
565
- if (args.resume_phase != "null" or is_continuation(args)) and os.path.exists(checkpoint_path):
584
+ if not args.no_checkpoint_write and (args.resume_phase != "null" or is_continuation(args)) and os.path.exists(checkpoint_path):
566
585
  try:
567
586
  with open(checkpoint_path, "r", encoding="utf-8") as f:
568
587
  existing = json.load(f)
@@ -571,14 +590,32 @@ def main():
571
590
  except (json.JSONDecodeError, KeyError) as exc:
572
591
  LOGGER.warning("Existing refactor checkpoint corrupted (%s) — generating fresh", exc)
573
592
 
574
- with open(checkpoint_path, "w", encoding="utf-8") as f:
575
- json.dump(checkpoint, f, indent=2, ensure_ascii=False)
576
- LOGGER.info("Wrote refactor checkpoint to %s", checkpoint_path)
593
+ if not args.no_checkpoint_write:
594
+ with open(checkpoint_path, "w", encoding="utf-8") as f:
595
+ json.dump(checkpoint, f, indent=2, ensure_ascii=False)
596
+ LOGGER.info("Wrote refactor checkpoint to %s", checkpoint_path)
577
597
 
578
598
  if is_continuation(args):
579
599
  rendered = append_continuation_handoff(
580
600
  rendered, args, project_root, args.task_type, args.refactor_id, args.refactor_id, checkpoint,
581
601
  )
602
+ final_valid, final_warnings, final_errors = validate_rendered(
603
+ rendered,
604
+ required_markers=[
605
+ ("## Your Mission", "Mission section"),
606
+ ("## Execution", "Execution section"),
607
+ ("## Failure Capture", "Failure Capture Protocol"),
608
+ ],
609
+ logger=LOGGER,
610
+ )
611
+ if not final_valid:
612
+ emit_failure(
613
+ "Rendered refactor continuation prompt failed validation: {}".format(
614
+ "; ".join(final_errors)
615
+ )
616
+ )
617
+ warnings.extend(final_warnings)
618
+ errors.extend(final_errors)
582
619
  err = write_output(args.output, rendered)
583
620
  if err:
584
621
  emit_failure(err)
@@ -586,9 +623,8 @@ def main():
586
623
  output = {
587
624
  "success": True,
588
625
  "output_path": os.path.abspath(args.output),
589
- "checkpoint_path": checkpoint_path,
626
+ "checkpoint_path": "" if args.no_checkpoint_write else checkpoint_path,
590
627
  "model": refactor.get("model", ""),
591
- "pipeline_mode": pipeline_mode,
592
628
  "render_mode": "sections" if use_sections else "legacy",
593
629
  "validation_warnings": len(warnings),
594
630
  "validation_errors": len(errors),
@@ -16,6 +16,7 @@ if _PIPELINE_ROOT not in sys.path:
16
16
 
17
17
  from prizmkit_runtime.checkpoint_state import ( # noqa: E402
18
18
  VALID_CHECKPOINT_STATUSES,
19
+ VALID_REPAIR_SCOPES,
19
20
  expected_status_for_stage_result,
20
21
  )
21
22
  from prizmkit_runtime.test_result import valid_test_artifact_pair # noqa: E402
@@ -48,9 +49,11 @@ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
48
49
  }
49
50
  if stage_result == "TEST_PASS":
50
51
  result.update(
51
- next_stage="prizmkit-retrospective",
52
- resume_from="prizmkit-retrospective",
53
- reason="project-native tests passed",
52
+ resumable=True,
53
+ next_stage="family-report",
54
+ resume_from="family-report",
55
+ route=["family-report", "prizmkit-retrospective"],
56
+ reason="project-native tests passed; family reports precede retrospective",
54
57
  )
55
58
  return result
56
59
  if stage_result == "TEST_BLOCKED":
@@ -62,16 +65,7 @@ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
62
65
  terminal_status="WORKFLOW_BLOCKED",
63
66
  )
64
67
  return result
65
- if stage_result == "TEST_NEEDS_FIXES":
66
- result.update(
67
- blocked=True,
68
- resumable=False,
69
- reason="prizmkit-test stopped with a known remaining correction",
70
- blocked_reason="test_needs_fixes",
71
- terminal_status="WORKFLOW_BLOCKED",
72
- )
73
- return result
74
- if stage_result != "REVIEW_NEEDS_FIXES":
68
+ if stage_result not in {"REVIEW_NEEDS_FIXES", "TEST_NEEDS_FIXES"}:
75
69
  result.update(
76
70
  blocked=True,
77
71
  reason="unknown stage result is unsafe",
@@ -87,13 +81,27 @@ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
87
81
  terminal_status="WORKFLOW_BLOCKED",
88
82
  )
89
83
  return result
84
+ if repair_scope not in VALID_REPAIR_SCOPES:
85
+ result.update(
86
+ blocked=True,
87
+ reason="repair scope is missing or unsafe",
88
+ blocked_reason="unsafe_repair_scope",
89
+ terminal_status="WORKFLOW_BLOCKED",
90
+ )
91
+ return result
90
92
 
91
93
  result["repair_round"] = current_round + 1
94
+ reason = (
95
+ "test findings require implementation, fresh review, and fresh testing"
96
+ if stage_result == "TEST_NEEDS_FIXES"
97
+ else "review findings require implementation and fresh review"
98
+ )
92
99
  result.update(
100
+ resumable=True,
93
101
  next_stage="prizmkit-implement",
94
102
  resume_from="prizmkit-implement",
95
103
  route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
96
- reason="review findings require implementation and fresh review",
104
+ reason=reason,
97
105
  )
98
106
  return result
99
107
 
@@ -117,7 +125,7 @@ def pipeline_checkpoint_metadata(artifact_dir, stage="plan",
117
125
  return {
118
126
  "schema_version": 1,
119
127
  "artifact_dir": artifact_dir,
120
- "orchestrator": "prizmkit-l4",
128
+ "orchestrator": "pipeline-runtime",
121
129
  "stage": stage,
122
130
  "current_stage": current_stage,
123
131
  "status": status,
@@ -176,7 +184,7 @@ def validate_rendered(content, required_markers=None, logger=None):
176
184
 
177
185
  unreplaced = re.findall(r"\{\{[A-Z][A-Z_0-9]+\}\}", content)
178
186
  if unreplaced:
179
- warnings.append(
187
+ errors.append(
180
188
  "Unreplaced placeholders: {}".format(", ".join(sorted(set(unreplaced))))
181
189
  )
182
190
 
@@ -309,7 +317,6 @@ def _contract_steps(contract):
309
317
  def generate_checkpoint_from_sections(
310
318
  sections,
311
319
  step_mapping,
312
- pipeline_mode,
313
320
  workflow_type,
314
321
  item_id,
315
322
  item_slug,
@@ -359,7 +366,6 @@ def generate_checkpoint_from_sections(
359
366
  return {
360
367
  "version": 1,
361
368
  "workflow_type": workflow_type,
362
- "pipeline_mode": pipeline_mode,
363
369
  "item_id": item_id,
364
370
  "item_slug": item_slug,
365
371
  "session_id": session_id,
@@ -409,10 +415,18 @@ def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger
409
415
  artifacts = step.get("required_artifacts", [])
410
416
  skill = step.get("skill", "")
411
417
  stage_result = previous.get("stage_result") if isinstance(previous, dict) else None
412
- verdict_valid = (
413
- (skill != "prizmkit-code-review" or stage_result == "REVIEW_PASS")
414
- and (skill != "prizmkit-test" or stage_result == "TEST_PASS")
415
- )
418
+ expected_results = {
419
+ "context-snapshot-and-plan": "PLAN_READY",
420
+ "bug-diagnosis-and-plan": "PLAN_READY",
421
+ "prizmkit-plan": "PLAN_READY",
422
+ "prizmkit-implement": "IMPLEMENTED",
423
+ "prizmkit-code-review": "REVIEW_PASS",
424
+ "prizmkit-test": "TEST_PASS",
425
+ "prizmkit-retrospective": "RETRO_COMPLETE",
426
+ "prizmkit-committer": "COMMITTED",
427
+ }
428
+ expected_result = expected_results.get(skill)
429
+ verdict_valid = expected_result is None or stage_result == expected_result
416
430
  if verdict_valid and validator(skill, artifacts):
417
431
  step["status"] = "completed"
418
432
  if stage_result:
@@ -441,25 +455,6 @@ def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger
441
455
  return fresh
442
456
 
443
457
 
444
- def determine_mode_from_complexity(value):
445
- """Map a coarse complexity/severity value to lite/standard/full."""
446
- mapping = {
447
- "low": "lite",
448
- "medium": "lite",
449
- "minor": "lite",
450
- "high": "standard",
451
- "major": "standard",
452
- "critical": "full",
453
- }
454
- return mapping.get(str(value or "").lower(), "lite")
455
-
456
-
457
- def normalize_mode(value, default="lite"):
458
- """Normalize a mode string to lite/standard/full."""
459
- value = str(value or "").lower()
460
- return value if value in {"lite", "standard", "full"} else default
461
-
462
-
463
458
  def detect_dev_server_port(project_root):
464
459
  """Return a detected dev-server port string, or an unknown placeholder."""
465
460
  unknown = "<UNKNOWN_DETECT_FROM_PROJECT_CONFIG>"
@@ -1003,11 +1003,8 @@ def action_status(bug_list_data, state_dir, project_root=None):
1003
1003
  bs = load_bug_status(state_dir, bid)
1004
1004
  retry_count = bs.get("retry_count", 0)
1005
1005
  max_retries_val = bs.get("max_retries", 3)
1006
- # Read phase cursor from checkpoint (authoritative when valid).
1006
+ # Read the authoritative checkpoint cursor without mutating cached runtime state.
1007
1007
  resume_phase = _checkpoint_phase_or_cached(project_root, bid, bs)
1008
- if resume_phase != bs.get("resume_from_phase"):
1009
- bs["resume_from_phase"] = resume_phase
1010
- save_bug_status(state_dir, bid, bs)
1011
1008
 
1012
1009
  if bstatus in counts:
1013
1010
  counts[bstatus] += 1
@@ -14,6 +14,7 @@ if _PIPELINE_ROOT not in sys.path:
14
14
 
15
15
  from prizmkit_runtime.checkpoint_state import ( # noqa: E402
16
16
  MAX_OUTER_REPAIR_ROUNDS,
17
+ PLAN_RESULTS,
17
18
  REVIEW_RESULTS,
18
19
  SKILL_WORKFLOW_STAGES,
19
20
  STEP_ID_PATTERN,
@@ -110,9 +111,16 @@ def _mandatory_predecessor_verdict_error(steps, index, workflow_type):
110
111
  preceding = steps[:index]
111
112
  review = next((item for item in preceding if item.get("skill") == "prizmkit-code-review"), None)
112
113
  test = next((item for item in preceding if item.get("skill") == "prizmkit-test"), None)
114
+ skill = steps[index].get("skill")
115
+ if skill == "prizmkit-implement":
116
+ planning = [
117
+ item for item in preceding
118
+ if item.get("stage_result") in PLAN_RESULTS
119
+ ]
120
+ if len(planning) != 1 or planning[0].get("status") != "completed" or planning[0].get("stage_result") != "PLAN_READY":
121
+ return "Implementation requires a completed PLAN_READY predecessor"
113
122
  if review is None and test is None:
114
123
  return None
115
- skill = steps[index].get("skill")
116
124
  if skill == "prizmkit-test":
117
125
  if not review or review.get("status") != "completed" or review.get("stage_result") != "REVIEW_PASS":
118
126
  return "Test stage requires a completed REVIEW_PASS predecessor"
@@ -170,23 +178,27 @@ def _validate_semantic_update(step, semantic_update):
170
178
 
171
179
 
172
180
  def _apply_repair_policy(l4_state, stage_result, repair_scope):
173
- if stage_result not in {"REVIEW_NEEDS_FIXES", "TEST_NEEDS_FIXES", "TEST_BLOCKED"}:
174
- return False
175
- current_round = l4_state.get("repair_round", 0)
176
- if not isinstance(current_round, int) or isinstance(current_round, bool):
177
- current_round = MAX_OUTER_REPAIR_ROUNDS
178
- if stage_result in {"TEST_NEEDS_FIXES", "TEST_BLOCKED"}:
181
+ terminal_blockers = {
182
+ "PLAN_BLOCKED": "plan_blocked",
183
+ "IMPLEMENT_REPAIR": "implementation_repair",
184
+ "IMPLEMENT_BLOCKED": "implementation_blocked",
185
+ "TEST_BLOCKED": "test_blocked",
186
+ "RETRO_BLOCKED": "retrospective_blocked",
187
+ "COMMIT_BLOCKED": "commit_blocked",
188
+ }
189
+ if stage_result in terminal_blockers:
179
190
  l4_state.update(
180
191
  terminal_status="WORKFLOW_BLOCKED",
181
- blocked_reason=(
182
- "test_needs_fixes"
183
- if stage_result == "TEST_NEEDS_FIXES"
184
- else "test_blocked"
185
- ),
192
+ blocked_reason=terminal_blockers[stage_result],
186
193
  current_stage=None,
187
194
  next_stage=None,
188
195
  )
189
196
  return False
197
+ if stage_result not in {"REVIEW_NEEDS_FIXES", "TEST_NEEDS_FIXES"}:
198
+ return False
199
+ current_round = l4_state.get("repair_round", 0)
200
+ if not isinstance(current_round, int) or isinstance(current_round, bool):
201
+ current_round = MAX_OUTER_REPAIR_ROUNDS
190
202
  if current_round >= MAX_OUTER_REPAIR_ROUNDS:
191
203
  l4_state.update(
192
204
  repair_round=MAX_OUTER_REPAIR_ROUNDS,
@@ -205,12 +217,36 @@ def _apply_repair_policy(l4_state, stage_result, repair_scope):
205
217
  )
206
218
  return False
207
219
  l4_state["repair_round"] = current_round + 1
220
+ l4_state["repair_scope"] = repair_scope
208
221
  l4_state["terminal_status"] = None
209
222
  l4_state["blocked_reason"] = None
210
223
  l4_state["next_stage"] = "prizmkit-implement"
211
224
  return True
212
225
 
213
226
 
227
+ def _prepare_repair_reentry(data, index):
228
+ """Rewind downstream gates when a routed repair re-enters implementation."""
229
+ step = data["steps"][index]
230
+ if step.get("skill") != "prizmkit-implement":
231
+ return
232
+ state_key = semantic_state_key(str(data.get("workflow_type") or ""))
233
+ l4_state = data.get(state_key)
234
+ if not isinstance(l4_state, dict):
235
+ return
236
+ if (
237
+ l4_state.get("next_stage") != "prizmkit-implement"
238
+ or l4_state.get("stage_result")
239
+ not in {"REVIEW_NEEDS_FIXES", "TEST_NEEDS_FIXES"}
240
+ ):
241
+ return
242
+ for later in data["steps"][index + 1:]:
243
+ later["status"] = "pending"
244
+ later.pop("stage_result", None)
245
+ later.pop("note", None)
246
+ l4_state["terminal_status"] = None
247
+ l4_state["blocked_reason"] = None
248
+
249
+
214
250
  def _sync_cursor(data, l4_state, preserve_next_stage=False):
215
251
  active = next(
216
252
  (step for step in data["steps"] if step.get("status") not in TERMINAL_STEP_STATUSES),
@@ -291,6 +327,9 @@ def update_checkpoint(
291
327
  suffix = " Available: {}".format(", ".join(available)) if available else ""
292
328
  return {"ok": False, "error": "{}{}".format(find_error or "Step not found.", suffix)}
293
329
 
330
+ if new_status == "in_progress":
331
+ _prepare_repair_reentry(data, index)
332
+
294
333
  if new_status in {"in_progress", "completed", "skipped"} and not _predecessors_terminal(data["steps"], index):
295
334
  return {
296
335
  "ok": False,
@@ -306,6 +345,11 @@ def update_checkpoint(
306
345
  return {"ok": False, "error": verdict_error}
307
346
 
308
347
  semantic_update = _normalize_semantic_update(semantic_update)
348
+ if semantic_update.get("stage_result") == "COMMITTED":
349
+ return {
350
+ "ok": False,
351
+ "error": "COMMITTED is Runtime-owned and cannot be written by the Prompt checkpoint helper",
352
+ }
309
353
  semantic_error = _validate_semantic_update(step, semantic_update)
310
354
  if semantic_error:
311
355
  return {"ok": False, "error": semantic_error}
@@ -319,6 +363,10 @@ def update_checkpoint(
319
363
  stage_result = stage_result or step.get("stage_result")
320
364
  if stage_result != "TEST_PASS":
321
365
  return {"ok": False, "error": "Test completion requires TEST_PASS"}
366
+ if new_status == "completed" and step.get("skill") == "prizmkit-committer":
367
+ stage_result = stage_result or step.get("stage_result")
368
+ if stage_result != "COMMITTED":
369
+ return {"ok": False, "error": "Committer completion requires Runtime-owned COMMITTED"}
322
370
  expected_status = expected_status_for_stage_result(stage_result)
323
371
  if expected_status is not None and new_status != expected_status:
324
372
  return {
@@ -350,7 +398,7 @@ def update_checkpoint(
350
398
  if key in semantic_update:
351
399
  l4_state[key] = semantic_update[key]
352
400
  l4_state["schema_version"] = 1
353
- l4_state["orchestrator"] = "prizmkit-l4"
401
+ l4_state["orchestrator"] = "pipeline-runtime"
354
402
  skill = step.get("skill")
355
403
  l4_state["stage"] = SKILL_WORKFLOW_STAGES.get(skill, skill)
356
404
  l4_state["status"] = new_status