prizmkit 1.1.130 → 1.1.134

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 (119) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/claude/command-adapter.js +0 -2
  3. package/bundled/dev-pipeline/.env.example +1 -1
  4. package/bundled/dev-pipeline/assets/skill-subagent-integration.md +11 -6
  5. package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +445 -8
  6. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +2 -9
  7. package/bundled/dev-pipeline/prizmkit_runtime/processes.py +21 -1
  8. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +87 -66
  9. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +53 -3
  10. package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +55 -25
  11. package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +4 -0
  12. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +119 -18
  13. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +3 -2
  14. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +411 -17
  15. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +57 -14
  16. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +5 -4
  17. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +55 -2
  18. package/bundled/dev-pipeline/scripts/prompt_framework.py +152 -1
  19. package/bundled/dev-pipeline/scripts/update-bug-status.py +53 -0
  20. package/bundled/dev-pipeline/scripts/update-checkpoint.py +294 -69
  21. package/bundled/dev-pipeline/scripts/update-feature-status.py +57 -0
  22. package/bundled/dev-pipeline/scripts/update-refactor-status.py +53 -0
  23. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +5 -5
  24. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +28 -22
  25. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +24 -10
  26. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +20 -2
  27. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +2 -2
  28. package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +1 -1
  29. package/bundled/dev-pipeline/templates/sections/bugfix-phase-manual-verification.md +5 -10
  30. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +9 -19
  31. package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +21 -0
  32. package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +1 -1
  33. package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +10 -10
  34. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
  35. package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +15 -0
  36. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +2 -2
  37. package/bundled/dev-pipeline/templates/sections/phase-commit.md +2 -2
  38. package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +26 -23
  39. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +5 -5
  40. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +15 -11
  41. package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +1 -1
  42. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +6 -6
  43. package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +21 -0
  44. package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +1 -1
  45. package/bundled/dev-pipeline/templates/sections/subagent-timeout-recovery.md +1 -1
  46. package/bundled/dev-pipeline/templates/sections/task-contract.md +4 -0
  47. package/bundled/dev-pipeline/tests/test_checkpoint_state.py +362 -3
  48. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +349 -48
  49. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +129 -0
  50. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +91 -0
  51. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +567 -23
  52. package/bundled/dev-pipeline/tests/test_unified_cli.py +37 -10
  53. package/bundled/skills/_metadata.json +63 -26
  54. package/bundled/skills/app-planner/SKILL.md +4 -3
  55. package/bundled/skills/bug-fix-workflow/SKILL.md +89 -180
  56. package/bundled/skills/bug-planner/SKILL.md +12 -27
  57. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +131 -220
  58. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +36 -90
  59. package/bundled/skills/feature-pipeline-launcher/SKILL.md +129 -271
  60. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +35 -76
  61. package/bundled/skills/feature-planner/SKILL.md +27 -22
  62. package/bundled/skills/feature-planner/assets/planning-guide.md +4 -4
  63. package/bundled/skills/feature-workflow/SKILL.md +94 -121
  64. package/bundled/skills/prizmkit/SKILL.md +130 -94
  65. package/bundled/skills/prizmkit/references/workflow-state-protocol.md +181 -0
  66. package/bundled/skills/prizmkit-code-review/SKILL.md +132 -86
  67. package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +243 -0
  68. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +42 -1
  69. package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +181 -0
  70. package/bundled/skills/prizmkit-code-review/scripts/render_review_report.py +93 -1
  71. package/bundled/skills/prizmkit-committer/SKILL.md +125 -48
  72. package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +181 -0
  73. package/bundled/skills/prizmkit-implement/SKILL.md +99 -73
  74. package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +1 -1
  75. package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +181 -0
  76. package/bundled/skills/prizmkit-init/SKILL.md +5 -5
  77. package/bundled/skills/prizmkit-plan/SKILL.md +146 -105
  78. package/bundled/skills/prizmkit-plan/assets/plan-template.md +18 -0
  79. package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +242 -0
  80. package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +4 -4
  81. package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +181 -0
  82. package/bundled/skills/prizmkit-retrospective/SKILL.md +111 -53
  83. package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +7 -6
  84. package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +5 -4
  85. package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +181 -0
  86. package/bundled/skills/prizmkit-test/SKILL.md +52 -6
  87. package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +63 -12
  88. package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +1 -1
  89. package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +13 -0
  90. package/bundled/skills/prizmkit-test/references/evidence-protocol.md +6 -1
  91. package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +8 -1
  92. package/bundled/skills/prizmkit-test/references/examples.md +1 -1
  93. package/bundled/skills/prizmkit-test/references/test-generation-steps.md +4 -1
  94. package/bundled/skills/prizmkit-test/references/test-report-template.md +1 -1
  95. package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +15 -0
  96. package/bundled/skills/prizmkit-test/references/workflow-state-protocol.md +181 -0
  97. package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +744 -23
  98. package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +194 -15
  99. package/bundled/skills/prizmkit-workflow/SKILL.md +266 -0
  100. package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +181 -0
  101. package/bundled/skills/recovery-workflow/SKILL.md +62 -241
  102. package/bundled/skills/recovery-workflow/evals/evals.json +17 -33
  103. package/bundled/skills/recovery-workflow/references/detection.md +28 -52
  104. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +105 -439
  105. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +136 -275
  106. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +53 -88
  107. package/bundled/skills/refactor-planner/SKILL.md +12 -57
  108. package/bundled/skills/refactor-planner/references/behavior-preservation.md +111 -230
  109. package/bundled/skills/refactor-planner/references/error-recovery.md +37 -0
  110. package/bundled/skills/refactor-planner/references/planning-phases.md +11 -17
  111. package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +1 -1
  112. package/bundled/skills/refactor-workflow/SKILL.md +98 -139
  113. package/bundled/templates/project-memory-template.md +4 -4
  114. package/package.json +1 -1
  115. package/src/index.js +4 -0
  116. package/src/prompts.js +10 -3
  117. package/src/scaffold.js +1 -1
  118. package/bundled/dev-pipeline/tests/test-deploy-safety.sh +0 -223
  119. package/bundled/skills/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
@@ -97,10 +97,11 @@ Implement the minimal fix (red → green):
97
97
  """\
98
98
  Verify fix quality:
99
99
  1. Run `/prizmkit-code-review` with the current bugfix artifact directory.
100
- 2. The current Main Agent is the only Code Review executor. It reviews the complete current change for up to ten rounds, directly repairs accepted findings, and verifies repairs.
101
- 3. Converge only when accepted and unresolved findings are both zero; missing required evidence or round-ten non-convergence produces NEEDS_FIXES.
102
- 4. Do not delegate review directly or indirectly. Do not invoke another review skill or review workflow. Do not relabel delegated work as a finder, verifier, audit, compatibility review, verification, or gap sweep.
103
- 5. `review-report.md` is the only persisted review artifact. Continue only after its last Final Result is valid; preserve append-only progress for recovery.""",
100
+ 2. Run the mandatory Main-Agent review over the complete current change for up to ten rounds; directly repair accepted findings and verify repairs.
101
+ 3. After Main-Agent convergence, allow only the one skill-owned independent Reviewer under the strict structural capability gate. If any capability is unavailable or unproven, record downgrade and create none.
102
+ 4. Converge only when accepted and unresolved findings are both zero; missing required evidence or round-ten non-convergence produces NEEDS_FIXES.
103
+ 5. Do not invoke another review skill or add review execution outside the skill contract.
104
+ 6. `review-report.md` is the only persisted review artifact. Continue only after its last Final Result is valid; preserve append-only progress for recovery.""",
104
105
  ),
105
106
  6: (
106
107
  "User Verification",
@@ -22,9 +22,11 @@ from prompt_framework import (
22
22
  merge_checkpoint_state,
23
23
  mode_agent_count,
24
24
  normalize_mode,
25
+ pipeline_checkpoint_metadata,
25
26
  read_text_file,
26
27
  render_from_sections,
27
28
  replace_placeholders,
29
+ route_pipeline_repair,
28
30
  validate_rendered,
29
31
  write_output,
30
32
  )
@@ -34,6 +36,30 @@ from utils import enrich_global_context, helper_replacements, load_json_file, re
34
36
  LOGGER = setup_logging("generate-refactor-prompt")
35
37
 
36
38
 
39
+ def route_refactor_repair(stage_result, repair_scope=None, repair_round=0):
40
+ """Map Refactor review/test outcomes to the shared safe route contract."""
41
+ return route_pipeline_repair(stage_result, repair_scope, repair_round)
42
+
43
+
44
+ def refactor_checkpoint_metadata(artifact_dir, evidence=None, stage="plan",
45
+ status="PLAN_READY", stage_result=None,
46
+ repair_scope=None, repair_round=0,
47
+ next_stage="prizmkit-implement",
48
+ resume_from="prizmkit-implement"):
49
+ """Build Refactor L4 handoff metadata while preserving Refactor L1 state."""
50
+ return pipeline_checkpoint_metadata(
51
+ artifact_dir,
52
+ evidence=evidence,
53
+ stage=stage,
54
+ status=status,
55
+ stage_result=stage_result,
56
+ repair_scope=repair_scope,
57
+ repair_round=repair_round,
58
+ next_stage=next_stage,
59
+ resume_from=resume_from,
60
+ )
61
+
62
+
37
63
  REFACTOR_SECTION_TO_SKILL = {
38
64
  "refactor-phase-init": checkpoint_step("prizmkit-init", "Initialize", [".prizmkit/refactor/{slug}"]),
39
65
  "refactor-phase-plan": checkpoint_step(
@@ -48,6 +74,14 @@ REFACTOR_SECTION_TO_SKILL = {
48
74
  "prizmkit-code-review", "Review — Code Review & Behavior Verification",
49
75
  [".prizmkit/refactor/{slug}/review-report.md"],
50
76
  ),
77
+ "refactor-phase-test": checkpoint_step(
78
+ "prizmkit-test", "Post-Review Test Gate",
79
+ [
80
+ ".prizmkit/test/evidence/*/manifest.json",
81
+ ".prizmkit/test/evidence/*/verdict.json",
82
+ ".prizmkit/test/evidence/*/validation.json",
83
+ ],
84
+ ),
51
85
  "phase-browser": checkpoint_step("browser-verification", "Browser Verification", []),
52
86
  "refactor-phase-commit-report": checkpoint_group([
53
87
  ("prizmkit-retrospective", "Retrospective", []),
@@ -377,7 +411,7 @@ def _refactor_header(pipeline_mode):
377
411
  title = "# Dev-Pipeline Refactor Session Bootstrap — {}\n".format(pipeline_mode.title())
378
412
  desc = {
379
413
  "lite": "**Tier 1 — Single Agent**: direct behavior-preserving refactor by the main orchestrator.",
380
- "standard": "**Tier 2 — Main-Agent Review Gates**: direct refactor with Main-Agent-only review gates.",
414
+ "standard": "**Tier 2 — Main-Agent Review Gates**: direct refactor with mandatory Main-Agent review and optional strict capability-gated independent correctness review.",
381
415
  "full": "**Tier 3 — Full Refactor Guardrails**: direct refactor with stronger behavior-preservation evidence.",
382
416
  }.get(pipeline_mode, "**Refactor pipeline**")
383
417
  return title + "\n" + desc + "\n"
@@ -399,6 +433,7 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, bro
399
433
  sections.extend([
400
434
  ("refactor-phase-implement", load_section(sections_dir, "refactor-phase-implement.md")),
401
435
  ("refactor-phase-review", load_section(sections_dir, "refactor-phase-review.md")),
436
+ ("refactor-phase-test", load_section(sections_dir, "refactor-phase-test.md")),
402
437
  ])
403
438
  if browser_enabled:
404
439
  browser_section_file = {
@@ -407,6 +442,7 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, bro
407
442
  }.get(browser_tool, "phase-browser-verification-auto.md")
408
443
  sections.append(("phase-browser", load_section(sections_dir, browser_section_file)))
409
444
  sections.extend([
445
+ ("headless-commit-authorization", load_section(sections_dir, "headless-commit-authorization.md")),
410
446
  ("refactor-phase-commit-report", load_section(sections_dir, "refactor-phase-commit-report.md")),
411
447
  ("refactor-session-status", load_section(sections_dir, "refactor-session-status.md")),
412
448
  ("refactor-critical-paths", load_section(sections_dir, "refactor-critical-paths.md")),
@@ -423,6 +459,7 @@ def generate_refactor_checkpoint(refactor_id, session_id, pipeline_mode="standar
423
459
  ("refactor-phase-plan", ""),
424
460
  ("refactor-phase-implement", ""),
425
461
  ("refactor-phase-review", ""),
462
+ ("refactor-phase-test", ""),
426
463
  ("refactor-phase-commit-report", ""),
427
464
  ]
428
465
  return generate_checkpoint_from_sections(
@@ -438,7 +475,11 @@ def generate_refactor_checkpoint(refactor_id, session_id, pipeline_mode="standar
438
475
 
439
476
 
440
477
  def merge_refactor_checkpoint_state(existing, fresh, project_root):
441
- return merge_checkpoint_state(existing, fresh, project_root, logger=LOGGER)
478
+ merged = merge_checkpoint_state(existing, fresh, project_root, logger=LOGGER)
479
+ existing_state = existing.get("refactor_state")
480
+ if isinstance(existing_state, dict):
481
+ merged["refactor_state"] = existing_state
482
+ return merged
442
483
 
443
484
 
444
485
  def emit_failure(message):
@@ -511,6 +552,18 @@ def main():
511
552
  checkpoint = generate_refactor_checkpoint(
512
553
  args.refactor_id, args.session_id, pipeline_mode, sections if use_sections else None,
513
554
  )
555
+ if not any(step.get("skill") == "prizmkit-test" for step in checkpoint["steps"]):
556
+ emit_failure("Refactor checkpoint is missing the mandatory prizmkit-test stage")
557
+ checkpoint["refactor_state"] = refactor_checkpoint_metadata(
558
+ replacements["{{ARTIFACT_DIR}}"],
559
+ stage="plan",
560
+ status="PLAN_READY",
561
+ stage_result=None,
562
+ repair_scope=None,
563
+ repair_round=0,
564
+ next_stage="prizmkit-implement",
565
+ resume_from="prizmkit-implement",
566
+ )
514
567
 
515
568
  if (args.resume_phase != "null" or is_continuation(args)) and os.path.exists(checkpoint_path):
516
569
  try:
@@ -10,6 +10,137 @@ import os
10
10
  import re
11
11
 
12
12
 
13
+ MAX_OUTER_REPAIR_ROUNDS = 3
14
+ REPAIR_SCOPES_REQUIRING_REVIEW = {
15
+ "production",
16
+ "runtime",
17
+ "schema",
18
+ "dependency",
19
+ "public-interface",
20
+ }
21
+
22
+
23
+ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
24
+ """Map review/test outcomes to bounded, safe L4 continuation routes."""
25
+ try:
26
+ current_round = int(repair_round)
27
+ except (TypeError, ValueError):
28
+ current_round = MAX_OUTER_REPAIR_ROUNDS
29
+ if current_round < 0:
30
+ current_round = MAX_OUTER_REPAIR_ROUNDS
31
+
32
+ result = {
33
+ "stage_result": stage_result,
34
+ "repair_scope": repair_scope,
35
+ "repair_round": current_round,
36
+ "blocked": False,
37
+ "resumable": False,
38
+ "next_stage": None,
39
+ "resume_from": None,
40
+ "route": [],
41
+ "reason": "",
42
+ "blocked_reason": None,
43
+ "terminal_status": None,
44
+ }
45
+ if stage_result == "TEST_PASS":
46
+ result.update(
47
+ next_stage="prizmkit-retrospective",
48
+ resume_from="prizmkit-retrospective",
49
+ reason="authoritative test evidence passed",
50
+ )
51
+ return result
52
+ if stage_result == "TEST_BLOCKED":
53
+ result.update(
54
+ blocked=True,
55
+ resumable=False,
56
+ reason="bounded automatic recovery cannot safely edit production",
57
+ blocked_reason="test_blocked",
58
+ terminal_status="WORKFLOW_BLOCKED",
59
+ )
60
+ return result
61
+ if stage_result not in {"REVIEW_NEEDS_FIXES", "TEST_FAIL"}:
62
+ result.update(
63
+ blocked=True,
64
+ reason="unknown stage result is unsafe",
65
+ blocked_reason="unknown_stage_result",
66
+ terminal_status="WORKFLOW_BLOCKED",
67
+ )
68
+ return result
69
+ if current_round >= MAX_OUTER_REPAIR_ROUNDS:
70
+ result.update(
71
+ blocked=True,
72
+ reason="maximum outer repair rounds reached",
73
+ blocked_reason="repair_round_limit",
74
+ terminal_status="WORKFLOW_BLOCKED",
75
+ )
76
+ return result
77
+
78
+ result["repair_round"] = current_round + 1
79
+ if stage_result == "REVIEW_NEEDS_FIXES":
80
+ result.update(
81
+ next_stage="prizmkit-implement",
82
+ resume_from="prizmkit-implement",
83
+ route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
84
+ reason="review findings require implementation and fresh review",
85
+ )
86
+ return result
87
+ if repair_scope == "test-infrastructure":
88
+ result.update(
89
+ next_stage="prizmkit-implement",
90
+ resume_from="prizmkit-implement",
91
+ route=["prizmkit-implement", "prizmkit-test"],
92
+ reason="test infrastructure failure must not edit production speculatively",
93
+ )
94
+ return result
95
+ if repair_scope in REPAIR_SCOPES_REQUIRING_REVIEW:
96
+ result.update(
97
+ next_stage="prizmkit-implement",
98
+ resume_from="prizmkit-implement",
99
+ route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
100
+ reason="production-facing failure requires review before retesting",
101
+ )
102
+ return result
103
+ result.update(
104
+ blocked=True,
105
+ reason="unknown repair scope has no safe automatic route",
106
+ blocked_reason="unsafe_repair_scope",
107
+ terminal_status="WORKFLOW_BLOCKED",
108
+ )
109
+ return result
110
+
111
+
112
+ def pipeline_checkpoint_metadata(artifact_dir, evidence=None, stage="plan",
113
+ status="PLAN_READY", stage_result=None,
114
+ repair_scope=None, repair_round=0,
115
+ next_stage="prizmkit-implement",
116
+ resume_from="prizmkit-implement",
117
+ blocked_reason=None, terminal_status=None):
118
+ """Build family-neutral semantic L4 metadata without replacing L1 state."""
119
+ evidence = evidence or {}
120
+ current_stage = None if terminal_status else stage
121
+ semantic_next_stage = None if terminal_status else next_stage
122
+ return {
123
+ "schema_version": 1,
124
+ "artifact_dir": artifact_dir,
125
+ "orchestrator": "prizmkit-l4",
126
+ "stage": stage,
127
+ "current_stage": current_stage,
128
+ "status": status,
129
+ "stage_result": stage_result,
130
+ "repair_scope": repair_scope,
131
+ "repair_round": repair_round,
132
+ "authoritative_evidence_paths": {
133
+ "manifest": evidence.get("manifest_path"),
134
+ "verdict": evidence.get("verdict_path"),
135
+ "validation": evidence.get("validation_path"),
136
+ },
137
+ "next_stage": semantic_next_stage,
138
+ "resume_from": resume_from,
139
+ "blocked_reason": blocked_reason,
140
+ "terminal_status": terminal_status,
141
+ }
142
+
143
+
13
144
  def read_text_file(path):
14
145
  """Read and return the text content of a file, plus an error string."""
15
146
  abs_path = os.path.abspath(path)
@@ -257,8 +388,19 @@ def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger
257
388
  previous_status = previous.get("status", "pending") if isinstance(previous, dict) else "pending"
258
389
  if previous_status == "completed":
259
390
  artifacts = step.get("required_artifacts", [])
260
- if validator(step.get("skill", ""), artifacts):
391
+ skill = step.get("skill", "")
392
+ stage_result = previous.get("stage_result") if isinstance(previous, dict) else None
393
+ verdict_valid = (
394
+ (skill != "prizmkit-code-review" or stage_result == "REVIEW_PASS")
395
+ and (skill != "prizmkit-test" or stage_result == "TEST_PASS")
396
+ )
397
+ if verdict_valid and validator(skill, artifacts):
261
398
  step["status"] = "completed"
399
+ if stage_result:
400
+ step["stage_result"] = stage_result
401
+ evidence = previous.get("authoritative_evidence_paths")
402
+ if isinstance(evidence, dict):
403
+ step["authoritative_evidence_paths"] = evidence
262
404
  continue
263
405
  if logger is not None:
264
406
  logger.warning(
@@ -271,6 +413,15 @@ def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger
271
413
  chain_broken = True
272
414
  step["status"] = "pending"
273
415
 
416
+ workflow_type = fresh.get("workflow_type", "")
417
+ state_key = {
418
+ "feature-pipeline": "feature_state",
419
+ "bugfix-pipeline": "bugfix_state",
420
+ "refactor-pipeline": "refactor_state",
421
+ }.get(workflow_type)
422
+ if state_key and isinstance(existing.get(state_key), dict):
423
+ fresh[state_key] = dict(existing[state_key])
424
+
274
425
  return fresh
275
426
 
276
427
 
@@ -46,6 +46,7 @@ SESSION_STATUS_VALUES = [
46
46
  "infra_error",
47
47
  "context_overflow",
48
48
  "stalled_context_continuation",
49
+ "workflow_blocked",
49
50
  "commit_missing",
50
51
  "docs_missing",
51
52
  "merge_conflict",
@@ -88,6 +89,7 @@ def parse_args():
88
89
  parser.add_argument("--continuation-summary-path", default=None, help="Optional continuation summary artifact path.")
89
90
  parser.add_argument("--no-progress-count", type=int, default=None, help="Consecutive context-overflow sessions without objective progress.")
90
91
  parser.add_argument("--progress-fingerprint", default=None, help="JSON progress fingerprint captured after the session.")
92
+ parser.add_argument("--checkpoint-state", default=None, help="JSON semantic L4 checkpoint snapshot captured after the session.")
91
93
  return parser.parse_args()
92
94
 
93
95
 
@@ -253,6 +255,37 @@ def _load_progress_fingerprint(raw):
253
255
  return {"unparsed": str(raw)}
254
256
 
255
257
 
258
+ SEMANTIC_CHECKPOINT_FIELDS = (
259
+ "current_stage",
260
+ "next_stage",
261
+ "stage_result",
262
+ "repair_scope",
263
+ "repair_round",
264
+ "authoritative_evidence_paths",
265
+ "blocked_reason",
266
+ "terminal_status",
267
+ )
268
+
269
+
270
+ def _load_checkpoint_state(raw):
271
+ if not raw:
272
+ return {}
273
+ try:
274
+ data = json.loads(raw)
275
+ except (TypeError, ValueError):
276
+ return {}
277
+ if not isinstance(data, dict):
278
+ return {}
279
+ return {key: data.get(key) for key in SEMANTIC_CHECKPOINT_FIELDS}
280
+
281
+
282
+ def _sync_semantic_checkpoint(status_data, args):
283
+ semantic = _load_checkpoint_state(getattr(args, "checkpoint_state", None))
284
+ if semantic:
285
+ status_data.update(semantic)
286
+ return {key: status_data.get(key) for key in SEMANTIC_CHECKPOINT_FIELDS}
287
+
288
+
256
289
  def _set_continuation_common(status_data, args, session_id):
257
290
  if args.active_dev_branch:
258
291
  status_data["active_dev_branch"] = args.active_dev_branch
@@ -494,6 +527,7 @@ def action_update(args, bug_list_path, state_dir):
494
527
  fingerprint = _load_progress_fingerprint(args.progress_fingerprint)
495
528
  if fingerprint is not None:
496
529
  bs["last_progress_fingerprint"] = fingerprint
530
+ semantic_checkpoint = _sync_semantic_checkpoint(bs, args)
497
531
 
498
532
 
499
533
  if session_status == "success":
@@ -560,6 +594,19 @@ def action_update(args, bug_list_path, state_dir):
560
594
  if err:
561
595
  error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
562
596
  return
597
+ elif session_status == "workflow_blocked":
598
+ # Semantic terminal state: preserve partial work without consuming any retry budget.
599
+ new_status = "needs_info"
600
+ bs["continuation_pending"] = False
601
+ bs["needs_attention"] = True
602
+ bs["terminal_status"] = "WORKFLOW_BLOCKED"
603
+ bs["blocked_reason"] = (
604
+ semantic_checkpoint.get("blocked_reason") or "workflow_blocked"
605
+ )
606
+ err = update_bug_in_list(bug_list_path, bug_id, new_status)
607
+ if err:
608
+ error_out("Failed to update .prizmkit/plans/bug-fix-list.json: {}".format(err))
609
+ return
563
610
  elif session_status == "stalled_context_continuation":
564
611
  # No-progress context-overflow stall pauses automation without consuming retry budgets.
565
612
  set_stalled_context_continuation_metadata(bs, args, session_id)
@@ -616,6 +663,7 @@ def action_update(args, bug_list_path, state_dir):
616
663
  "infra_error_count": bs.get("infra_error_count", 0),
617
664
  "max_infra_retries": max_infra_retries,
618
665
  "resume_from_phase": bs.get("resume_from_phase"),
666
+ "checkpoint_state": semantic_checkpoint,
619
667
  "updated_at": bs["updated_at"],
620
668
  }
621
669
  if session_status in ("commit_missing", "docs_missing", "merge_conflict"):
@@ -630,6 +678,11 @@ def action_update(args, bug_list_path, state_dir):
630
678
  summary["restart_policy"] = "context_overflow_continuation"
631
679
  summary.update(continuation_metadata_summary(bs))
632
680
  summary["artifacts_preserved"] = True
681
+ elif session_status == "workflow_blocked":
682
+ summary["restart_policy"] = "terminal_blocked"
683
+ summary.update(continuation_metadata_summary(bs))
684
+ summary["checkpoint_state"] = semantic_checkpoint
685
+ summary["artifacts_preserved"] = True
633
686
  elif session_status == "stalled_context_continuation":
634
687
  summary["restart_policy"] = "needs_attention"
635
688
  summary.update(continuation_metadata_summary(bs))