prizmkit 1.1.140 → 1.1.142
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/README.md +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +165 -125
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +13 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -6
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +5 -3
- package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +160 -0
- package/bundled/dev-pipeline/scripts/check-session-status.py +11 -1
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +23 -806
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +6 -8
- package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +1 -1
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +6 -8
- package/bundled/dev-pipeline/scripts/prompt_framework.py +68 -56
- package/bundled/dev-pipeline/scripts/update-bug-status.py +21 -2
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +52 -131
- package/bundled/dev-pipeline/scripts/update-feature-status.py +21 -2
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +21 -2
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +8 -19
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +6 -6
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +5 -5
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +1 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +1 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-manual-verification.md +1 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +1 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +13 -10
- package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +1 -1
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +18 -9
- package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-base.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +14 -26
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -3
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +1 -1
- package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +13 -10
- package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +1 -1
- package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
- package/bundled/dev-pipeline/tests/test_checkpoint_state.py +494 -413
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +144 -684
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +20 -41
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +24 -24
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +176 -36
- package/bundled/skills/_metadata.json +6 -6
- package/bundled/skills/prizmkit/SKILL.md +13 -18
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-code-review/SKILL.md +7 -7
- package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-committer/SKILL.md +8 -7
- package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-implement/SKILL.md +3 -2
- package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-plan/SKILL.md +2 -1
- package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-retrospective/SKILL.md +8 -6
- package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +73 -80
- package/bundled/skills/prizmkit-test/SKILL.md +217 -189
- package/bundled/skills/prizmkit-test/references/external-contract-mock-guidance.md +119 -0
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +269 -0
- package/bundled/skills/prizmkit-test/references/test-coverage-model.md +193 -0
- package/bundled/skills/prizmkit-test/references/test-report-template.md +164 -79
- package/bundled/skills/prizmkit-workflow/SKILL.md +28 -36
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +73 -80
- package/package.json +1 -1
- package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +0 -477
- package/bundled/skills/prizmkit-test/assets/behavior-risk-matrix.schema.json +0 -116
- package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +0 -111
- package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +0 -66
- package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +0 -104
- package/bundled/skills/prizmkit-test/references/contract-mock-protocol.md +0 -65
- package/bundled/skills/prizmkit-test/references/evidence-protocol.md +0 -208
- package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +0 -80
- package/bundled/skills/prizmkit-test/references/examples.md +0 -100
- package/bundled/skills/prizmkit-test/references/service-boundary-test-catalog.md +0 -228
- package/bundled/skills/prizmkit-test/references/test-generation-steps.md +0 -118
- package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +0 -107
- package/bundled/skills/prizmkit-test/references/workflow-state-protocol.md +0 -181
- package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +0 -1930
- package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +0 -1847
|
@@ -472,7 +472,7 @@ class TestBugfixCheckpointGeneration:
|
|
|
472
472
|
existing["bugfix_state"] = bugfix_checkpoint_metadata(
|
|
473
473
|
".prizmkit/bugfix/B-001",
|
|
474
474
|
stage="test",
|
|
475
|
-
status="
|
|
475
|
+
status="failed",
|
|
476
476
|
stage_result="TEST_BLOCKED",
|
|
477
477
|
repair_round=2,
|
|
478
478
|
next_stage="prizmkit-test",
|
|
@@ -481,6 +481,7 @@ class TestBugfixCheckpointGeneration:
|
|
|
481
481
|
|
|
482
482
|
merged = merge_bugfix_checkpoint_state(existing, fresh, str(tmp_path))
|
|
483
483
|
|
|
484
|
+
assert merged["bugfix_state"]["status"] == "failed"
|
|
484
485
|
assert merged["bugfix_state"]["stage_result"] == "TEST_BLOCKED"
|
|
485
486
|
assert merged["bugfix_state"]["resume_from"] == "prizmkit-test"
|
|
486
487
|
|
|
@@ -500,66 +501,44 @@ class TestBugfixCheckpointGeneration:
|
|
|
500
501
|
test_step = checkpoint["steps"][4]
|
|
501
502
|
assert test_step["depends_on"] == "S04"
|
|
502
503
|
assert test_step["required_artifacts"] == [
|
|
503
|
-
".prizmkit/test
|
|
504
|
-
".prizmkit/test
|
|
505
|
-
".prizmkit/test/evidence/*/validation.json",
|
|
504
|
+
".prizmkit/bugfix/B-001/test-report.md",
|
|
505
|
+
".prizmkit/bugfix/B-001/test-result.json",
|
|
506
506
|
]
|
|
507
507
|
assert checkpoint["steps"][5]["depends_on"] == "S05"
|
|
508
508
|
|
|
509
|
-
def
|
|
509
|
+
def test_bugfix_result_routing_stops_test_non_pass(self):
|
|
510
510
|
review = route_bugfix_repair("REVIEW_NEEDS_FIXES", repair_round=0)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
)
|
|
514
|
-
production = route_bugfix_repair("TEST_FAIL", "public-interface", repair_round=2)
|
|
511
|
+
needs_fixes = route_bugfix_repair("TEST_NEEDS_FIXES", repair_round=1)
|
|
512
|
+
blocked = route_bugfix_repair("TEST_BLOCKED", repair_round=1)
|
|
515
513
|
|
|
516
514
|
assert review["route"] == [
|
|
517
515
|
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
518
516
|
]
|
|
519
|
-
assert
|
|
520
|
-
assert
|
|
521
|
-
|
|
522
|
-
]
|
|
523
|
-
assert production["repair_round"] == 3
|
|
524
|
-
|
|
525
|
-
def test_bugfix_repair_routing_blocks_unsafe_blocked_and_exhausted_results(self):
|
|
526
|
-
unknown = route_bugfix_repair("TEST_FAIL", "unknown", repair_round=1)
|
|
527
|
-
blocked = route_bugfix_repair("TEST_BLOCKED", "production", repair_round=1)
|
|
528
|
-
exhausted = route_bugfix_repair("TEST_FAIL", "production", repair_round=3)
|
|
529
|
-
|
|
530
|
-
assert unknown["blocked"] is True
|
|
531
|
-
assert unknown["route"] == []
|
|
517
|
+
assert review["repair_round"] == 1
|
|
518
|
+
assert needs_fixes["blocked"] is True
|
|
519
|
+
assert needs_fixes["route"] == []
|
|
520
|
+
assert needs_fixes["blocked_reason"] == "test_needs_fixes"
|
|
532
521
|
assert blocked["blocked"] is True
|
|
533
522
|
assert blocked["resumable"] is False
|
|
534
523
|
assert blocked["next_stage"] is None
|
|
535
524
|
assert blocked["terminal_status"] == "WORKFLOW_BLOCKED"
|
|
536
525
|
assert blocked["blocked_reason"] == "test_blocked"
|
|
537
|
-
assert blocked["route"] == []
|
|
538
|
-
assert "cannot safely edit production" in blocked["reason"]
|
|
539
|
-
assert exhausted["blocked"] is True
|
|
540
|
-
assert exhausted["repair_round"] == 3
|
|
541
526
|
|
|
542
|
-
def
|
|
527
|
+
def test_bugfix_checkpoint_metadata_has_no_evidence_handoff(self):
|
|
543
528
|
metadata = bugfix_checkpoint_metadata(
|
|
544
529
|
".prizmkit/bugfix/B-001",
|
|
545
|
-
evidence={
|
|
546
|
-
"manifest_path": ".prizmkit/test/evidence/id/manifest.json",
|
|
547
|
-
"verdict_path": ".prizmkit/test/evidence/id/verdict.json",
|
|
548
|
-
"validation_path": ".prizmkit/test/evidence/id/validation.json",
|
|
549
|
-
},
|
|
550
530
|
stage="test",
|
|
551
|
-
status="
|
|
552
|
-
stage_result="
|
|
553
|
-
|
|
554
|
-
|
|
531
|
+
status="failed",
|
|
532
|
+
stage_result="TEST_NEEDS_FIXES",
|
|
533
|
+
repair_round=0,
|
|
534
|
+
next_stage=None,
|
|
535
|
+
resume_from=None,
|
|
555
536
|
)
|
|
556
537
|
|
|
557
538
|
assert metadata["artifact_dir"] == ".prizmkit/bugfix/B-001"
|
|
558
|
-
assert metadata["
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
assert metadata["repair_round"] == 2
|
|
562
|
-
assert metadata["resume_from"] == "prizmkit-implement"
|
|
539
|
+
assert metadata["status"] == "failed"
|
|
540
|
+
assert metadata["stage_result"] == "TEST_NEEDS_FIXES"
|
|
541
|
+
assert "authoritative_evidence_paths" not in metadata
|
|
563
542
|
|
|
564
543
|
def test_manual_bugfix_uses_automatic_verification_and_keeps_commit_gate(self):
|
|
565
544
|
sections = assemble_bugfix_sections(
|
|
@@ -59,12 +59,12 @@ class TestRefactorCheckpointMerge:
|
|
|
59
59
|
existing["refactor_state"] = refactor_checkpoint_metadata(
|
|
60
60
|
".prizmkit/refactor/R-008",
|
|
61
61
|
stage="test",
|
|
62
|
-
status="
|
|
63
|
-
stage_result="
|
|
62
|
+
status="failed",
|
|
63
|
+
stage_result="TEST_NEEDS_FIXES",
|
|
64
64
|
repair_scope="public-interface",
|
|
65
65
|
repair_round=2,
|
|
66
|
-
next_stage=
|
|
67
|
-
resume_from=
|
|
66
|
+
next_stage=None,
|
|
67
|
+
resume_from=None,
|
|
68
68
|
)
|
|
69
69
|
existing["steps"][0]["status"] = "skipped"
|
|
70
70
|
|
|
@@ -72,6 +72,7 @@ class TestRefactorCheckpointMerge:
|
|
|
72
72
|
|
|
73
73
|
assert merged["steps"][0]["status"] == "skipped"
|
|
74
74
|
assert merged["steps"][1]["status"] == "pending"
|
|
75
|
+
assert merged["refactor_state"]["status"] == "failed"
|
|
75
76
|
assert merged["refactor_state"]["repair_scope"] == "public-interface"
|
|
76
77
|
assert merged["refactor_state"]["repair_round"] == 2
|
|
77
78
|
|
|
@@ -215,7 +216,7 @@ def test_template_source_is_clean_for_headless_prompt_contract():
|
|
|
215
216
|
assert "/prizmkit-test scope=this-change artifact_dir=.prizmkit/refactor/{{REFACTOR_ID}}/" in content
|
|
216
217
|
assert "local_commit_authorized=true" in content
|
|
217
218
|
assert "push_authorized" not in content
|
|
218
|
-
assert "Behavior-preservation
|
|
219
|
+
assert "Behavior-preservation context remains supporting input" in content
|
|
219
220
|
|
|
220
221
|
|
|
221
222
|
# ---------------------------------------------------------------------------
|
|
@@ -349,44 +350,43 @@ class TestRefactorCheckpointGeneration:
|
|
|
349
350
|
"completion-summary",
|
|
350
351
|
]
|
|
351
352
|
assert checkpoint["steps"][4]["depends_on"] == "S04"
|
|
353
|
+
assert checkpoint["steps"][4]["required_artifacts"] == [
|
|
354
|
+
".prizmkit/refactor/R-001/test-report.md",
|
|
355
|
+
".prizmkit/refactor/R-001/test-result.json",
|
|
356
|
+
]
|
|
352
357
|
assert checkpoint["steps"][5]["depends_on"] == "S05"
|
|
353
358
|
|
|
354
|
-
def
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
)
|
|
358
|
-
production = route_refactor_repair("TEST_FAIL", "public-interface", repair_round=1)
|
|
359
|
-
blocked = route_refactor_repair("TEST_BLOCKED", "production", repair_round=1)
|
|
359
|
+
def test_refactor_result_routing_stops_test_non_pass(self):
|
|
360
|
+
review = route_refactor_repair("REVIEW_NEEDS_FIXES", repair_round=0)
|
|
361
|
+
needs_fixes = route_refactor_repair("TEST_NEEDS_FIXES", repair_round=1)
|
|
362
|
+
blocked = route_refactor_repair("TEST_BLOCKED", repair_round=1)
|
|
360
363
|
|
|
361
|
-
assert
|
|
362
|
-
assert production["route"] == [
|
|
364
|
+
assert review["route"] == [
|
|
363
365
|
"prizmkit-implement", "prizmkit-code-review", "prizmkit-test",
|
|
364
366
|
]
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
assert
|
|
368
|
-
assert unknown["route"] == []
|
|
369
|
-
assert exhausted["blocked"] is True
|
|
370
|
-
assert exhausted["repair_round"] == 3
|
|
367
|
+
assert needs_fixes["blocked"] is True
|
|
368
|
+
assert needs_fixes["route"] == []
|
|
369
|
+
assert needs_fixes["blocked_reason"] == "test_needs_fixes"
|
|
371
370
|
assert blocked["blocked"] is True
|
|
372
371
|
assert blocked["route"] == []
|
|
373
372
|
assert blocked["next_stage"] is None
|
|
374
373
|
assert blocked["terminal_status"] == "WORKFLOW_BLOCKED"
|
|
375
374
|
assert blocked["blocked_reason"] == "test_blocked"
|
|
376
375
|
|
|
377
|
-
def
|
|
376
|
+
def test_refactor_checkpoint_metadata_has_no_evidence_handoff(self):
|
|
378
377
|
metadata = refactor_checkpoint_metadata(
|
|
379
378
|
".prizmkit/refactor/R-001",
|
|
380
|
-
evidence={"manifest_path": "manifest.json"},
|
|
381
379
|
stage="test",
|
|
382
|
-
status="
|
|
380
|
+
status="completed",
|
|
383
381
|
stage_result="TEST_PASS",
|
|
384
382
|
next_stage="prizmkit-retrospective",
|
|
385
383
|
resume_from="prizmkit-retrospective",
|
|
386
384
|
)
|
|
387
385
|
|
|
388
386
|
assert metadata["artifact_dir"] == ".prizmkit/refactor/R-001"
|
|
389
|
-
assert metadata["
|
|
387
|
+
assert metadata["status"] == "completed"
|
|
388
|
+
assert metadata["stage_result"] == "TEST_PASS"
|
|
389
|
+
assert "authoritative_evidence_paths" not in metadata
|
|
390
390
|
assert metadata["next_stage"] == "prizmkit-retrospective"
|
|
391
391
|
assert metadata["resume_from"] == "prizmkit-retrospective"
|
|
392
392
|
|
|
@@ -397,7 +397,7 @@ class TestRefactorCheckpointGeneration:
|
|
|
397
397
|
"/prizmkit-test scope=this-change artifact_dir=.prizmkit/refactor/R-001/"
|
|
398
398
|
) < prompt.index("### Headless Commit Authorization")
|
|
399
399
|
assert "prizmkit-workflow" not in prompt
|
|
400
|
-
assert "
|
|
400
|
+
assert "Existing behavior-preservation context is input to testing" in prompt
|
|
401
401
|
assert '"local_commit_authorized": true' in prompt
|
|
402
402
|
assert "push_authorized" not in prompt
|
|
403
403
|
assert "Remote publication is controlled by the runtime" in prompt
|
|
@@ -92,12 +92,6 @@ def _item_id_from_next_result(kind, result):
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_type="feature-pipeline"):
|
|
95
|
-
validator = (
|
|
96
|
-
project_root / ".claude" / "command-assets" / "prizmkit-test"
|
|
97
|
-
/ "scripts" / "validate_test_evidence.py"
|
|
98
|
-
)
|
|
99
|
-
validator.parent.mkdir(parents=True, exist_ok=True)
|
|
100
|
-
validator.write_text("import sys\nsys.exit(0)\n", encoding="utf-8")
|
|
101
95
|
contracts = {
|
|
102
96
|
"feature-pipeline": (
|
|
103
97
|
"feature_state",
|
|
@@ -123,25 +117,6 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
|
|
|
123
117
|
),
|
|
124
118
|
}
|
|
125
119
|
state_key, skills = contracts[workflow_type]
|
|
126
|
-
evidence_id = "semantic-evidence"
|
|
127
|
-
evidence_dir = project_root / ".prizmkit" / "test" / "evidence" / evidence_id
|
|
128
|
-
evidence_dir.mkdir(parents=True, exist_ok=True)
|
|
129
|
-
evidence = {
|
|
130
|
-
"manifest": evidence_dir / "manifest.json",
|
|
131
|
-
"verdict": evidence_dir / "verdict.json",
|
|
132
|
-
"validation": evidence_dir / "validation.json",
|
|
133
|
-
}
|
|
134
|
-
evidence["manifest"].write_text(
|
|
135
|
-
json.dumps({"evidence_id": evidence_id, "final_verdict": "TEST_PASS"}),
|
|
136
|
-
encoding="utf-8",
|
|
137
|
-
)
|
|
138
|
-
evidence["verdict"].write_text(json.dumps({"verdict": "TEST_PASS"}), encoding="utf-8")
|
|
139
|
-
evidence["validation"].write_text(
|
|
140
|
-
json.dumps({"verdict": "TEST_PASS", "result": "passed"}), encoding="utf-8"
|
|
141
|
-
)
|
|
142
|
-
relative_evidence = {
|
|
143
|
-
key: str(path.relative_to(project_root)) for key, path in evidence.items()
|
|
144
|
-
}
|
|
145
120
|
steps = []
|
|
146
121
|
previous = None
|
|
147
122
|
for index, skill in enumerate(skills, start=1):
|
|
@@ -157,10 +132,38 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
|
|
|
157
132
|
step["stage_result"] = "REVIEW_PASS"
|
|
158
133
|
if skill == "prizmkit-test":
|
|
159
134
|
step["stage_result"] = "TEST_PASS"
|
|
160
|
-
|
|
135
|
+
relative_artifact = artifact_dir.relative_to(project_root)
|
|
136
|
+
step["required_artifacts"] = [
|
|
137
|
+
str(relative_artifact / "test-report.md"),
|
|
138
|
+
str(relative_artifact / "test-result.json"),
|
|
139
|
+
]
|
|
161
140
|
steps.append(step)
|
|
162
141
|
previous = step["id"]
|
|
163
142
|
artifact_dir.mkdir(parents=True, exist_ok=True)
|
|
143
|
+
(artifact_dir / "test-report.md").write_text(
|
|
144
|
+
"# Test Report\n\n## Final Result\n\n- Result: TEST_PASS\n",
|
|
145
|
+
encoding="utf-8",
|
|
146
|
+
)
|
|
147
|
+
(artifact_dir / "test-result.json").write_text(
|
|
148
|
+
json.dumps({
|
|
149
|
+
"schema_version": 1,
|
|
150
|
+
"result": "TEST_PASS",
|
|
151
|
+
"report": "test-report.md",
|
|
152
|
+
"main_review_rounds": 1,
|
|
153
|
+
"independent_review": {
|
|
154
|
+
"status": "downgraded",
|
|
155
|
+
"responses": 0,
|
|
156
|
+
"downgrade_reason": "read-only continuation capability unavailable",
|
|
157
|
+
"final_state_rechecked": False,
|
|
158
|
+
},
|
|
159
|
+
"repair_rounds": 0,
|
|
160
|
+
"production_changed": False,
|
|
161
|
+
"review_required": False,
|
|
162
|
+
"review_scope": None,
|
|
163
|
+
"unresolved_items": [],
|
|
164
|
+
}),
|
|
165
|
+
encoding="utf-8",
|
|
166
|
+
)
|
|
164
167
|
checkpoint = artifact_dir / "workflow-checkpoint.json"
|
|
165
168
|
checkpoint.write_text(
|
|
166
169
|
json.dumps({
|
|
@@ -169,7 +172,6 @@ def _write_semantic_completion_checkpoint(project_root, artifact_dir, workflow_t
|
|
|
169
172
|
"steps": steps,
|
|
170
173
|
state_key: {
|
|
171
174
|
"repair_round": 0,
|
|
172
|
-
"authoritative_evidence_paths": relative_evidence,
|
|
173
175
|
"terminal_status": "WORKFLOW_COMPLETED",
|
|
174
176
|
},
|
|
175
177
|
}),
|
|
@@ -3424,7 +3426,150 @@ def _terminal_success_result(tmp_path):
|
|
|
3424
3426
|
)
|
|
3425
3427
|
|
|
3426
3428
|
|
|
3427
|
-
def
|
|
3429
|
+
def test_session_status_parser_preserves_current_runtime_outcomes():
|
|
3430
|
+
import importlib.util
|
|
3431
|
+
|
|
3432
|
+
script = PIPELINE_ROOT / "scripts" / "check-session-status.py"
|
|
3433
|
+
spec = importlib.util.spec_from_file_location("check_session_status_contract", script)
|
|
3434
|
+
module = importlib.util.module_from_spec(spec)
|
|
3435
|
+
spec.loader.exec_module(module)
|
|
3436
|
+
|
|
3437
|
+
for status in (
|
|
3438
|
+
"infra_error",
|
|
3439
|
+
"stalled_context_continuation",
|
|
3440
|
+
"workflow_blocked",
|
|
3441
|
+
"workflow_skipped",
|
|
3442
|
+
):
|
|
3443
|
+
assert module.determine_status({"status": status}) == status
|
|
3444
|
+
|
|
3445
|
+
|
|
3446
|
+
def test_terminal_success_without_semantic_completion_is_skipped(tmp_path):
|
|
3447
|
+
from prizmkit_runtime.runner_classification import classify_session
|
|
3448
|
+
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
3449
|
+
|
|
3450
|
+
base_head = _init_git_repo_for_invalid_checkpoint_test(tmp_path)
|
|
3451
|
+
artifact_dir = tmp_path / ".prizmkit" / "specs" / "001-incomplete"
|
|
3452
|
+
checkpoint = _write_semantic_completion_checkpoint(tmp_path, artifact_dir)
|
|
3453
|
+
payload = json.loads(checkpoint.read_text(encoding="utf-8"))
|
|
3454
|
+
payload["steps"][2]["required_artifacts"] = [
|
|
3455
|
+
".prizmkit/specs/001-incomplete/test-report.md",
|
|
3456
|
+
".prizmkit/specs/001-incomplete/missing-test-result.json",
|
|
3457
|
+
]
|
|
3458
|
+
checkpoint.write_text(json.dumps(payload), encoding="utf-8")
|
|
3459
|
+
prompt = PromptGenerationResult(
|
|
3460
|
+
output_path=tmp_path / "prompt.md",
|
|
3461
|
+
checkpoint_path=checkpoint,
|
|
3462
|
+
artifact_path=artifact_dir,
|
|
3463
|
+
)
|
|
3464
|
+
|
|
3465
|
+
classification = classify_session(
|
|
3466
|
+
_terminal_success_result(tmp_path),
|
|
3467
|
+
project_root=tmp_path,
|
|
3468
|
+
base_head=base_head,
|
|
3469
|
+
prompt=prompt,
|
|
3470
|
+
)
|
|
3471
|
+
|
|
3472
|
+
assert classification.session_status == "workflow_skipped"
|
|
3473
|
+
assert classification.reason == "no_semantic_completion:incomplete_semantic_evidence"
|
|
3474
|
+
assert classification.fatal_error_code == ""
|
|
3475
|
+
|
|
3476
|
+
|
|
3477
|
+
def test_terminal_success_text_does_not_hide_provider_failure(tmp_path):
|
|
3478
|
+
from prizmkit_runtime.runner_classification import classify_session
|
|
3479
|
+
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
3480
|
+
from prizmkit_runtime.sessions import AISessionCommand, AISessionResult
|
|
3481
|
+
from prizmkit_runtime.status import ProgressSummary
|
|
3482
|
+
|
|
3483
|
+
base_head = _init_git_repo_for_invalid_checkpoint_test(tmp_path)
|
|
3484
|
+
artifact_dir = tmp_path / ".prizmkit" / "specs" / "001-provider-error"
|
|
3485
|
+
checkpoint = _write_semantic_completion_checkpoint(tmp_path, artifact_dir)
|
|
3486
|
+
payload = json.loads(checkpoint.read_text(encoding="utf-8"))
|
|
3487
|
+
payload["steps"][2]["required_artifacts"] = [
|
|
3488
|
+
".prizmkit/specs/001-provider-error/test-report.md",
|
|
3489
|
+
".prizmkit/specs/001-provider-error/missing-test-result.json",
|
|
3490
|
+
]
|
|
3491
|
+
checkpoint.write_text(json.dumps(payload), encoding="utf-8")
|
|
3492
|
+
log = tmp_path / "provider-error.log"
|
|
3493
|
+
log.write_text("gateway failure after output", encoding="utf-8")
|
|
3494
|
+
raw = AISessionResult(
|
|
3495
|
+
command=AISessionCommand(("fake",), None, "claude", "stdin"),
|
|
3496
|
+
exit_code=0,
|
|
3497
|
+
timed_out=False,
|
|
3498
|
+
termination_reason=None,
|
|
3499
|
+
stale_marker=None,
|
|
3500
|
+
fatal_error_code="provider_error",
|
|
3501
|
+
progress_summary=ProgressSummary(result_subtype="success"),
|
|
3502
|
+
session_log=log,
|
|
3503
|
+
backup_log=tmp_path / "backup.log",
|
|
3504
|
+
log_recovery=None,
|
|
3505
|
+
started_epoch=0,
|
|
3506
|
+
ended_epoch=1,
|
|
3507
|
+
)
|
|
3508
|
+
|
|
3509
|
+
classification = classify_session(
|
|
3510
|
+
raw,
|
|
3511
|
+
project_root=tmp_path,
|
|
3512
|
+
base_head=base_head,
|
|
3513
|
+
prompt=PromptGenerationResult(
|
|
3514
|
+
output_path=tmp_path / "prompt.md",
|
|
3515
|
+
checkpoint_path=checkpoint,
|
|
3516
|
+
artifact_path=artifact_dir,
|
|
3517
|
+
),
|
|
3518
|
+
)
|
|
3519
|
+
|
|
3520
|
+
assert classification.session_status == "infra_error"
|
|
3521
|
+
assert classification.reason == "ai_runtime_or_provider_error"
|
|
3522
|
+
|
|
3523
|
+
|
|
3524
|
+
@pytest.mark.parametrize(
|
|
3525
|
+
("kind", "item_id"),
|
|
3526
|
+
[("feature", "F-001"), ("bugfix", "B-001"), ("refactor", "R-001")],
|
|
3527
|
+
)
|
|
3528
|
+
def test_family_status_skips_semantic_completion_failure_without_retry_spend(
|
|
3529
|
+
tmp_path, kind, item_id
|
|
3530
|
+
):
|
|
3531
|
+
from prizmkit_runtime.runner_models import family_for, parse_invocation
|
|
3532
|
+
from prizmkit_runtime.runner_status import start_item, update_item
|
|
3533
|
+
|
|
3534
|
+
paths = _make_paths(tmp_path / kind)
|
|
3535
|
+
item = {
|
|
3536
|
+
"id": item_id,
|
|
3537
|
+
"title": "Skip invalid completion evidence",
|
|
3538
|
+
"status": "pending",
|
|
3539
|
+
"priority": "high",
|
|
3540
|
+
"dependencies": [],
|
|
3541
|
+
}
|
|
3542
|
+
if kind == "bugfix":
|
|
3543
|
+
item.update(severity="high", description="invalid evidence", reproduction_steps=["run"])
|
|
3544
|
+
elif kind == "refactor":
|
|
3545
|
+
item.update(description="invalid evidence", targets=["src"], goals=["preserve"])
|
|
3546
|
+
_write_family_plan(paths, kind, [item])
|
|
3547
|
+
family = family_for(kind, paths)
|
|
3548
|
+
invocation = parse_invocation(family, "run", ())
|
|
3549
|
+
invocation = invocation.__class__(**{**invocation.__dict__, "list_path": family.plan_path})
|
|
3550
|
+
assert start_item(family, invocation, item_id, paths.project_root).ok is True
|
|
3551
|
+
|
|
3552
|
+
result = update_item(
|
|
3553
|
+
family,
|
|
3554
|
+
invocation,
|
|
3555
|
+
item_id,
|
|
3556
|
+
"workflow_skipped",
|
|
3557
|
+
"session-1",
|
|
3558
|
+
paths.project_root,
|
|
3559
|
+
checkpoint_state={},
|
|
3560
|
+
)
|
|
3561
|
+
status = json.loads((family.state_dir / item_id / "status.json").read_text(encoding="utf-8"))
|
|
3562
|
+
|
|
3563
|
+
assert result.ok is True
|
|
3564
|
+
assert result.data["new_status"] == "skipped"
|
|
3565
|
+
assert result.data["restart_policy"] == "terminal_skipped"
|
|
3566
|
+
assert status["retry_count"] == 0
|
|
3567
|
+
assert status["infra_error_count"] == 0
|
|
3568
|
+
assert status["needs_attention"] is True
|
|
3569
|
+
assert status["skipped_reason"] == "workflow_completion_evidence_invalid"
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
def test_invalid_existing_checkpoint_skips_terminal_success_with_completion_summary(tmp_path):
|
|
3428
3573
|
from prizmkit_runtime.runner_classification import classify_session
|
|
3429
3574
|
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
3430
3575
|
|
|
@@ -3438,11 +3583,11 @@ def test_invalid_existing_checkpoint_blocks_terminal_success_with_completion_sum
|
|
|
3438
3583
|
|
|
3439
3584
|
classification = classify_session(_terminal_success_result(tmp_path), project_root=tmp_path, base_head=base_head, prompt=prompt)
|
|
3440
3585
|
|
|
3441
|
-
assert classification.session_status == "
|
|
3586
|
+
assert classification.session_status == "workflow_skipped"
|
|
3442
3587
|
assert classification.reason == "invalid_workflow_checkpoint:invalid_status"
|
|
3443
3588
|
|
|
3444
3589
|
|
|
3445
|
-
def
|
|
3590
|
+
def test_invalid_existing_checkpoint_blocks_runtime_failure_with_head_change(tmp_path):
|
|
3446
3591
|
from prizmkit_runtime.runner_classification import classify_session
|
|
3447
3592
|
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
3448
3593
|
from prizmkit_runtime.sessions import AISessionCommand, AISessionResult
|
|
@@ -3479,7 +3624,7 @@ def test_invalid_existing_checkpoint_blocks_head_change_success(tmp_path):
|
|
|
3479
3624
|
assert classification.reason == "invalid_workflow_checkpoint:malformed_step_id"
|
|
3480
3625
|
|
|
3481
3626
|
|
|
3482
|
-
def
|
|
3627
|
+
def test_invalid_existing_checkpoint_blocks_ambiguous_clean_exit(tmp_path):
|
|
3483
3628
|
from prizmkit_runtime.runner_classification import classify_session
|
|
3484
3629
|
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
3485
3630
|
from prizmkit_runtime.sessions import AISessionCommand, AISessionResult
|
|
@@ -3877,11 +4022,6 @@ def test_family_status_persists_identical_semantic_blocked_snapshot_without_retr
|
|
|
3877
4022
|
"stage_result": "TEST_BLOCKED",
|
|
3878
4023
|
"repair_scope": "production",
|
|
3879
4024
|
"repair_round": 2,
|
|
3880
|
-
"authoritative_evidence_paths": {
|
|
3881
|
-
"manifest": ".prizmkit/test/evidence/id/manifest.json",
|
|
3882
|
-
"verdict": ".prizmkit/test/evidence/id/verdict.json",
|
|
3883
|
-
"validation": ".prizmkit/test/evidence/id/validation.json",
|
|
3884
|
-
},
|
|
3885
4025
|
"blocked_reason": "test_blocked",
|
|
3886
4026
|
"terminal_status": "WORKFLOW_BLOCKED",
|
|
3887
4027
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.
|
|
2
|
+
"version": "1.1.142",
|
|
3
3
|
"skills": {
|
|
4
4
|
"prizmkit": {
|
|
5
5
|
"description": "Framework introduction and navigation for the formal single-requirement lifecycle, project initialization, Prizm docs, and independent deployment.",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"hasScripts": false
|
|
10
10
|
},
|
|
11
11
|
"prizmkit-workflow": {
|
|
12
|
-
"description": "Composite
|
|
12
|
+
"description": "Composite workflow for one explicitly requested formal requirement: plan → implement → code-review → test → retrospective → committer, with stable artifact identity and deterministic repair routing.",
|
|
13
13
|
"tier": "foundation",
|
|
14
14
|
"category": "prizmkit-skill",
|
|
15
15
|
"hasAssets": false,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"hasScripts": true
|
|
45
45
|
},
|
|
46
46
|
"prizmkit-committer": {
|
|
47
|
-
"description": "Final formal-requirement commit gate: verifies all prior stages, confirms interactive commits or performs authorized
|
|
47
|
+
"description": "Final formal-requirement commit gate: verifies all prior stages, confirms interactive commits or performs authorized headless pipeline commits, and never pushes automatically.",
|
|
48
48
|
"tier": "1",
|
|
49
49
|
"category": "prizmkit-skill",
|
|
50
50
|
"hasAssets": false,
|
|
@@ -72,11 +72,11 @@
|
|
|
72
72
|
"hasScripts": false
|
|
73
73
|
},
|
|
74
74
|
"prizmkit-test": {
|
|
75
|
-
"description": "
|
|
75
|
+
"description": "AI-led project-native testing for the affected business module and Regression Ring, with bounded failure repair, mandatory Main-Agent review, optional strict independent Test Reviewer, and TEST_PASS/TEST_NEEDS_FIXES/TEST_BLOCKED results.",
|
|
76
76
|
"tier": "1",
|
|
77
77
|
"category": "prizmkit-skill",
|
|
78
|
-
"hasAssets":
|
|
79
|
-
"hasScripts":
|
|
78
|
+
"hasAssets": false,
|
|
79
|
+
"hasScripts": false
|
|
80
80
|
},
|
|
81
81
|
"feature-workflow": {
|
|
82
82
|
"description": "Thin feature scenario router. Clarifies whether the request needs direct single-requirement guidance, app planning, feature planning, or command construction from an existing feature list.",
|
|
@@ -69,12 +69,12 @@ Typos, pure formatting, small documentation edits, and other explicitly low-risk
|
|
|
69
69
|
|
|
70
70
|
| Stage | Responsibility | Success handoff |
|
|
71
71
|
|---|---|---|
|
|
72
|
-
| `prizmkit-plan` | Clarify the requirement and create/review `spec.md` and `plan.md`. | `PLAN_READY` → `prizmkit-implement` |
|
|
73
|
-
| `prizmkit-implement` | Execute the plan tasks and record completion. | `IMPLEMENTED` → `prizmkit-code-review` |
|
|
74
|
-
| `prizmkit-code-review` | Main Agent reviews, repairs, verifies, and loops until convergence. | `REVIEW_PASS` → `prizmkit-test` |
|
|
75
|
-
| `prizmkit-test` | Validate the final reviewed workspace with project-native
|
|
76
|
-
| `prizmkit-retrospective` | Synchronize durable project documentation or record no documentation change. | `RETRO_COMPLETE` → `prizmkit-committer` |
|
|
77
|
-
| `prizmkit-committer` | Verify gates, request commit confirmation, and create the local commit. | `COMMITTED` |
|
|
72
|
+
| `prizmkit-plan` | Clarify the requirement and create/review `spec.md` and `plan.md`. | `status=completed`, `stage_result=PLAN_READY` → `prizmkit-implement` |
|
|
73
|
+
| `prizmkit-implement` | Execute the plan tasks and record completion. | `status=completed`, `stage_result=IMPLEMENTED` → `prizmkit-code-review` |
|
|
74
|
+
| `prizmkit-code-review` | Main Agent reviews, repairs, verifies, and loops until convergence. | `status=completed`, `stage_result=REVIEW_PASS` → `prizmkit-test` |
|
|
75
|
+
| `prizmkit-test` | Validate the final reviewed workspace with project-native tests and a consistent terminal report/result pair. | `status=completed`, `stage_result=TEST_PASS` → `prizmkit-retrospective` |
|
|
76
|
+
| `prizmkit-retrospective` | Synchronize durable project documentation or record no documentation change. | `status=completed`, `stage_result=RETRO_COMPLETE` → `prizmkit-committer` |
|
|
77
|
+
| `prizmkit-committer` | Verify gates, request commit confirmation, and create the local commit. | `status=completed`, `stage_result=COMMITTED` |
|
|
78
78
|
|
|
79
79
|
### `prizmkit-workflow`
|
|
80
80
|
|
|
@@ -108,19 +108,14 @@ REVIEW_NEEDS_FIXES
|
|
|
108
108
|
→ prizmkit-implement
|
|
109
109
|
→ prizmkit-code-review
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
→
|
|
113
|
-
→
|
|
114
|
-
|
|
115
|
-
TEST_FAIL affecting production code, runtime configuration, schema,
|
|
116
|
-
dependencies, or public interfaces
|
|
117
|
-
→ prizmkit-implement
|
|
118
|
-
→ prizmkit-code-review
|
|
119
|
-
→ prizmkit-test
|
|
111
|
+
TEST_NEEDS_FIXES
|
|
112
|
+
→ preserve test-report.md and test-result.json
|
|
113
|
+
→ stop with the known correction or delta-review requirement
|
|
114
|
+
→ caller owns any later review/retest route
|
|
120
115
|
|
|
121
116
|
TEST_BLOCKED
|
|
122
|
-
→
|
|
123
|
-
→
|
|
117
|
+
→ preserve the blocker without speculative code changes
|
|
118
|
+
→ caller owns recovery after truth, input, safety, environment, or reliability is restored
|
|
124
119
|
```
|
|
125
120
|
|
|
126
121
|
Automatic outer repair is limited to three rounds. The workflow stops with a resumable blocked result when the limit is reached or a gate cannot be safely completed.
|
|
@@ -141,7 +136,7 @@ An active requirement may use:
|
|
|
141
136
|
|
|
142
137
|
This runtime state records the current stage, terminal status, repair scope, repair round, and resume entry. The skill set does not prescribe whether the target project commits, ignores, or shares this file.
|
|
143
138
|
|
|
144
|
-
Read `${SKILL_DIR}/references/workflow-state-protocol.md` for the state protocol. If the state file is missing or stale, use `spec.md`, `plan.md`, review
|
|
139
|
+
Read `${SKILL_DIR}/references/workflow-state-protocol.md` for the state protocol. If the state file is missing or stale, use `spec.md`, `plan.md`, the review report, `test-report.md`, and `test-result.json` to reconstruct the safest recoverable stage and report that reconstruction.
|
|
145
140
|
|
|
146
141
|
## Quick Start
|
|
147
142
|
|