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.
- package/bundled/VERSION.json +3 -3
- package/bundled/adapters/codex/skill-adapter.js +1 -1
- package/bundled/adapters/pi/skill-adapter.js +2 -1
- package/bundled/dev-pipeline/.env.example +2 -6
- package/bundled/dev-pipeline/README.md +21 -27
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +341 -15
- package/bundled/dev-pipeline/prizmkit_runtime/cli.py +0 -3
- package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +1 -15
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +48 -14
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +50 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -9
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +120 -22
- package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +482 -0
- package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +64 -11
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +145 -367
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +91 -62
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +105 -69
- package/bundled/dev-pipeline/scripts/prompt_framework.py +36 -41
- package/bundled/dev-pipeline/scripts/update-bug-status.py +1 -4
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +61 -13
- package/bundled/dev-pipeline/scripts/update-feature-status.py +1 -4
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +1 -4
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +22 -27
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +71 -104
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +59 -111
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +37 -72
- package/bundled/dev-pipeline/templates/sections/artifact-manifest.md +39 -0
- package/bundled/dev-pipeline/templates/sections/bugfix-critical-paths.md +3 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +8 -25
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +3 -3
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-implement.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +4 -4
- package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +0 -1
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +7 -4
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +14 -27
- package/bundled/dev-pipeline/templates/sections/feature-completion-summary.md +20 -0
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -71
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -7
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +3 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -4
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +5 -17
- package/bundled/dev-pipeline/templates/sections/refactor-critical-paths.md +3 -1
- package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +10 -23
- package/bundled/dev-pipeline/templates/sections/refactor-phase-implement.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-phase-plan.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +7 -7
- package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +0 -1
- package/bundled/dev-pipeline/templates/sections/retrospective.md +12 -0
- package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +35 -0
- package/bundled/dev-pipeline/templates/session-status-schema.json +45 -62
- package/bundled/dev-pipeline/tests/test_checkpoint_state.py +469 -18
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +262 -175
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +62 -23
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +76 -28
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +168 -18
- package/bundled/dev-pipeline/tests/test_recovery_workflow.py +111 -0
- package/bundled/dev-pipeline/tests/test_reset_preserve.py +0 -2
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +608 -0
- package/bundled/dev-pipeline/tests/test_unified_cli.py +167 -25
- package/bundled/skills/_metadata.json +9 -9
- package/bundled/skills/app-planner/SKILL.md +3 -3
- package/bundled/skills/app-planner/references/generated-plan-review.md +2 -1
- package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +56 -64
- package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +85 -240
- package/bundled/skills/app-planner/references/rules/backend/question-bank.md +25 -25
- package/bundled/skills/app-planner/references/rules/backend/question-manifest.json +16 -7
- package/bundled/skills/app-planner/references/rules/backend/template.md +74 -92
- package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +93 -93
- package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +66 -173
- package/bundled/skills/app-planner/references/rules/database/question-bank.md +31 -26
- package/bundled/skills/app-planner/references/rules/database/question-manifest.json +13 -4
- package/bundled/skills/app-planner/references/rules/database/template.md +76 -98
- package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +68 -95
- package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +93 -166
- package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +46 -36
- package/bundled/skills/app-planner/references/rules/frontend/question-manifest.json +11 -2
- package/bundled/skills/app-planner/references/rules/frontend/template.md +79 -257
- package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +91 -99
- package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +73 -246
- package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +17 -17
- package/bundled/skills/app-planner/references/rules/mobile/question-manifest.json +17 -2
- package/bundled/skills/app-planner/references/rules/mobile/template.md +73 -85
- package/bundled/skills/app-planner/references/rules-configuration.md +133 -65
- package/bundled/skills/app-planner/scripts/validate-rules-configuration.py +291 -0
- package/bundled/skills/prizmkit/SKILL.md +17 -18
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +22 -18
- package/bundled/skills/prizmkit-code-review/SKILL.md +22 -58
- package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +6 -6
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +2 -2
- package/bundled/skills/prizmkit-committer/SKILL.md +82 -132
- package/bundled/skills/prizmkit-deploy/SKILL.md +27 -11
- package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +89 -0
- package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +44 -14
- package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +19 -3
- package/bundled/skills/prizmkit-deploy/references/database-setup.md +22 -12
- package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +3 -1
- package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +22 -6
- package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +49 -0
- package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +1 -1
- package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +164 -0
- package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +9 -8
- package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +6 -6
- package/bundled/skills/prizmkit-implement/SKILL.md +30 -66
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +4 -4
- package/bundled/skills/prizmkit-init/SKILL.md +4 -0
- package/bundled/skills/prizmkit-plan/SKILL.md +21 -64
- package/bundled/skills/prizmkit-plan/references/artifact-identity.md +38 -0
- package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +4 -4
- package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +5 -5
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +75 -11
- package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +191 -56
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +18 -18
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +14 -8
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +12 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +23 -12
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -9
- package/bundled/skills/prizmkit-retrospective/SKILL.md +94 -97
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +79 -37
- package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +111 -54
- package/bundled/skills/prizmkit-test/SKILL.md +64 -51
- package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +206 -0
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +17 -9
- package/bundled/skills/prizmkit-test/references/test-coverage-model.md +45 -21
- package/bundled/skills/prizmkit-test/references/test-report-template.md +20 -13
- package/bundled/skills/prizmkit-workflow/SKILL.md +35 -37
- package/bundled/skills/prizmkit-workflow/references/artifact-identity.md +34 -0
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +22 -18
- package/bundled/skills/recovery-workflow/SKILL.md +2 -1
- package/bundled/skills/recovery-workflow/references/detection.md +4 -3
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +15 -5
- package/bundled/templates/hooks/validate-prizm-docs.py +124 -12
- package/package.json +1 -1
- package/src/scaffold.js +33 -22
- package/bundled/dev-pipeline/templates/sections/bugfix-artifacts.md +0 -16
- package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +0 -31
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -7
- package/bundled/dev-pipeline/templates/sections/critical-paths-lite.md +0 -7
- package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +0 -9
- package/bundled/dev-pipeline/templates/sections/directory-convention-lite.md +0 -6
- package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +0 -15
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -61
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -24
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -12
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +0 -44
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -25
- package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +0 -20
- package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +0 -20
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +0 -20
- package/bundled/dev-pipeline/templates/sections/refactor-artifacts.md +0 -17
- package/bundled/dev-pipeline/templates/sections/refactor-session-status.md +0 -28
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +0 -52
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +0 -52
- package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-test/references/external-contract-mock-guidance.md +0 -119
|
@@ -6,6 +6,8 @@ import json
|
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
8
|
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
9
11
|
from prizmkit_runtime.checkpoint_state import (
|
|
10
12
|
VALID_CHECKPOINT_STATUSES,
|
|
11
13
|
VALID_STAGE_RESULTS,
|
|
@@ -14,6 +16,7 @@ from prizmkit_runtime.checkpoint_state import (
|
|
|
14
16
|
read_checkpoint_cursor,
|
|
15
17
|
validate_checkpoint_data,
|
|
16
18
|
)
|
|
19
|
+
from prizmkit_runtime.test_result import load_test_result
|
|
17
20
|
from update_checkpoint import update_checkpoint
|
|
18
21
|
|
|
19
22
|
|
|
@@ -58,8 +61,6 @@ def _write_test_artifacts(root, slug="feature", *, result="TEST_PASS"):
|
|
|
58
61
|
},
|
|
59
62
|
"repair_rounds": 0,
|
|
60
63
|
"production_changed": False,
|
|
61
|
-
"review_required": False,
|
|
62
|
-
"review_scope": None,
|
|
63
64
|
"unresolved_items": [],
|
|
64
65
|
}
|
|
65
66
|
(artifact_dir / "test-result.json").write_text(
|
|
@@ -73,14 +74,16 @@ def _family_checkpoint(root=None, *, semantic=None, terminal=True):
|
|
|
73
74
|
"prizmkit-implement",
|
|
74
75
|
"prizmkit-code-review",
|
|
75
76
|
"prizmkit-test",
|
|
77
|
+
"completion-summary",
|
|
76
78
|
"prizmkit-retrospective",
|
|
77
79
|
"prizmkit-committer",
|
|
78
|
-
"completion-summary",
|
|
79
80
|
]
|
|
80
81
|
steps = []
|
|
81
82
|
previous = None
|
|
82
83
|
for index, skill in enumerate(skills, start=1):
|
|
83
84
|
step = _step(f"S{index:02d}", skill, skill, "completed", previous)
|
|
85
|
+
if skill == "prizmkit-implement":
|
|
86
|
+
step["stage_result"] = "IMPLEMENTED"
|
|
84
87
|
if skill == "prizmkit-code-review":
|
|
85
88
|
step["stage_result"] = "REVIEW_PASS"
|
|
86
89
|
if skill == "prizmkit-test":
|
|
@@ -89,6 +92,10 @@ def _family_checkpoint(root=None, *, semantic=None, terminal=True):
|
|
|
89
92
|
".prizmkit/specs/feature/test-report.md",
|
|
90
93
|
".prizmkit/specs/feature/test-result.json",
|
|
91
94
|
]
|
|
95
|
+
if skill == "prizmkit-retrospective":
|
|
96
|
+
step["stage_result"] = "RETRO_COMPLETE"
|
|
97
|
+
if skill == "prizmkit-committer":
|
|
98
|
+
step["stage_result"] = "COMMITTED"
|
|
92
99
|
steps.append(step)
|
|
93
100
|
previous = step["id"]
|
|
94
101
|
if root is not None:
|
|
@@ -97,7 +104,14 @@ def _family_checkpoint(root=None, *, semantic=None, terminal=True):
|
|
|
97
104
|
"version": 1,
|
|
98
105
|
"workflow_type": "feature-pipeline",
|
|
99
106
|
"steps": steps,
|
|
100
|
-
"feature_state": semantic or (
|
|
107
|
+
"feature_state": semantic or (
|
|
108
|
+
{
|
|
109
|
+
"terminal_status": "WORKFLOW_COMPLETED",
|
|
110
|
+
"runtime_base_head": "a" * 40,
|
|
111
|
+
"runtime_commit_hash": "b" * 40,
|
|
112
|
+
}
|
|
113
|
+
if terminal else {}
|
|
114
|
+
),
|
|
101
115
|
}
|
|
102
116
|
|
|
103
117
|
|
|
@@ -201,6 +215,16 @@ def test_structural_validation_rejects_status_result_mismatch(tmp_path):
|
|
|
201
215
|
assert state.error_code == "stage_result_status_mismatch"
|
|
202
216
|
|
|
203
217
|
|
|
218
|
+
def test_family_planning_wrappers_own_plan_results(tmp_path):
|
|
219
|
+
for skill in ("context-snapshot-and-plan", "bug-diagnosis-and-plan"):
|
|
220
|
+
step = _step("S01", skill, "Plan", "completed")
|
|
221
|
+
step["stage_result"] = "PLAN_READY"
|
|
222
|
+
state = validate_checkpoint_data(
|
|
223
|
+
_checkpoint([step]), path=tmp_path / f"{skill}.json",
|
|
224
|
+
)
|
|
225
|
+
assert state.valid is True
|
|
226
|
+
|
|
227
|
+
|
|
204
228
|
def test_structural_validation_rejects_stage_result_owner_mismatch(tmp_path):
|
|
205
229
|
for skill in ("prizmkit-test", "custom-stage"):
|
|
206
230
|
step = _step("S01", skill, "Step", "completed")
|
|
@@ -391,7 +415,6 @@ def test_checkpoint_updater_supports_every_owned_stage_result(tmp_path):
|
|
|
391
415
|
("prizmkit-test", "TEST_BLOCKED", "failed"),
|
|
392
416
|
("prizmkit-retrospective", "RETRO_COMPLETE", "completed"),
|
|
393
417
|
("prizmkit-committer", "COMMIT_PENDING", "in_progress"),
|
|
394
|
-
("prizmkit-committer", "COMMITTED", "completed"),
|
|
395
418
|
]
|
|
396
419
|
|
|
397
420
|
assert {stage_result for _skill, stage_result, _status in cases} <= VALID_STAGE_RESULTS
|
|
@@ -404,6 +427,19 @@ def test_checkpoint_updater_supports_every_owned_stage_result(tmp_path):
|
|
|
404
427
|
payload["steps"].insert(0, _step("S01", skill, skill, "pending"))
|
|
405
428
|
target_index = 0
|
|
406
429
|
else:
|
|
430
|
+
payload["steps"].insert(
|
|
431
|
+
0,
|
|
432
|
+
{
|
|
433
|
+
"id": "S00",
|
|
434
|
+
"skill": "context-snapshot-and-plan",
|
|
435
|
+
"name": "Plan",
|
|
436
|
+
"status": "completed",
|
|
437
|
+
"stage_result": "PLAN_READY",
|
|
438
|
+
"required_artifacts": [],
|
|
439
|
+
"depends_on": None,
|
|
440
|
+
},
|
|
441
|
+
)
|
|
442
|
+
payload["steps"][1]["depends_on"] = "S00"
|
|
407
443
|
target_index = next(
|
|
408
444
|
position
|
|
409
445
|
for position, step in enumerate(payload["steps"])
|
|
@@ -511,11 +547,26 @@ def test_family_sequence_mismatch_cannot_complete(tmp_path):
|
|
|
511
547
|
assert state.semantic.error_code == "invalid_stage_sequence"
|
|
512
548
|
|
|
513
549
|
|
|
514
|
-
def
|
|
550
|
+
def test_test_needs_fixes_routes_to_implementation_and_rewinds_stale_gates(tmp_path):
|
|
515
551
|
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
516
|
-
payload["steps"]
|
|
517
|
-
|
|
518
|
-
|
|
552
|
+
payload["steps"].insert(
|
|
553
|
+
0,
|
|
554
|
+
{
|
|
555
|
+
"id": "S00",
|
|
556
|
+
"skill": "context-snapshot-and-plan",
|
|
557
|
+
"name": "Plan",
|
|
558
|
+
"status": "completed",
|
|
559
|
+
"stage_result": "PLAN_READY",
|
|
560
|
+
"required_artifacts": [],
|
|
561
|
+
"depends_on": None,
|
|
562
|
+
},
|
|
563
|
+
)
|
|
564
|
+
payload["steps"][1]["depends_on"] = "S00"
|
|
565
|
+
test_step = next(step for step in payload["steps"] if step["skill"] == "prizmkit-test")
|
|
566
|
+
test_index = payload["steps"].index(test_step)
|
|
567
|
+
test_step["status"] = "in_progress"
|
|
568
|
+
test_step.pop("stage_result")
|
|
569
|
+
for step in payload["steps"][test_index + 1:]:
|
|
519
570
|
step["status"] = "pending"
|
|
520
571
|
step.pop("stage_result", None)
|
|
521
572
|
checkpoint = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
@@ -524,16 +575,80 @@ def test_test_needs_fixes_is_valid_domain_result_and_blocks_l4(tmp_path):
|
|
|
524
575
|
str(checkpoint),
|
|
525
576
|
"prizmkit-test",
|
|
526
577
|
"failed",
|
|
527
|
-
semantic_update={
|
|
578
|
+
semantic_update={
|
|
579
|
+
"stage_result": "TEST_NEEDS_FIXES",
|
|
580
|
+
"repair_scope": "production",
|
|
581
|
+
},
|
|
528
582
|
)
|
|
529
|
-
|
|
583
|
+
routed = json.loads(checkpoint.read_text(encoding="utf-8"))
|
|
530
584
|
|
|
531
585
|
assert result["ok"] is True
|
|
532
|
-
assert
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
assert "
|
|
586
|
+
assert test_step["skill"] == "prizmkit-test"
|
|
587
|
+
persisted_test = next(
|
|
588
|
+
step for step in routed["steps"] if step["skill"] == "prizmkit-test"
|
|
589
|
+
)
|
|
590
|
+
assert persisted_test["stage_result"] == "TEST_NEEDS_FIXES"
|
|
591
|
+
assert routed["feature_state"]["stage_result"] == "TEST_NEEDS_FIXES"
|
|
592
|
+
assert routed["feature_state"]["next_stage"] == "prizmkit-implement"
|
|
593
|
+
assert routed["feature_state"]["repair_round"] == 1
|
|
594
|
+
|
|
595
|
+
restarted = update_checkpoint(
|
|
596
|
+
str(checkpoint), "prizmkit-implement", "in_progress"
|
|
597
|
+
)
|
|
598
|
+
rewound = json.loads(checkpoint.read_text(encoding="utf-8"))
|
|
599
|
+
|
|
600
|
+
assert restarted["ok"] is True
|
|
601
|
+
implementation = next(
|
|
602
|
+
step for step in rewound["steps"] if step["skill"] == "prizmkit-implement"
|
|
603
|
+
)
|
|
604
|
+
assert implementation["status"] == "in_progress"
|
|
605
|
+
for step in rewound["steps"][rewound["steps"].index(implementation) + 1:]:
|
|
606
|
+
assert step["status"] == "pending"
|
|
607
|
+
assert "stage_result" not in step
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
def test_terminal_atomic_blockers_become_workflow_blocked(tmp_path):
|
|
611
|
+
cases = [
|
|
612
|
+
("context-snapshot-and-plan", "PLAN_BLOCKED"),
|
|
613
|
+
("prizmkit-implement", "IMPLEMENT_BLOCKED"),
|
|
614
|
+
("prizmkit-retrospective", "RETRO_BLOCKED"),
|
|
615
|
+
("prizmkit-committer", "COMMIT_BLOCKED"),
|
|
616
|
+
]
|
|
617
|
+
for index, (skill, stage_result) in enumerate(cases):
|
|
618
|
+
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
619
|
+
if skill == "context-snapshot-and-plan":
|
|
620
|
+
payload["steps"].insert(
|
|
621
|
+
0,
|
|
622
|
+
{
|
|
623
|
+
"id": "S00",
|
|
624
|
+
"skill": skill,
|
|
625
|
+
"name": "Plan",
|
|
626
|
+
"status": "pending",
|
|
627
|
+
"required_artifacts": [],
|
|
628
|
+
"depends_on": None,
|
|
629
|
+
},
|
|
630
|
+
)
|
|
631
|
+
payload["steps"][1]["depends_on"] = "S00"
|
|
632
|
+
target_index = 0
|
|
633
|
+
else:
|
|
634
|
+
target_index = next(
|
|
635
|
+
position for position, step in enumerate(payload["steps"])
|
|
636
|
+
if step["skill"] == skill
|
|
637
|
+
)
|
|
638
|
+
for step in payload["steps"][target_index:]:
|
|
639
|
+
step["status"] = "pending"
|
|
640
|
+
step.pop("stage_result", None)
|
|
641
|
+
checkpoint = _write(tmp_path / f"terminal-blocker-{index}.json", payload)
|
|
642
|
+
|
|
643
|
+
result = update_checkpoint(
|
|
644
|
+
str(checkpoint), skill, "failed",
|
|
645
|
+
semantic_update={"stage_result": stage_result},
|
|
646
|
+
)
|
|
647
|
+
persisted = json.loads(checkpoint.read_text(encoding="utf-8"))
|
|
648
|
+
|
|
649
|
+
assert result["ok"] is True
|
|
650
|
+
assert persisted["feature_state"]["terminal_status"] == "WORKFLOW_BLOCKED"
|
|
651
|
+
assert persisted["feature_state"]["blocked_reason"]
|
|
537
652
|
|
|
538
653
|
|
|
539
654
|
def test_test_blocked_preserves_l1_result_without_evidence_discovery(tmp_path):
|
|
@@ -602,6 +717,31 @@ def test_update_checkpoint_rejects_test_completion_for_non_pass(tmp_path):
|
|
|
602
717
|
assert "requires TEST_PASS" in result["error"]
|
|
603
718
|
|
|
604
719
|
|
|
720
|
+
def test_prompt_checkpoint_helper_rejects_runtime_owned_committed_result(tmp_path):
|
|
721
|
+
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
722
|
+
committer = next(
|
|
723
|
+
step for step in payload["steps"] if step["skill"] == "prizmkit-committer"
|
|
724
|
+
)
|
|
725
|
+
committer["status"] = "in_progress"
|
|
726
|
+
committer["stage_result"] = "COMMIT_PENDING"
|
|
727
|
+
checkpoint = _write(tmp_path / "workflow-checkpoint.json", payload)
|
|
728
|
+
|
|
729
|
+
result = update_checkpoint(
|
|
730
|
+
str(checkpoint),
|
|
731
|
+
"prizmkit-committer",
|
|
732
|
+
"completed",
|
|
733
|
+
semantic_update={"stage_result": "COMMITTED"},
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
assert result["ok"] is False
|
|
737
|
+
assert "Runtime-owned" in result["error"]
|
|
738
|
+
without_result = update_checkpoint(
|
|
739
|
+
str(checkpoint), "prizmkit-committer", "completed"
|
|
740
|
+
)
|
|
741
|
+
assert without_result["ok"] is False
|
|
742
|
+
assert "Runtime-owned COMMITTED" in without_result["error"]
|
|
743
|
+
|
|
744
|
+
|
|
605
745
|
def test_update_checkpoint_rejects_test_before_review_pass(tmp_path):
|
|
606
746
|
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
607
747
|
payload["steps"][1]["status"] = "skipped"
|
|
@@ -623,7 +763,7 @@ def test_update_checkpoint_rejects_finalization_before_test_pass(tmp_path):
|
|
|
623
763
|
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
624
764
|
payload["steps"][2]["status"] = "skipped"
|
|
625
765
|
payload["steps"][2].pop("stage_result", None)
|
|
626
|
-
payload["steps"][3]["status"] = "
|
|
766
|
+
payload["steps"][3]["status"] = "completed"
|
|
627
767
|
for step in payload["steps"][4:]:
|
|
628
768
|
step["status"] = "pending"
|
|
629
769
|
step.pop("stage_result", None)
|
|
@@ -635,9 +775,53 @@ def test_update_checkpoint_rejects_finalization_before_test_pass(tmp_path):
|
|
|
635
775
|
assert "TEST_PASS" in result["error"]
|
|
636
776
|
|
|
637
777
|
|
|
778
|
+
def test_commit_pending_is_runtime_ready_but_not_workflow_complete(tmp_path):
|
|
779
|
+
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
780
|
+
payload["steps"].insert(
|
|
781
|
+
0,
|
|
782
|
+
{
|
|
783
|
+
"id": "S00",
|
|
784
|
+
"skill": "context-snapshot-and-plan",
|
|
785
|
+
"name": "Plan",
|
|
786
|
+
"status": "completed",
|
|
787
|
+
"stage_result": "PLAN_READY",
|
|
788
|
+
"required_artifacts": [],
|
|
789
|
+
"depends_on": None,
|
|
790
|
+
},
|
|
791
|
+
)
|
|
792
|
+
payload["steps"][1]["depends_on"] = "S00"
|
|
793
|
+
committer = next(
|
|
794
|
+
step for step in payload["steps"] if step["skill"] == "prizmkit-committer"
|
|
795
|
+
)
|
|
796
|
+
committer["status"] = "in_progress"
|
|
797
|
+
committer["stage_result"] = "COMMIT_PENDING"
|
|
798
|
+
committer["required_artifacts"] = [
|
|
799
|
+
".prizmkit/specs/feature/runtime-commit-request.json"
|
|
800
|
+
]
|
|
801
|
+
artifact_dir = tmp_path / ".prizmkit/specs/feature"
|
|
802
|
+
(artifact_dir / "runtime-commit-request.json").write_text("{}", encoding="utf-8")
|
|
803
|
+
payload["feature_state"] = {
|
|
804
|
+
"stage": "committer",
|
|
805
|
+
"status": "in_progress",
|
|
806
|
+
"stage_result": "COMMIT_PENDING",
|
|
807
|
+
"repair_round": 0,
|
|
808
|
+
}
|
|
809
|
+
checkpoint = _write(artifact_dir / "workflow-checkpoint.json", payload)
|
|
810
|
+
|
|
811
|
+
state = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
812
|
+
|
|
813
|
+
assert state.valid is True
|
|
814
|
+
assert state.semantic_commit_ready is True
|
|
815
|
+
assert state.semantic_complete is False
|
|
816
|
+
assert state.semantic_snapshot["commit_ready"] is True
|
|
817
|
+
|
|
818
|
+
|
|
638
819
|
def test_declared_final_artifact_must_exist_for_completion(tmp_path):
|
|
639
820
|
payload = _family_checkpoint(tmp_path)
|
|
640
|
-
|
|
821
|
+
summary_step = next(
|
|
822
|
+
step for step in payload["steps"] if step["skill"] == "completion-summary"
|
|
823
|
+
)
|
|
824
|
+
summary_step["required_artifacts"] = [
|
|
641
825
|
".prizmkit/specs/feature/completion-summary.json"
|
|
642
826
|
]
|
|
643
827
|
checkpoint = _write(
|
|
@@ -655,6 +839,239 @@ def test_declared_final_artifact_must_exist_for_completion(tmp_path):
|
|
|
655
839
|
assert present.semantic.artifacts_valid is True
|
|
656
840
|
|
|
657
841
|
|
|
842
|
+
def test_completion_requires_declared_review_report_with_terminal_pass(tmp_path):
|
|
843
|
+
payload = _family_checkpoint(tmp_path)
|
|
844
|
+
review = next(
|
|
845
|
+
step for step in payload["steps"]
|
|
846
|
+
if step["skill"] == "prizmkit-code-review"
|
|
847
|
+
)
|
|
848
|
+
review["required_artifacts"] = [
|
|
849
|
+
".prizmkit/specs/feature/review-report.md"
|
|
850
|
+
]
|
|
851
|
+
checkpoint = _write(
|
|
852
|
+
tmp_path / ".prizmkit/specs/feature/workflow-checkpoint.json", payload,
|
|
853
|
+
)
|
|
854
|
+
|
|
855
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is False
|
|
856
|
+
(checkpoint.parent / "review-report.md").write_text(
|
|
857
|
+
"# Review Report\n\n## Final Result\n\n- Verdict: NEEDS_FIXES\n",
|
|
858
|
+
encoding="utf-8",
|
|
859
|
+
)
|
|
860
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is False
|
|
861
|
+
(checkpoint.parent / "review-report.md").write_text(
|
|
862
|
+
"# Review Report\n\n## Final Result\n\n- Verdict: PASS\n",
|
|
863
|
+
encoding="utf-8",
|
|
864
|
+
)
|
|
865
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is True
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
def test_completion_requires_valid_declared_retrospective_result(tmp_path):
|
|
869
|
+
payload = _family_checkpoint(tmp_path)
|
|
870
|
+
retrospective = next(
|
|
871
|
+
step for step in payload["steps"]
|
|
872
|
+
if step["skill"] == "prizmkit-retrospective"
|
|
873
|
+
)
|
|
874
|
+
retrospective["required_artifacts"] = [
|
|
875
|
+
".prizmkit/specs/feature/retrospective-result.json"
|
|
876
|
+
]
|
|
877
|
+
checkpoint = _write(
|
|
878
|
+
tmp_path / ".prizmkit/specs/feature/workflow-checkpoint.json", payload,
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
(checkpoint.parent / "retrospective-result.json").write_text(
|
|
882
|
+
"{}\n", encoding="utf-8",
|
|
883
|
+
)
|
|
884
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is False
|
|
885
|
+
(checkpoint.parent / "retrospective-result.json").write_text(
|
|
886
|
+
json.dumps(
|
|
887
|
+
{
|
|
888
|
+
"schema_version": 1,
|
|
889
|
+
"outcome": "RETRO_COMPLETE",
|
|
890
|
+
"result": "NO_DOC_CHANGE",
|
|
891
|
+
"reason": "No durable change",
|
|
892
|
+
"change_paths": ["src/example.py"],
|
|
893
|
+
"documentation_paths": [],
|
|
894
|
+
"validation": [],
|
|
895
|
+
}
|
|
896
|
+
),
|
|
897
|
+
encoding="utf-8",
|
|
898
|
+
)
|
|
899
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is True
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
@pytest.mark.parametrize(
|
|
903
|
+
"invalid_path",
|
|
904
|
+
[
|
|
905
|
+
".prizmkit/prizm-docs/../escape.prizm",
|
|
906
|
+
".prizmkit/prizm-docs/./module.prizm",
|
|
907
|
+
".prizmkit/prizm-docs//module.prizm",
|
|
908
|
+
".prizmkit\\prizm-docs\\module.prizm",
|
|
909
|
+
".prizmkit/prizm-docs/module.md",
|
|
910
|
+
],
|
|
911
|
+
)
|
|
912
|
+
def test_completion_rejects_unsafe_retrospective_documentation_path(
|
|
913
|
+
tmp_path, invalid_path,
|
|
914
|
+
):
|
|
915
|
+
payload = _family_checkpoint(tmp_path)
|
|
916
|
+
retrospective = next(
|
|
917
|
+
step for step in payload["steps"]
|
|
918
|
+
if step["skill"] == "prizmkit-retrospective"
|
|
919
|
+
)
|
|
920
|
+
retrospective["required_artifacts"] = [
|
|
921
|
+
".prizmkit/specs/feature/retrospective-result.json"
|
|
922
|
+
]
|
|
923
|
+
checkpoint = _write(
|
|
924
|
+
tmp_path / ".prizmkit/specs/feature/workflow-checkpoint.json", payload,
|
|
925
|
+
)
|
|
926
|
+
(checkpoint.parent / "retrospective-result.json").write_text(
|
|
927
|
+
json.dumps(
|
|
928
|
+
{
|
|
929
|
+
"schema_version": 1,
|
|
930
|
+
"outcome": "RETRO_COMPLETE",
|
|
931
|
+
"result": "DOCS_UPDATED",
|
|
932
|
+
"reason": "Durable docs changed",
|
|
933
|
+
"change_paths": ["src/example.py"],
|
|
934
|
+
"documentation_paths": [invalid_path],
|
|
935
|
+
"validation": ["validate docs"],
|
|
936
|
+
}
|
|
937
|
+
),
|
|
938
|
+
encoding="utf-8",
|
|
939
|
+
)
|
|
940
|
+
|
|
941
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is False
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
@pytest.mark.parametrize(
|
|
945
|
+
"invalid_path",
|
|
946
|
+
["../escape.py", "./src/example.py", "src//example.py", "src\\example.py"],
|
|
947
|
+
)
|
|
948
|
+
def test_completion_rejects_unsafe_retrospective_change_path(tmp_path, invalid_path):
|
|
949
|
+
payload = _family_checkpoint(tmp_path)
|
|
950
|
+
retrospective = next(
|
|
951
|
+
step for step in payload["steps"]
|
|
952
|
+
if step["skill"] == "prizmkit-retrospective"
|
|
953
|
+
)
|
|
954
|
+
retrospective["required_artifacts"] = [
|
|
955
|
+
".prizmkit/specs/feature/retrospective-result.json"
|
|
956
|
+
]
|
|
957
|
+
checkpoint = _write(
|
|
958
|
+
tmp_path / ".prizmkit/specs/feature/workflow-checkpoint.json", payload,
|
|
959
|
+
)
|
|
960
|
+
(checkpoint.parent / "retrospective-result.json").write_text(
|
|
961
|
+
json.dumps(
|
|
962
|
+
{
|
|
963
|
+
"schema_version": 1,
|
|
964
|
+
"outcome": "RETRO_COMPLETE",
|
|
965
|
+
"result": "NO_DOC_CHANGE",
|
|
966
|
+
"reason": "No durable change",
|
|
967
|
+
"change_paths": [invalid_path],
|
|
968
|
+
"documentation_paths": [],
|
|
969
|
+
"validation": [],
|
|
970
|
+
}
|
|
971
|
+
),
|
|
972
|
+
encoding="utf-8",
|
|
973
|
+
)
|
|
974
|
+
|
|
975
|
+
assert load_checkpoint_state(checkpoint, project_root=tmp_path).semantic_complete is False
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
def test_completion_rejects_configured_verification_after_test(tmp_path):
|
|
979
|
+
payload = _family_checkpoint(tmp_path)
|
|
980
|
+
test_index = next(
|
|
981
|
+
index for index, step in enumerate(payload["steps"])
|
|
982
|
+
if step["skill"] == "prizmkit-test"
|
|
983
|
+
)
|
|
984
|
+
test_step = payload["steps"][test_index]
|
|
985
|
+
following = payload["steps"][test_index + 1]
|
|
986
|
+
payload["steps"].insert(
|
|
987
|
+
test_index + 1,
|
|
988
|
+
{
|
|
989
|
+
"id": "S99",
|
|
990
|
+
"skill": "browser-verification",
|
|
991
|
+
"name": "Browser Verification",
|
|
992
|
+
"status": "completed",
|
|
993
|
+
"required_artifacts": [],
|
|
994
|
+
"depends_on": test_step["id"],
|
|
995
|
+
},
|
|
996
|
+
)
|
|
997
|
+
following["depends_on"] = "S99"
|
|
998
|
+
|
|
999
|
+
state = validate_checkpoint_data(payload, project_root=tmp_path)
|
|
1000
|
+
|
|
1001
|
+
assert state.semantic.sequence_valid is False
|
|
1002
|
+
assert "after review and before test" in state.semantic.error_message
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
def test_configured_manual_verification_cannot_be_skipped_for_commit_readiness(tmp_path):
|
|
1006
|
+
payload = _family_checkpoint(tmp_path, semantic={}, terminal=False)
|
|
1007
|
+
payload["steps"].insert(
|
|
1008
|
+
0,
|
|
1009
|
+
{
|
|
1010
|
+
"id": "S00",
|
|
1011
|
+
"skill": "context-snapshot-and-plan",
|
|
1012
|
+
"name": "Plan",
|
|
1013
|
+
"status": "completed",
|
|
1014
|
+
"stage_result": "PLAN_READY",
|
|
1015
|
+
"required_artifacts": [],
|
|
1016
|
+
"depends_on": None,
|
|
1017
|
+
},
|
|
1018
|
+
)
|
|
1019
|
+
payload["steps"][1]["depends_on"] = "S00"
|
|
1020
|
+
review = next(
|
|
1021
|
+
step for step in payload["steps"]
|
|
1022
|
+
if step["skill"] == "prizmkit-code-review"
|
|
1023
|
+
)
|
|
1024
|
+
test = next(
|
|
1025
|
+
step for step in payload["steps"] if step["skill"] == "prizmkit-test"
|
|
1026
|
+
)
|
|
1027
|
+
test_index = payload["steps"].index(test)
|
|
1028
|
+
payload["steps"].insert(
|
|
1029
|
+
test_index,
|
|
1030
|
+
{
|
|
1031
|
+
"id": "S99",
|
|
1032
|
+
"skill": "manual-verification",
|
|
1033
|
+
"name": "Manual Verification",
|
|
1034
|
+
"status": "skipped",
|
|
1035
|
+
"required_artifacts": [],
|
|
1036
|
+
"depends_on": review["id"],
|
|
1037
|
+
},
|
|
1038
|
+
)
|
|
1039
|
+
test["depends_on"] = "S99"
|
|
1040
|
+
committer = next(
|
|
1041
|
+
step for step in payload["steps"]
|
|
1042
|
+
if step["skill"] == "prizmkit-committer"
|
|
1043
|
+
)
|
|
1044
|
+
committer["status"] = "in_progress"
|
|
1045
|
+
committer["stage_result"] = "COMMIT_PENDING"
|
|
1046
|
+
committer["required_artifacts"] = [
|
|
1047
|
+
".prizmkit/specs/feature/runtime-commit-request.json"
|
|
1048
|
+
]
|
|
1049
|
+
artifact_dir = tmp_path / ".prizmkit/specs/feature"
|
|
1050
|
+
(artifact_dir / "runtime-commit-request.json").write_text("{}", encoding="utf-8")
|
|
1051
|
+
checkpoint = _write(artifact_dir / "workflow-checkpoint.json", payload)
|
|
1052
|
+
|
|
1053
|
+
skipped = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
1054
|
+
payload["steps"][test_index]["status"] = "completed"
|
|
1055
|
+
checkpoint.write_text(json.dumps(payload), encoding="utf-8")
|
|
1056
|
+
completed = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
1057
|
+
|
|
1058
|
+
assert skipped.semantic_commit_ready is False
|
|
1059
|
+
assert completed.semantic_commit_ready is True
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
def test_nonpass_test_projection_requires_exact_unresolved_item(tmp_path):
|
|
1063
|
+
artifact_dir = _write_test_artifacts(
|
|
1064
|
+
tmp_path, slug="nonpass", result="TEST_NEEDS_FIXES"
|
|
1065
|
+
)
|
|
1066
|
+
result_path = artifact_dir / "test-result.json"
|
|
1067
|
+
|
|
1068
|
+
assert load_test_result(result_path) is None
|
|
1069
|
+
projection = json.loads(result_path.read_text(encoding="utf-8"))
|
|
1070
|
+
projection["unresolved_items"] = ["Public API correction remains"]
|
|
1071
|
+
result_path.write_text(json.dumps(projection), encoding="utf-8")
|
|
1072
|
+
assert load_test_result(result_path) is not None
|
|
1073
|
+
|
|
1074
|
+
|
|
658
1075
|
def test_completion_rejects_invalid_test_result_projection(tmp_path):
|
|
659
1076
|
payload = _family_checkpoint(tmp_path)
|
|
660
1077
|
checkpoint = _write(
|
|
@@ -694,6 +1111,40 @@ def test_completion_rejects_inconsistent_independent_review_metadata(tmp_path):
|
|
|
694
1111
|
assert state.semantic.artifacts_valid is False
|
|
695
1112
|
|
|
696
1113
|
|
|
1114
|
+
def test_legacy_completed_checkpoint_accepts_historical_test_projection_read_only(tmp_path):
|
|
1115
|
+
payload = _family_checkpoint(tmp_path)
|
|
1116
|
+
by_skill = {step["skill"]: step for step in payload["steps"]}
|
|
1117
|
+
legacy_order = [
|
|
1118
|
+
"prizmkit-implement",
|
|
1119
|
+
"prizmkit-code-review",
|
|
1120
|
+
"prizmkit-test",
|
|
1121
|
+
"prizmkit-retrospective",
|
|
1122
|
+
"prizmkit-committer",
|
|
1123
|
+
"completion-summary",
|
|
1124
|
+
]
|
|
1125
|
+
payload["steps"] = [by_skill[skill] for skill in legacy_order]
|
|
1126
|
+
previous = None
|
|
1127
|
+
for index, step in enumerate(payload["steps"], start=1):
|
|
1128
|
+
step["id"] = f"S{index:02d}"
|
|
1129
|
+
step["depends_on"] = previous
|
|
1130
|
+
previous = step["id"]
|
|
1131
|
+
checkpoint = _write(
|
|
1132
|
+
tmp_path / ".prizmkit/specs/feature/workflow-checkpoint.json", payload,
|
|
1133
|
+
)
|
|
1134
|
+
result_path = checkpoint.parent / "test-result.json"
|
|
1135
|
+
projection = json.loads(result_path.read_text(encoding="utf-8"))
|
|
1136
|
+
projection["review_required"] = False
|
|
1137
|
+
projection["review_scope"] = None
|
|
1138
|
+
result_path.write_text(json.dumps(projection), encoding="utf-8")
|
|
1139
|
+
assert load_test_result(result_path) is None
|
|
1140
|
+
|
|
1141
|
+
state = load_checkpoint_state(checkpoint, project_root=tmp_path)
|
|
1142
|
+
|
|
1143
|
+
assert state.semantic_complete is True
|
|
1144
|
+
assert state.semantic.artifacts_valid is True
|
|
1145
|
+
assert state.semantic_commit_ready is False
|
|
1146
|
+
|
|
1147
|
+
|
|
697
1148
|
def test_completion_accepts_legacy_terminal_result_report(tmp_path):
|
|
698
1149
|
payload = _family_checkpoint(tmp_path)
|
|
699
1150
|
checkpoint = _write(
|