prizmkit 1.1.130 → 1.1.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/.env.example +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +445 -8
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +87 -66
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +53 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +55 -25
- package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +4 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +15 -1
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +396 -4
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +54 -1
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +54 -1
- package/bundled/dev-pipeline/scripts/prompt_framework.py +152 -1
- package/bundled/dev-pipeline/scripts/update-bug-status.py +53 -0
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +294 -69
- package/bundled/dev-pipeline/scripts/update-feature-status.py +57 -0
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +53 -0
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +20 -14
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +21 -4
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +18 -0
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +1 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +5 -15
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +21 -0
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +10 -10
- package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +16 -0
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +26 -23
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +12 -8
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +1 -1
- package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +21 -0
- package/bundled/dev-pipeline/tests/test_checkpoint_state.py +362 -3
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +310 -22
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +132 -0
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +91 -0
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +411 -18
- package/bundled/dev-pipeline/tests/test_unified_cli.py +3 -3
- package/bundled/skills/_metadata.json +62 -25
- package/bundled/skills/app-planner/SKILL.md +4 -3
- package/bundled/skills/bug-fix-workflow/SKILL.md +89 -180
- package/bundled/skills/bug-planner/SKILL.md +12 -27
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +131 -220
- package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +36 -90
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +129 -271
- package/bundled/skills/feature-pipeline-launcher/references/configuration.md +35 -76
- package/bundled/skills/feature-planner/SKILL.md +27 -22
- package/bundled/skills/feature-planner/assets/planning-guide.md +4 -4
- package/bundled/skills/feature-workflow/SKILL.md +94 -121
- package/bundled/skills/prizmkit/SKILL.md +130 -94
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-code-review/SKILL.md +114 -84
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +1 -1
- package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-committer/SKILL.md +131 -47
- package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +99 -73
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +1 -1
- package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-init/SKILL.md +5 -5
- package/bundled/skills/prizmkit-plan/SKILL.md +132 -105
- package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-retrospective/SKILL.md +111 -53
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +7 -6
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +5 -4
- package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-test/SKILL.md +28 -6
- package/bundled/skills/prizmkit-test/references/examples.md +1 -1
- package/bundled/skills/prizmkit-test/references/test-report-template.md +1 -1
- package/bundled/skills/prizmkit-test/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/prizmkit-workflow/SKILL.md +266 -0
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +181 -0
- package/bundled/skills/recovery-workflow/SKILL.md +62 -241
- package/bundled/skills/recovery-workflow/evals/evals.json +17 -33
- package/bundled/skills/recovery-workflow/references/detection.md +28 -52
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +105 -439
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +136 -275
- package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +53 -88
- package/bundled/skills/refactor-planner/SKILL.md +12 -57
- package/bundled/skills/refactor-planner/references/behavior-preservation.md +111 -230
- package/bundled/skills/refactor-planner/references/error-recovery.md +37 -0
- package/bundled/skills/refactor-planner/references/planning-phases.md +11 -17
- package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +1 -1
- package/bundled/skills/refactor-workflow/SKILL.md +98 -139
- package/bundled/templates/project-memory-template.md +4 -4
- package/package.json +1 -1
- package/src/index.js +4 -0
- package/src/prompts.js +10 -3
- package/src/scaffold.js +1 -1
- package/bundled/dev-pipeline/tests/test-deploy-safety.sh +0 -223
- package/bundled/skills/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
|
|
7
|
-
from prizmkit_runtime.checkpoint_state import load_checkpoint_state, read_checkpoint_cursor
|
|
7
|
+
from prizmkit_runtime.checkpoint_state import load_checkpoint_state, read_checkpoint_cursor, validate_checkpoint_data
|
|
8
8
|
from update_checkpoint import update_checkpoint
|
|
9
9
|
|
|
10
10
|
|
|
@@ -138,7 +138,7 @@ def test_update_checkpoint_rejects_ambiguous_skill_without_mutation(tmp_path):
|
|
|
138
138
|
|
|
139
139
|
def test_update_checkpoint_exact_id_updates_one_duplicate_skill_step(tmp_path):
|
|
140
140
|
path = _write(tmp_path / "workflow-checkpoint.json", _checkpoint([
|
|
141
|
-
_step("S01", "prizmkit-committer", "Commit First", "
|
|
141
|
+
_step("S01", "prizmkit-committer", "Commit First", "completed"),
|
|
142
142
|
_step("S02", "prizmkit-committer", "Commit Second", "pending", "S01"),
|
|
143
143
|
]))
|
|
144
144
|
|
|
@@ -147,7 +147,7 @@ def test_update_checkpoint_exact_id_updates_one_duplicate_skill_step(tmp_path):
|
|
|
147
147
|
|
|
148
148
|
assert result["ok"] is True
|
|
149
149
|
assert result["step_id"] == "S02"
|
|
150
|
-
assert data["steps"][0]["status"] == "
|
|
150
|
+
assert data["steps"][0]["status"] == "completed"
|
|
151
151
|
assert data["steps"][1]["status"] == "completed"
|
|
152
152
|
|
|
153
153
|
|
|
@@ -162,3 +162,362 @@ def test_update_checkpoint_invalid_checkpoint_fails_without_mutation(tmp_path):
|
|
|
162
162
|
assert result["ok"] is False
|
|
163
163
|
assert "invalid_status" in result["error"]
|
|
164
164
|
assert path.read_text(encoding="utf-8") == before
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _family_checkpoint(workflow_type, skills, *, semantic=None):
|
|
169
|
+
steps = []
|
|
170
|
+
previous = None
|
|
171
|
+
for index, skill in enumerate(skills, start=1):
|
|
172
|
+
step = _step(f"S{index:02d}", skill, skill, "completed", previous)
|
|
173
|
+
if skill == "prizmkit-code-review":
|
|
174
|
+
step["stage_result"] = "REVIEW_PASS"
|
|
175
|
+
if skill == "prizmkit-test":
|
|
176
|
+
step["stage_result"] = "TEST_PASS"
|
|
177
|
+
steps.append(step)
|
|
178
|
+
previous = step["id"]
|
|
179
|
+
payload = {"version": 1, "workflow_type": workflow_type, "steps": steps}
|
|
180
|
+
state_key = {
|
|
181
|
+
"feature-pipeline": "feature_state",
|
|
182
|
+
"bugfix-pipeline": "bugfix_state",
|
|
183
|
+
"refactor-pipeline": "refactor_state",
|
|
184
|
+
}[workflow_type]
|
|
185
|
+
payload[state_key] = semantic or {}
|
|
186
|
+
return payload
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _write_test_evidence(root, verdict="TEST_PASS", validation_result="passed", evidence_id="evidence-1"):
|
|
190
|
+
evidence = root / ".prizmkit" / "test" / "evidence" / evidence_id
|
|
191
|
+
evidence.mkdir(parents=True)
|
|
192
|
+
manifest = evidence / "manifest.json"
|
|
193
|
+
verdict_path = evidence / "verdict.json"
|
|
194
|
+
validation = evidence / "validation.json"
|
|
195
|
+
manifest.write_text(json.dumps({"evidence_id": evidence_id, "final_verdict": verdict}), encoding="utf-8")
|
|
196
|
+
verdict_path.write_text(json.dumps({"verdict": verdict}), encoding="utf-8")
|
|
197
|
+
validation.write_text(json.dumps({"verdict": verdict, "result": validation_result}), encoding="utf-8")
|
|
198
|
+
return {
|
|
199
|
+
"manifest": str(manifest.relative_to(root)),
|
|
200
|
+
"verdict": str(verdict_path.relative_to(root)),
|
|
201
|
+
"validation": str(validation.relative_to(root)),
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_semantic_completion_requires_family_sequence_verdicts_and_structured_evidence(tmp_path, monkeypatch):
|
|
206
|
+
monkeypatch.setattr(
|
|
207
|
+
"prizmkit_runtime.checkpoint_state._resolve_evidence_validator",
|
|
208
|
+
lambda _root: tmp_path / "validator.py",
|
|
209
|
+
)
|
|
210
|
+
monkeypatch.setattr(
|
|
211
|
+
"prizmkit_runtime.checkpoint_state._evidence_validator_passes",
|
|
212
|
+
lambda *_args: True,
|
|
213
|
+
)
|
|
214
|
+
paths = _write_test_evidence(tmp_path)
|
|
215
|
+
skills = [
|
|
216
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
217
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
218
|
+
]
|
|
219
|
+
payload = _family_checkpoint(
|
|
220
|
+
"feature-pipeline",
|
|
221
|
+
skills,
|
|
222
|
+
semantic={
|
|
223
|
+
"repair_round": 0,
|
|
224
|
+
"authoritative_evidence_paths": paths,
|
|
225
|
+
"terminal_status": "WORKFLOW_COMPLETED",
|
|
226
|
+
},
|
|
227
|
+
)
|
|
228
|
+
payload["steps"][2]["authoritative_evidence_paths"] = paths
|
|
229
|
+
checkpoint = tmp_path / ".prizmkit" / "specs" / "feature" / "workflow-checkpoint.json"
|
|
230
|
+
checkpoint.parent.mkdir(parents=True)
|
|
231
|
+
_write(checkpoint, payload)
|
|
232
|
+
|
|
233
|
+
state = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
234
|
+
|
|
235
|
+
assert state.valid is True
|
|
236
|
+
assert state.all_completed is True
|
|
237
|
+
assert state.semantic_complete is True
|
|
238
|
+
assert state.semantic.evidence_valid is True
|
|
239
|
+
assert state.semantic.terminal_status == "WORKFLOW_COMPLETED"
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_completed_steps_without_stage_verdicts_are_not_semantic_completion(tmp_path):
|
|
243
|
+
skills = [
|
|
244
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
245
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
246
|
+
]
|
|
247
|
+
payload = _family_checkpoint("feature-pipeline", skills)
|
|
248
|
+
payload["steps"][1].pop("stage_result")
|
|
249
|
+
payload["steps"][2].pop("stage_result")
|
|
250
|
+
payload["feature_state"]["terminal_status"] = "WORKFLOW_COMPLETED"
|
|
251
|
+
|
|
252
|
+
state = validate_checkpoint_data(payload, project_root=tmp_path)
|
|
253
|
+
|
|
254
|
+
assert state.valid is True
|
|
255
|
+
assert state.all_completed is True
|
|
256
|
+
assert state.semantic_complete is False
|
|
257
|
+
assert state.semantic.error_code == "incomplete_semantic_evidence"
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def test_family_sequence_mismatch_cannot_complete(tmp_path):
|
|
261
|
+
paths = _write_test_evidence(tmp_path)
|
|
262
|
+
skills = [
|
|
263
|
+
"prizmkit-implement", "prizmkit-test", "prizmkit-code-review",
|
|
264
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
265
|
+
]
|
|
266
|
+
payload = _family_checkpoint(
|
|
267
|
+
"feature-pipeline",
|
|
268
|
+
skills,
|
|
269
|
+
semantic={"authoritative_evidence_paths": paths, "terminal_status": "WORKFLOW_COMPLETED"},
|
|
270
|
+
)
|
|
271
|
+
payload["steps"][1]["authoritative_evidence_paths"] = paths
|
|
272
|
+
|
|
273
|
+
state = validate_checkpoint_data(payload, project_root=tmp_path)
|
|
274
|
+
|
|
275
|
+
assert state.semantic_complete is False
|
|
276
|
+
assert state.semantic.sequence_valid is False
|
|
277
|
+
assert state.semantic.error_code == "invalid_stage_sequence"
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def test_stale_or_mismatched_test_evidence_cannot_complete(tmp_path):
|
|
281
|
+
paths = _write_test_evidence(tmp_path, verdict="TEST_FAIL")
|
|
282
|
+
skills = [
|
|
283
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
284
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
285
|
+
]
|
|
286
|
+
payload = _family_checkpoint(
|
|
287
|
+
"feature-pipeline",
|
|
288
|
+
skills,
|
|
289
|
+
semantic={"authoritative_evidence_paths": paths, "terminal_status": "WORKFLOW_COMPLETED"},
|
|
290
|
+
)
|
|
291
|
+
payload["steps"][2]["authoritative_evidence_paths"] = paths
|
|
292
|
+
|
|
293
|
+
state = validate_checkpoint_data(payload, project_root=tmp_path)
|
|
294
|
+
|
|
295
|
+
assert state.semantic_complete is False
|
|
296
|
+
assert state.semantic.evidence_valid is False
|
|
297
|
+
assert state.semantic.error_code == "incomplete_semantic_evidence"
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def test_blocked_terminal_is_semantic_and_requires_reason(tmp_path):
|
|
301
|
+
payload = _family_checkpoint(
|
|
302
|
+
"feature-pipeline",
|
|
303
|
+
[
|
|
304
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
305
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
306
|
+
],
|
|
307
|
+
semantic={
|
|
308
|
+
"repair_scope": "production",
|
|
309
|
+
"repair_round": 3,
|
|
310
|
+
"blocked_reason": "repair_round_limit",
|
|
311
|
+
"terminal_status": "WORKFLOW_BLOCKED",
|
|
312
|
+
},
|
|
313
|
+
)
|
|
314
|
+
payload["steps"][2]["stage_result"] = "TEST_FAIL"
|
|
315
|
+
|
|
316
|
+
state = validate_checkpoint_data(payload, project_root=tmp_path)
|
|
317
|
+
|
|
318
|
+
assert state.semantic_blocked is True
|
|
319
|
+
assert state.semantic_complete is False
|
|
320
|
+
assert state.semantic.blocked_reason == "repair_round_limit"
|
|
321
|
+
assert state.cursor_signature == "blocked:repair_round_limit"
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def test_step_progress_must_be_a_terminal_prefix(tmp_path):
|
|
325
|
+
payload = _checkpoint([
|
|
326
|
+
_step("S01", "plan", "Plan", "pending"),
|
|
327
|
+
_step("S02", "implement", "Implement", "completed", "S01"),
|
|
328
|
+
])
|
|
329
|
+
|
|
330
|
+
state = validate_checkpoint_data(payload)
|
|
331
|
+
|
|
332
|
+
assert state.valid is False
|
|
333
|
+
assert state.error_code == "invalid_step_progress"
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def test_update_checkpoint_rejects_out_of_order_transition(tmp_path):
|
|
338
|
+
path = _write(tmp_path / "workflow-checkpoint.json", _checkpoint([
|
|
339
|
+
_step("S01", "plan", "Plan", "pending"),
|
|
340
|
+
_step("S02", "implement", "Implement", "pending", "S01"),
|
|
341
|
+
]))
|
|
342
|
+
|
|
343
|
+
result = update_checkpoint(str(path), "S02", "in_progress")
|
|
344
|
+
|
|
345
|
+
assert result["ok"] is False
|
|
346
|
+
assert "before all predecessors" in result["error"]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def test_update_checkpoint_blocks_unknown_repair_scope_without_mutating_retry_budget(tmp_path):
|
|
350
|
+
payload = _family_checkpoint(
|
|
351
|
+
"feature-pipeline",
|
|
352
|
+
[
|
|
353
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
354
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
355
|
+
],
|
|
356
|
+
)
|
|
357
|
+
payload["steps"][1]["status"] = "in_progress"
|
|
358
|
+
for step in payload["steps"][2:]:
|
|
359
|
+
step["status"] = "pending"
|
|
360
|
+
step.pop("stage_result", None)
|
|
361
|
+
path = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
362
|
+
|
|
363
|
+
result = update_checkpoint(
|
|
364
|
+
str(path),
|
|
365
|
+
"prizmkit-code-review",
|
|
366
|
+
"failed",
|
|
367
|
+
semantic_update={"stage_result": "REVIEW_NEEDS_FIXES", "repair_round": 0},
|
|
368
|
+
)
|
|
369
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
370
|
+
|
|
371
|
+
assert result["ok"] is True
|
|
372
|
+
assert data["feature_state"]["terminal_status"] == "WORKFLOW_BLOCKED"
|
|
373
|
+
assert data["feature_state"]["blocked_reason"] == "unsafe_repair_scope"
|
|
374
|
+
assert "retry_count" not in data["feature_state"]
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def test_update_checkpoint_enforces_three_outer_repair_rounds(tmp_path):
|
|
378
|
+
payload = _family_checkpoint(
|
|
379
|
+
"feature-pipeline",
|
|
380
|
+
[
|
|
381
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
382
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
383
|
+
],
|
|
384
|
+
semantic={"repair_scope": "production", "repair_round": 3},
|
|
385
|
+
)
|
|
386
|
+
payload["steps"][1]["status"] = "in_progress"
|
|
387
|
+
for step in payload["steps"][2:]:
|
|
388
|
+
step["status"] = "pending"
|
|
389
|
+
step.pop("stage_result", None)
|
|
390
|
+
path = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
391
|
+
|
|
392
|
+
result = update_checkpoint(
|
|
393
|
+
str(path),
|
|
394
|
+
"prizmkit-code-review",
|
|
395
|
+
"failed",
|
|
396
|
+
semantic_update={"stage_result": "REVIEW_NEEDS_FIXES", "repair_scope": "production"},
|
|
397
|
+
)
|
|
398
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
399
|
+
|
|
400
|
+
assert result["ok"] is True
|
|
401
|
+
assert data["feature_state"]["repair_round"] == 3
|
|
402
|
+
assert data["feature_state"]["terminal_status"] == "WORKFLOW_BLOCKED"
|
|
403
|
+
assert data["feature_state"]["blocked_reason"] == "repair_round_limit"
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def test_declared_final_artifact_must_exist_for_semantic_completion(tmp_path, monkeypatch):
|
|
408
|
+
monkeypatch.setattr(
|
|
409
|
+
"prizmkit_runtime.checkpoint_state._resolve_evidence_validator",
|
|
410
|
+
lambda _root: tmp_path / "validator.py",
|
|
411
|
+
)
|
|
412
|
+
monkeypatch.setattr(
|
|
413
|
+
"prizmkit_runtime.checkpoint_state._evidence_validator_passes",
|
|
414
|
+
lambda *_args: True,
|
|
415
|
+
)
|
|
416
|
+
paths = _write_test_evidence(tmp_path)
|
|
417
|
+
skills = [
|
|
418
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
419
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
420
|
+
]
|
|
421
|
+
payload = _family_checkpoint(
|
|
422
|
+
"feature-pipeline",
|
|
423
|
+
skills,
|
|
424
|
+
semantic={"authoritative_evidence_paths": paths, "terminal_status": "WORKFLOW_COMPLETED"},
|
|
425
|
+
)
|
|
426
|
+
payload["steps"][2]["authoritative_evidence_paths"] = paths
|
|
427
|
+
payload["steps"][-1]["required_artifacts"] = [".prizmkit/specs/feature/completion-summary.json"]
|
|
428
|
+
checkpoint = tmp_path / ".prizmkit" / "specs" / "feature" / "workflow-checkpoint.json"
|
|
429
|
+
checkpoint.parent.mkdir(parents=True)
|
|
430
|
+
_write(checkpoint, payload)
|
|
431
|
+
|
|
432
|
+
missing = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
433
|
+
(checkpoint.parent / "completion-summary.json").write_text("{}", encoding="utf-8")
|
|
434
|
+
present = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
435
|
+
|
|
436
|
+
assert missing.semantic_complete is False
|
|
437
|
+
assert missing.semantic.artifacts_valid is False
|
|
438
|
+
assert present.semantic_complete is True
|
|
439
|
+
assert present.semantic.artifacts_valid is True
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def test_update_checkpoint_rejects_test_pass_when_validator_replay_fails(tmp_path, monkeypatch):
|
|
444
|
+
paths = _write_test_evidence(tmp_path)
|
|
445
|
+
payload = _family_checkpoint(
|
|
446
|
+
"feature-pipeline",
|
|
447
|
+
[
|
|
448
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
449
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
450
|
+
],
|
|
451
|
+
)
|
|
452
|
+
payload["steps"][2]["status"] = "in_progress"
|
|
453
|
+
for step in payload["steps"][3:]:
|
|
454
|
+
step["status"] = "pending"
|
|
455
|
+
step.pop("stage_result", None)
|
|
456
|
+
checkpoint = tmp_path / "workflow-checkpoint.json"
|
|
457
|
+
_write(checkpoint, payload)
|
|
458
|
+
monkeypatch.setattr(
|
|
459
|
+
"prizmkit_runtime.checkpoint_state._resolve_evidence_validator",
|
|
460
|
+
lambda _root: tmp_path / "validator.py",
|
|
461
|
+
)
|
|
462
|
+
monkeypatch.setattr(
|
|
463
|
+
"prizmkit_runtime.checkpoint_state._evidence_validator_passes",
|
|
464
|
+
lambda *_args: False,
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
result = update_checkpoint(
|
|
468
|
+
str(checkpoint),
|
|
469
|
+
"prizmkit-test",
|
|
470
|
+
"completed",
|
|
471
|
+
semantic_update={
|
|
472
|
+
"stage_result": "TEST_PASS",
|
|
473
|
+
"authoritative_evidence_paths": paths,
|
|
474
|
+
},
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
assert result["ok"] is False
|
|
478
|
+
assert "validator-attested" in result["error"]
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def test_update_checkpoint_rejects_test_before_review_pass(tmp_path):
|
|
483
|
+
payload = _family_checkpoint(
|
|
484
|
+
"feature-pipeline",
|
|
485
|
+
[
|
|
486
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
487
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
488
|
+
],
|
|
489
|
+
)
|
|
490
|
+
payload["steps"][1]["status"] = "skipped"
|
|
491
|
+
payload["steps"][1].pop("stage_result", None)
|
|
492
|
+
payload["steps"][2]["status"] = "pending"
|
|
493
|
+
for step in payload["steps"][3:]:
|
|
494
|
+
step["status"] = "pending"
|
|
495
|
+
step.pop("stage_result", None)
|
|
496
|
+
checkpoint = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
497
|
+
|
|
498
|
+
result = update_checkpoint(str(checkpoint), "prizmkit-test", "in_progress")
|
|
499
|
+
|
|
500
|
+
assert result["ok"] is False
|
|
501
|
+
assert "REVIEW_PASS" in result["error"]
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def test_update_checkpoint_rejects_finalization_before_test_pass(tmp_path):
|
|
505
|
+
payload = _family_checkpoint(
|
|
506
|
+
"feature-pipeline",
|
|
507
|
+
[
|
|
508
|
+
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
509
|
+
"prizmkit-retrospective", "prizmkit-committer", "completion-summary",
|
|
510
|
+
],
|
|
511
|
+
)
|
|
512
|
+
payload["steps"][2]["status"] = "skipped"
|
|
513
|
+
payload["steps"][2].pop("stage_result", None)
|
|
514
|
+
payload["steps"][3]["status"] = "pending"
|
|
515
|
+
for step in payload["steps"][4:]:
|
|
516
|
+
step["status"] = "pending"
|
|
517
|
+
step.pop("stage_result", None)
|
|
518
|
+
checkpoint = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
519
|
+
|
|
520
|
+
result = update_checkpoint(str(checkpoint), "prizmkit-retrospective", "in_progress")
|
|
521
|
+
|
|
522
|
+
assert result["ok"] is False
|
|
523
|
+
assert "TEST_PASS" in result["error"]
|