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
@@ -76,6 +76,102 @@ def _write_family_plan(paths, kind, items):
76
76
  return plan_path
77
77
 
78
78
 
79
+ @pytest.mark.parametrize(
80
+ ("kind", "item_id", "filename", "list_key", "schema", "item"),
81
+ [
82
+ (
83
+ "feature", "F-001", "feature-list.json", "features",
84
+ "dev-pipeline-feature-list-v1",
85
+ {
86
+ "id": "F-001", "title": "Preview Feature", "description": "Preview only",
87
+ "priority": "high", "dependencies": [],
88
+ "acceptance_criteria": ["Prompt validates"], "status": "pending",
89
+ },
90
+ ),
91
+ (
92
+ "bugfix", "B-001", "bug-fix-list.json", "bugs",
93
+ "dev-pipeline-bug-fix-list-v1",
94
+ {
95
+ "id": "B-001", "title": "Preview Bug", "description": "Preview only",
96
+ "severity": "high", "priority": "high", "dependencies": [],
97
+ "error_source": {"type": "user_report", "reproduction_steps": ["preview"]},
98
+ "verification_type": "automated",
99
+ "acceptance_criteria": ["Prompt validates"], "status": "pending",
100
+ },
101
+ ),
102
+ (
103
+ "refactor", "R-001", "refactor-list.json", "refactors",
104
+ "dev-pipeline-refactor-list-v1",
105
+ {
106
+ "id": "R-001", "title": "Preview Refactor", "description": "Preview only",
107
+ "scope": {"files": ["src/example.js"], "modules": ["example"]},
108
+ "type": "simplify", "priority": "high", "complexity": "low",
109
+ "behavior_preservation": {"strategy": "test-gate", "existing_tests": True},
110
+ "acceptance_criteria": ["Prompt validates"],
111
+ "dependencies": [], "status": "pending",
112
+ },
113
+ ),
114
+ ],
115
+ )
116
+ def test_actual_dry_run_is_read_only_and_successful(
117
+ tmp_path, kind, item_id, filename, list_key, schema, item,
118
+ ):
119
+ from prizmkit_runtime.paths import resolve_runtime_paths
120
+ from prizmkit_runtime.runners import run_pipeline_command
121
+
122
+ project = tmp_path / kind
123
+ plans = project / ".prizmkit" / "plans"
124
+ plans.mkdir(parents=True)
125
+ plan_path = plans / filename
126
+ plan_path.write_text(
127
+ json.dumps({"$schema": schema, "project_name": "Dry Run", list_key: [item]}),
128
+ encoding="utf-8",
129
+ )
130
+ fake_cli = project / "fake-ai.py"
131
+ fake_cli.write_text(
132
+ "#!/usr/bin/env python3\nfrom pathlib import Path\nPath('AI_WAS_LAUNCHED').write_text('bad')\n",
133
+ encoding="utf-8",
134
+ )
135
+ fake_cli.chmod(0o755)
136
+ (project / ".prizmkit" / "config.json").write_text(
137
+ json.dumps({
138
+ "platform": "pi",
139
+ "ai_cli": str(fake_cli),
140
+ "ai_cli_launch": {"profile": "custom", "prompt_arg": "--prompt"},
141
+ }),
142
+ encoding="utf-8",
143
+ )
144
+ subprocess.run(["git", "init", "-b", "main"], cwd=project, check=True, stdout=subprocess.DEVNULL)
145
+ subprocess.run(["git", "config", "user.name", "Dry Run Test"], cwd=project, check=True)
146
+ subprocess.run(["git", "config", "user.email", "dry-run@example.invalid"], cwd=project, check=True)
147
+ subprocess.run(["git", "add", "."], cwd=project, check=True)
148
+ subprocess.run(["git", "commit", "-m", "initial"], cwd=project, check=True, stdout=subprocess.DEVNULL)
149
+ paths = resolve_runtime_paths(pipeline_root=PIPELINE_ROOT, project_root=project)
150
+ branch_before = subprocess.check_output(["git", "branch", "--show-current"], cwd=project, text=True).strip()
151
+ head_before = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=project, text=True).strip()
152
+ status_before = subprocess.check_output(["git", "status", "--porcelain=v1", "-uall"], cwd=project, text=True)
153
+
154
+ run_args = (
155
+ (str(plan_path), "--dry-run")
156
+ if kind == "feature"
157
+ else (item_id, str(plan_path), "--dry-run")
158
+ )
159
+ result = run_pipeline_command(kind, "run", run_args, paths)
160
+
161
+ assert result.exit_code == 0
162
+ assert "processed=1 completed=False stopped_reason=dry_run" in result.render()
163
+ assert "last_status: dry_run" in result.render()
164
+ assert json.loads(plan_path.read_text(encoding="utf-8"))[list_key][0]["status"] == "pending"
165
+ assert subprocess.check_output(["git", "branch", "--show-current"], cwd=project, text=True).strip() == branch_before
166
+ assert subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=project, text=True).strip() == head_before
167
+ assert subprocess.check_output(["git", "status", "--porcelain=v1", "-uall"], cwd=project, text=True) == status_before
168
+ assert not (project / "AI_WAS_LAUNCHED").exists()
169
+ assert not (project / ".prizmkit" / "state").exists()
170
+ assert not (project / ".prizmkit" / "specs").exists()
171
+ assert not (project / ".prizmkit" / "bugfix").exists()
172
+ assert not (project / ".prizmkit" / "refactor").exists()
173
+
174
+
79
175
  def _get_next_result(kind, paths):
80
176
  from prizmkit_runtime.runner_models import family_for, parse_invocation
81
177
  from prizmkit_runtime.runner_status import get_next
@@ -97,22 +193,22 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
97
193
  "feature_state",
98
194
  [
99
195
  "prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
100
- "prizmkit-retrospective", "prizmkit-committer", "completion-summary",
196
+ "completion-summary", "prizmkit-retrospective", "prizmkit-committer",
101
197
  ],
102
198
  ),
103
199
  "bugfix-pipeline": (
104
200
  "bugfix_state",
105
201
  [
106
202
  "prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
107
- "prizmkit-retrospective", "prizmkit-committer", "bug-report",
203
+ "bug-report", "prizmkit-retrospective", "prizmkit-committer",
108
204
  ],
109
205
  ),
110
206
  "refactor-pipeline": (
111
207
  "refactor_state",
112
208
  [
113
209
  "prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
114
- "prizmkit-retrospective", "prizmkit-committer", "refactor-report",
115
- "completion-summary",
210
+ "refactor-report", "completion-summary", "prizmkit-retrospective",
211
+ "prizmkit-committer",
116
212
  ],
117
213
  ),
118
214
  }
@@ -128,6 +224,8 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
128
224
  "required_artifacts": [],
129
225
  "depends_on": previous,
130
226
  }
227
+ if skill == "prizmkit-implement":
228
+ step["stage_result"] = "IMPLEMENTED"
131
229
  if skill == "prizmkit-code-review":
132
230
  step["stage_result"] = "REVIEW_PASS"
133
231
  if skill == "prizmkit-test":
@@ -137,6 +235,10 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
137
235
  str(relative_artifact / "test-report.md"),
138
236
  str(relative_artifact / "test-result.json"),
139
237
  ]
238
+ if skill == "prizmkit-retrospective":
239
+ step["stage_result"] = "RETRO_COMPLETE"
240
+ if skill == "prizmkit-committer":
241
+ step["stage_result"] = "COMMITTED"
140
242
  steps.append(step)
141
243
  previous = step["id"]
142
244
  artifact_dir.mkdir(parents=True, exist_ok=True)
@@ -158,12 +260,31 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
158
260
  },
159
261
  "repair_rounds": 0,
160
262
  "production_changed": False,
161
- "review_required": False,
162
- "review_scope": None,
163
263
  "unresolved_items": [],
164
264
  }),
165
265
  encoding="utf-8",
166
266
  )
267
+ runtime_commit_hash = "b" * 40
268
+ runtime_base_head = "a" * 40
269
+ head = subprocess.run(
270
+ ["git", "rev-parse", "HEAD"],
271
+ cwd=project_root,
272
+ stdout=subprocess.PIPE,
273
+ stderr=subprocess.DEVNULL,
274
+ text=True,
275
+ check=False,
276
+ )
277
+ parent = subprocess.run(
278
+ ["git", "rev-parse", "HEAD^"],
279
+ cwd=project_root,
280
+ stdout=subprocess.PIPE,
281
+ stderr=subprocess.DEVNULL,
282
+ text=True,
283
+ check=False,
284
+ )
285
+ if head.returncode == 0 and parent.returncode == 0:
286
+ runtime_commit_hash = head.stdout.strip()
287
+ runtime_base_head = parent.stdout.strip()
167
288
  checkpoint = artifact_dir / "workflow-checkpoint.json"
168
289
  checkpoint.write_text(
169
290
  json.dumps({
@@ -173,6 +294,8 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
173
294
  state_key: {
174
295
  "repair_round": 0,
175
296
  "terminal_status": "WORKFLOW_COMPLETED",
297
+ "runtime_base_head": runtime_base_head,
298
+ "runtime_commit_hash": runtime_commit_hash,
176
299
  },
177
300
  }),
178
301
  encoding="utf-8",
@@ -403,7 +526,7 @@ def test_runner_models_parse_legacy_args_and_environment(tmp_path):
403
526
  invocation = parse_invocation(
404
527
  family,
405
528
  "run",
406
- ("custom-list.json", "F-2", "--features", "F-003:F-001", "--max-retries", "7", "--max-infra-retries=5", "--mode", "full"),
529
+ ("custom-list.json", "F-2", "--features", "F-003:F-001", "--max-retries", "7", "--max-infra-retries=5"),
407
530
  )
408
531
  env = RunnerEnvironment.from_env(
409
532
  {
@@ -422,7 +545,7 @@ def test_runner_models_parse_legacy_args_and_environment(tmp_path):
422
545
  assert invocation.item_filter == "F-003:F-001"
423
546
  assert invocation.max_retries == 7
424
547
  assert invocation.max_infra_retries == 5
425
- assert invocation.mode == "full"
548
+ assert not hasattr(invocation, "mode")
426
549
  assert env.stop_on_failure is True
427
550
  assert env.auto_push is True
428
551
  assert env.dev_branch == "dev/custom"
@@ -1082,7 +1205,6 @@ def test_prompt_generation_result_preserves_per_item_model(monkeypatch, tmp_path
1082
1205
  "output_path": str(session_paths.prompt_path),
1083
1206
  "checkpoint_path": str(paths.project_root / ".prizmkit" / "bugfix" / "B-001" / "workflow-checkpoint.json"),
1084
1207
  "model": "per-item-model",
1085
- "pipeline_mode": "standard",
1086
1208
  }
1087
1209
  ),
1088
1210
  stderr="",
@@ -1130,7 +1252,6 @@ def test_prompt_generation_passes_explicit_execution_root_to_generator(monkeypat
1130
1252
  "output_path": str(session_paths.prompt_path),
1131
1253
  "checkpoint_path": str(execution_root / ".prizmkit" / "specs" / "001-low" / "workflow-checkpoint.json"),
1132
1254
  "model": "",
1133
- "pipeline_mode": "full",
1134
1255
  }
1135
1256
  ),
1136
1257
  stderr="",
@@ -1195,7 +1316,6 @@ def _install_runner_session_fakes(monkeypatch, runners, *, statuses=("success",)
1195
1316
  return PromptGenerationResult(
1196
1317
  output_path=session_paths.prompt_path,
1197
1318
  model="per-item-model",
1198
- pipeline_mode="full",
1199
1319
  checkpoint_path=execution_root / ".prizmkit" / "specs" / "001-low" / "workflow-checkpoint.json",
1200
1320
  artifact_path=execution_root / ".prizmkit" / "specs" / "001-low",
1201
1321
  raw={},
@@ -1528,7 +1648,6 @@ def test_explicit_worktree_materializes_ignored_support_assets_before_prompt_and
1528
1648
  return PromptGenerationResult(
1529
1649
  output_path=session_paths.prompt_path,
1530
1650
  model="",
1531
- pipeline_mode="full",
1532
1651
  checkpoint_path=execution_root / ".prizmkit" / "specs" / "001-support" / "workflow-checkpoint.json",
1533
1652
  artifact_path=execution_root / ".prizmkit" / "specs" / "001-support",
1534
1653
  raw={},
@@ -1615,7 +1734,6 @@ def test_has_branch_completion_evidence_requires_task_branch_ahead_of_base(tmp_p
1615
1734
  subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=tmp_path, check=True)
1616
1735
  subprocess.run(["git", "config", "user.name", "Test"], cwd=tmp_path, check=True)
1617
1736
  artifact_dir = tmp_path / ".prizmkit" / "specs" / "001-done"
1618
- _write_semantic_completion_checkpoint(tmp_path, artifact_dir)
1619
1737
  (tmp_path / "base.txt").write_text("base", encoding="utf-8")
1620
1738
  subprocess.run(["git", "add", "base.txt"], cwd=tmp_path, check=True)
1621
1739
  subprocess.run(["git", "commit", "-m", "base"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
@@ -1623,6 +1741,7 @@ def test_has_branch_completion_evidence_requires_task_branch_ahead_of_base(tmp_p
1623
1741
  (tmp_path / "done.txt").write_text("done", encoding="utf-8")
1624
1742
  subprocess.run(["git", "add", "done.txt"], cwd=tmp_path, check=True)
1625
1743
  subprocess.run(["git", "commit", "-m", "done"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1744
+ _write_semantic_completion_checkpoint(tmp_path, artifact_dir)
1626
1745
 
1627
1746
  assert has_branch_completion_evidence(tmp_path, "main", "dev/F-001", artifact_dir) is True
1628
1747
 
@@ -1994,7 +2113,7 @@ def test_foreground_runner_emits_structured_feature_progress(monkeypatch, tmp_pa
1994
2113
  assert "Feature: F-001 — Readable output" in captured.err
1995
2114
  assert "Code retry: 1 / 3" in captured.err
1996
2115
  assert "Preflight: no user-visible changes to preserve before feature task F-001" in captured.err
1997
- assert "Pipeline mode: full (Full Guidance)" in captured.err
2116
+ assert "Pipeline mode:" not in captured.err
1998
2117
  assert "Spawning AI CLI session: F-001-session-1" in captured.err
1999
2118
  assert "Session result: success" in captured.err
2000
2119
 
@@ -3166,6 +3285,14 @@ def test_classification_accepts_final_success_after_internal_stream_retry(tmp_pa
3166
3285
  stdout=subprocess.PIPE,
3167
3286
  text=True,
3168
3287
  ).stdout.strip()
3288
+ (tmp_path / "done.txt").write_text("done", encoding="utf-8")
3289
+ subprocess.run(["git", "add", "done.txt"], cwd=tmp_path, check=True)
3290
+ subprocess.run(
3291
+ ["git", "commit", "-m", "done"],
3292
+ cwd=tmp_path,
3293
+ check=True,
3294
+ stdout=subprocess.DEVNULL,
3295
+ )
3169
3296
  artifact_dir = tmp_path / ".prizmkit" / "bugfix" / "B-004"
3170
3297
  checkpoint = _write_semantic_completion_checkpoint(tmp_path, artifact_dir, "bugfix-pipeline")
3171
3298
 
@@ -3313,7 +3440,7 @@ def test_classification_keeps_pre_completion_provider_error_as_infra_error(tmp_p
3313
3440
  assert classification.reason == "ai_runtime_or_provider_error"
3314
3441
 
3315
3442
 
3316
- def test_classification_accepts_terminal_success_with_completed_checkpoint_without_git_delta(tmp_path):
3443
+ def test_classification_rejects_completed_checkpoint_without_runtime_git_receipt(tmp_path):
3317
3444
  from prizmkit_runtime.runner_classification import classify_session
3318
3445
  from prizmkit_runtime.runner_models import PromptGenerationResult
3319
3446
  from prizmkit_runtime.sessions import AISessionCommand, AISessionResult
@@ -3353,8 +3480,8 @@ def test_classification_accepts_terminal_success_with_completed_checkpoint_witho
3353
3480
  )
3354
3481
 
3355
3482
  classification = classify_session(raw, project_root=tmp_path, base_head=base_head, prompt=prompt)
3356
- assert classification.session_status == "success"
3357
- assert classification.reason == "terminal_success_with_semantic_checkpoint"
3483
+ assert classification.session_status == "commit_missing"
3484
+ assert classification.reason == "runtime_commit_receipt_mismatch"
3358
3485
 
3359
3486
 
3360
3487
  def test_classification_preserves_success_before_context_overflow(tmp_path):
@@ -3915,6 +4042,14 @@ def test_pi_length_stop_does_not_override_completed_checkpoint(tmp_path):
3915
4042
  from prizmkit_runtime.status import ProgressSummary
3916
4043
 
3917
4044
  base_head = _init_git_repo_for_invalid_checkpoint_test(tmp_path)
4045
+ (tmp_path / "done.txt").write_text("done", encoding="utf-8")
4046
+ subprocess.run(["git", "add", "done.txt"], cwd=tmp_path, check=True)
4047
+ subprocess.run(
4048
+ ["git", "commit", "-m", "done"],
4049
+ cwd=tmp_path,
4050
+ check=True,
4051
+ stdout=subprocess.DEVNULL,
4052
+ )
3918
4053
  artifact_dir = tmp_path / ".prizmkit" / "specs" / "001-length-complete"
3919
4054
  checkpoint = _write_semantic_completion_checkpoint(tmp_path, artifact_dir)
3920
4055
  prompt = PromptGenerationResult(
@@ -4361,6 +4496,21 @@ def test_semantic_completion_classification_has_cross_family_parity(tmp_path, wo
4361
4496
  (tmp_path / "base.txt").write_text("base", encoding="utf-8")
4362
4497
  subprocess.run(["git", "add", "base.txt"], cwd=tmp_path, check=True)
4363
4498
  subprocess.run(["git", "commit", "-m", "base"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
4499
+ base_head = subprocess.run(
4500
+ ["git", "rev-parse", "HEAD"],
4501
+ cwd=tmp_path,
4502
+ check=True,
4503
+ stdout=subprocess.PIPE,
4504
+ text=True,
4505
+ ).stdout.strip()
4506
+ (tmp_path / "done.txt").write_text("done", encoding="utf-8")
4507
+ subprocess.run(["git", "add", "done.txt"], cwd=tmp_path, check=True)
4508
+ subprocess.run(
4509
+ ["git", "commit", "-m", "done"],
4510
+ cwd=tmp_path,
4511
+ check=True,
4512
+ stdout=subprocess.DEVNULL,
4513
+ )
4364
4514
  artifact = tmp_path / ".prizmkit" / "artifacts" / workflow_type
4365
4515
  checkpoint = _write_semantic_completion_checkpoint(tmp_path, artifact, workflow_type)
4366
4516
  log = tmp_path / f"{workflow_type}.log"
@@ -4383,7 +4533,7 @@ def test_semantic_completion_classification_has_cross_family_parity(tmp_path, wo
4383
4533
  classification = classify_session(
4384
4534
  raw,
4385
4535
  project_root=tmp_path,
4386
- base_head="",
4536
+ base_head=base_head,
4387
4537
  prompt=PromptGenerationResult(
4388
4538
  output_path=tmp_path / "prompt.md",
4389
4539
  checkpoint_path=checkpoint,
@@ -86,6 +86,25 @@ def _write_checkout(
86
86
  return checkout
87
87
 
88
88
 
89
+ def _write_raw_checkout(
90
+ project: Path,
91
+ family: str,
92
+ directory_id: str,
93
+ payload: dict[str, object],
94
+ ) -> Path:
95
+ checkout = (
96
+ project
97
+ / ".prizmkit"
98
+ / "state"
99
+ / STATE_DIRS[family]
100
+ / directory_id
101
+ / "checkout.json"
102
+ )
103
+ checkout.parent.mkdir(parents=True, exist_ok=True)
104
+ checkout.write_text(json.dumps(payload) + "\n", encoding="utf-8")
105
+ return checkout
106
+
107
+
89
108
  def _repository_snapshot(project: Path) -> tuple[str, str, str]:
90
109
  return (
91
110
  _git(project, "branch", "--show-current"),
@@ -209,3 +228,95 @@ def test_zero_candidates_filters_invalid_records_without_history_fallback_or_ses
209
228
  assert _repository_snapshot(project) == repository_before
210
229
  assert _historical_snapshot(historical) == history_before
211
230
  assert sorted(path.name for path in historical.parent.iterdir()) == ["historical-only"]
231
+
232
+
233
+ def test_detector_rejects_malformed_or_mismatched_checkout_identity(tmp_path):
234
+ project = tmp_path / "project"
235
+ _init_repository(project)
236
+ invalid_records = (
237
+ (
238
+ "feature",
239
+ "F-not-an-id",
240
+ "dev/F-not-an-id",
241
+ {
242
+ "task_type": "feature",
243
+ "task_id": "F-not-an-id",
244
+ "state": "active",
245
+ "active_dev_branch": "dev/F-not-an-id",
246
+ "base_branch": "main",
247
+ "checkout_mode": "branch",
248
+ },
249
+ ),
250
+ (
251
+ "bugfix",
252
+ "B-004",
253
+ "bugfix/B-004-missing-id",
254
+ {
255
+ "task_type": "bugfix",
256
+ "state": "active",
257
+ "active_dev_branch": "bugfix/B-004-missing-id",
258
+ "base_branch": "main",
259
+ "checkout_mode": "branch",
260
+ },
261
+ ),
262
+ (
263
+ "refactor",
264
+ "R-005",
265
+ "refactor/R-005-wrong-type",
266
+ {
267
+ "task_type": "feature",
268
+ "task_id": "R-005",
269
+ "state": "active",
270
+ "active_dev_branch": "refactor/R-005-wrong-type",
271
+ "base_branch": "main",
272
+ "checkout_mode": "branch",
273
+ },
274
+ ),
275
+ (
276
+ "feature",
277
+ "F-006",
278
+ "dev/F-006-path-mismatch",
279
+ {
280
+ "task_type": "feature",
281
+ "task_id": "F-007",
282
+ "state": "active",
283
+ "active_dev_branch": "dev/F-006-path-mismatch",
284
+ "base_branch": "main",
285
+ "checkout_mode": "branch",
286
+ },
287
+ ),
288
+ )
289
+ for family, directory_id, branch, payload in invalid_records:
290
+ _git(project, "branch", branch)
291
+ _write_raw_checkout(project, family, directory_id, payload)
292
+
293
+ detector = _load_detector("recovery_workflow_invalid_identity")
294
+
295
+ assert detector.detect_candidates(project) == []
296
+
297
+
298
+ def test_recovery_workflow_metadata_matches_detector_only_contract():
299
+ metadata = json.loads((REPO_ROOT / "core" / "skills" / "_metadata.json").read_text())
300
+ recovery = metadata["skills"]["recovery-workflow"]
301
+ description = recovery["description"].lower()
302
+
303
+ assert recovery["hasScripts"] is True
304
+ assert "active feature, bugfix, or refactor checkout records" in description
305
+ assert "operation-first" in description
306
+ assert "direct requirement" not in description
307
+
308
+
309
+ def test_canonical_recovery_and_cli_guidance_has_no_retired_contracts():
310
+ env_example = (REPO_ROOT / "dev-pipeline" / ".env.example").read_text(encoding="utf-8")
311
+ readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
312
+ readme_en = (REPO_ROOT / "README_EN.md").read_text(encoding="utf-8")
313
+
314
+ assert "cli.py feature run" not in env_example
315
+ assert "cli.py run feature" in env_example
316
+ assert "从断点继续" not in readme
317
+ assert "reset/clean/unskip/complete" not in readme
318
+ assert "reset/clean/reset_state/complete" in readme
319
+ assert "Auto-detect + resume from breakpoint" not in readme_en
320
+ assert "interrupted at Phase 4" not in readme_en
321
+ assert "Resumes from Phase 5" not in readme_en
322
+ assert "Does not execute the command or infer a lifecycle phase" in readme_en
@@ -110,8 +110,6 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
110
110
  },
111
111
  "repair_rounds": 0,
112
112
  "production_changed": False,
113
- "review_required": False,
114
- "review_scope": None,
115
113
  "unresolved_items": [],
116
114
  }),
117
115
  encoding="utf-8",