prizmkit 1.1.139 → 1.1.141
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/prizmkit_runtime/checkpoint_state.py +41 -121
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -6
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +1 -2
- package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +150 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +21 -804
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +4 -6
- package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +1 -1
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +4 -6
- package/bundled/dev-pipeline/scripts/prompt_framework.py +56 -55
- package/bundled/dev-pipeline/scripts/update-bug-status.py +1 -2
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +14 -96
- package/bundled/dev-pipeline/scripts/update-feature-status.py +1 -2
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +1 -2
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +3 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -18
- 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-test.md +13 -10
- package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +1 -1
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +14 -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-specify-plan-full.md +3 -3
- 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/tests/test_checkpoint_state.py +287 -384
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +119 -684
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +17 -40
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +20 -23
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +29 -32
- package/bundled/skills/_metadata.json +6 -6
- package/bundled/skills/prizmkit/SKILL.md +8 -13
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-code-review/SKILL.md +3 -3
- package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-committer/SKILL.md +3 -3
- package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-retrospective/SKILL.md +2 -2
- package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +61 -80
- package/bundled/skills/prizmkit-test/SKILL.md +217 -187
- 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 +15 -23
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +61 -80
- package/package.json +1 -1
- package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +0 -476
- 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 -110
- package/bundled/skills/prizmkit-test/references/workflow-state-protocol.md +0 -181
- package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +0 -1851
- package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +0 -1793
|
@@ -40,15 +40,14 @@ def route_bugfix_repair(stage_result, repair_scope=None, repair_round=0):
|
|
|
40
40
|
return route_pipeline_repair(stage_result, repair_scope, repair_round)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def bugfix_checkpoint_metadata(artifact_dir,
|
|
43
|
+
def bugfix_checkpoint_metadata(artifact_dir, stage="plan",
|
|
44
44
|
status="PLAN_READY", stage_result=None,
|
|
45
45
|
repair_scope=None, repair_round=0,
|
|
46
46
|
next_stage="prizmkit-implement",
|
|
47
47
|
resume_from="prizmkit-implement"):
|
|
48
|
-
"""Build Bugfix
|
|
48
|
+
"""Build Bugfix pipeline handoff metadata while preserving skill state."""
|
|
49
49
|
return pipeline_checkpoint_metadata(
|
|
50
50
|
artifact_dir,
|
|
51
|
-
evidence=evidence,
|
|
52
51
|
stage=stage,
|
|
53
52
|
status=status,
|
|
54
53
|
stage_result=stage_result,
|
|
@@ -71,9 +70,8 @@ BUGFIX_SECTION_TO_SKILL = {
|
|
|
71
70
|
"bugfix-phase-test": checkpoint_step(
|
|
72
71
|
"prizmkit-test", "Post-Review Test Gate",
|
|
73
72
|
[
|
|
74
|
-
".prizmkit/test
|
|
75
|
-
".prizmkit/test
|
|
76
|
-
".prizmkit/test/evidence/*/validation.json",
|
|
73
|
+
".prizmkit/bugfix/{slug}/test-report.md",
|
|
74
|
+
".prizmkit/bugfix/{slug}/test-result.json",
|
|
77
75
|
],
|
|
78
76
|
),
|
|
79
77
|
"phase-browser": checkpoint_step("browser-verification", "Browser Verification", []),
|
|
@@ -67,7 +67,7 @@ affected files, and root cause hypothesis.""",
|
|
|
67
67
|
"Triage",
|
|
68
68
|
"""\
|
|
69
69
|
Locate affected code and identify root cause:
|
|
70
|
-
1. Read `.prizmkit/prizm-docs/root.prizm` then relevant
|
|
70
|
+
1. Read `.prizmkit/prizm-docs/root.prizm` then the relevant module indexes and detail docs for affected modules
|
|
71
71
|
2. Read files mentioned in the bug description or error/stack trace
|
|
72
72
|
3. Check `.prizmkit/prizm-docs/` TRAPS for known patterns
|
|
73
73
|
4. Classify: root cause (confirmed/suspected), blast radius, fix complexity
|
|
@@ -40,15 +40,14 @@ def route_refactor_repair(stage_result, repair_scope=None, repair_round=0):
|
|
|
40
40
|
return route_pipeline_repair(stage_result, repair_scope, repair_round)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def refactor_checkpoint_metadata(artifact_dir,
|
|
43
|
+
def refactor_checkpoint_metadata(artifact_dir, stage="plan",
|
|
44
44
|
status="PLAN_READY", stage_result=None,
|
|
45
45
|
repair_scope=None, repair_round=0,
|
|
46
46
|
next_stage="prizmkit-implement",
|
|
47
47
|
resume_from="prizmkit-implement"):
|
|
48
|
-
"""Build Refactor
|
|
48
|
+
"""Build Refactor pipeline handoff metadata while preserving skill state."""
|
|
49
49
|
return pipeline_checkpoint_metadata(
|
|
50
50
|
artifact_dir,
|
|
51
|
-
evidence=evidence,
|
|
52
51
|
stage=stage,
|
|
53
52
|
status=status,
|
|
54
53
|
stage_result=stage_result,
|
|
@@ -76,9 +75,8 @@ REFACTOR_SECTION_TO_SKILL = {
|
|
|
76
75
|
"refactor-phase-test": checkpoint_step(
|
|
77
76
|
"prizmkit-test", "Post-Review Test Gate",
|
|
78
77
|
[
|
|
79
|
-
".prizmkit/test
|
|
80
|
-
".prizmkit/test
|
|
81
|
-
".prizmkit/test/evidence/*/validation.json",
|
|
78
|
+
".prizmkit/refactor/{slug}/test-report.md",
|
|
79
|
+
".prizmkit/refactor/{slug}/test-result.json",
|
|
82
80
|
],
|
|
83
81
|
),
|
|
84
82
|
"phase-browser": checkpoint_step("browser-verification", "Browser Verification", []),
|
|
@@ -8,20 +8,20 @@ so feature, bugfix, and refactor prompts do not drift.
|
|
|
8
8
|
import glob
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
_PIPELINE_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
14
|
+
if _PIPELINE_ROOT not in sys.path:
|
|
15
|
+
sys.path.insert(0, _PIPELINE_ROOT)
|
|
16
|
+
|
|
17
|
+
from prizmkit_runtime.test_result import valid_test_artifact_pair # noqa: E402
|
|
11
18
|
|
|
12
19
|
|
|
13
20
|
MAX_OUTER_REPAIR_ROUNDS = 3
|
|
14
|
-
REPAIR_SCOPES_REQUIRING_REVIEW = {
|
|
15
|
-
"production",
|
|
16
|
-
"runtime",
|
|
17
|
-
"schema",
|
|
18
|
-
"dependency",
|
|
19
|
-
"public-interface",
|
|
20
|
-
}
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
|
|
24
|
-
"""Map review/test outcomes to bounded, safe
|
|
24
|
+
"""Map review/test outcomes to bounded, safe pipeline continuation routes."""
|
|
25
25
|
try:
|
|
26
26
|
current_round = int(repair_round)
|
|
27
27
|
except (TypeError, ValueError):
|
|
@@ -46,19 +46,28 @@ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
|
|
|
46
46
|
result.update(
|
|
47
47
|
next_stage="prizmkit-retrospective",
|
|
48
48
|
resume_from="prizmkit-retrospective",
|
|
49
|
-
reason="
|
|
49
|
+
reason="project-native tests passed",
|
|
50
50
|
)
|
|
51
51
|
return result
|
|
52
52
|
if stage_result == "TEST_BLOCKED":
|
|
53
53
|
result.update(
|
|
54
54
|
blocked=True,
|
|
55
55
|
resumable=False,
|
|
56
|
-
reason="
|
|
56
|
+
reason="testing could not establish a safe verdict",
|
|
57
57
|
blocked_reason="test_blocked",
|
|
58
58
|
terminal_status="WORKFLOW_BLOCKED",
|
|
59
59
|
)
|
|
60
60
|
return result
|
|
61
|
-
if stage_result
|
|
61
|
+
if stage_result == "TEST_NEEDS_FIXES":
|
|
62
|
+
result.update(
|
|
63
|
+
blocked=True,
|
|
64
|
+
resumable=False,
|
|
65
|
+
reason="prizmkit-test stopped with a known remaining correction",
|
|
66
|
+
blocked_reason="test_needs_fixes",
|
|
67
|
+
terminal_status="WORKFLOW_BLOCKED",
|
|
68
|
+
)
|
|
69
|
+
return result
|
|
70
|
+
if stage_result != "REVIEW_NEEDS_FIXES":
|
|
62
71
|
result.update(
|
|
63
72
|
blocked=True,
|
|
64
73
|
reason="unknown stage result is unsafe",
|
|
@@ -76,55 +85,22 @@ def route_pipeline_repair(stage_result, repair_scope=None, repair_round=0):
|
|
|
76
85
|
return result
|
|
77
86
|
|
|
78
87
|
result["repair_round"] = current_round + 1
|
|
79
|
-
if stage_result == "REVIEW_NEEDS_FIXES":
|
|
80
|
-
result.update(
|
|
81
|
-
next_stage="prizmkit-implement",
|
|
82
|
-
resume_from="prizmkit-implement",
|
|
83
|
-
route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
|
|
84
|
-
reason="review findings require implementation and fresh review",
|
|
85
|
-
)
|
|
86
|
-
return result
|
|
87
|
-
if repair_scope == "test-infrastructure":
|
|
88
|
-
result.update(
|
|
89
|
-
next_stage="prizmkit-implement",
|
|
90
|
-
resume_from="prizmkit-implement",
|
|
91
|
-
route=["prizmkit-implement", "prizmkit-test"],
|
|
92
|
-
reason="test infrastructure failure must not edit production speculatively",
|
|
93
|
-
)
|
|
94
|
-
return result
|
|
95
|
-
if repair_scope in REPAIR_SCOPES_REQUIRING_REVIEW:
|
|
96
|
-
result.update(
|
|
97
|
-
next_stage="prizmkit-implement",
|
|
98
|
-
resume_from="prizmkit-implement",
|
|
99
|
-
route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
|
|
100
|
-
reason="production-facing failure requires review before retesting",
|
|
101
|
-
)
|
|
102
|
-
return result
|
|
103
88
|
result.update(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
89
|
+
next_stage="prizmkit-implement",
|
|
90
|
+
resume_from="prizmkit-implement",
|
|
91
|
+
route=["prizmkit-implement", "prizmkit-code-review", "prizmkit-test"],
|
|
92
|
+
reason="review findings require implementation and fresh review",
|
|
108
93
|
)
|
|
109
94
|
return result
|
|
110
95
|
|
|
111
96
|
|
|
112
|
-
def pipeline_checkpoint_metadata(artifact_dir,
|
|
97
|
+
def pipeline_checkpoint_metadata(artifact_dir, stage="plan",
|
|
113
98
|
status="PLAN_READY", stage_result=None,
|
|
114
99
|
repair_scope=None, repair_round=0,
|
|
115
100
|
next_stage="prizmkit-implement",
|
|
116
101
|
resume_from="prizmkit-implement",
|
|
117
102
|
blocked_reason=None, terminal_status=None):
|
|
118
|
-
"""Build family-neutral
|
|
119
|
-
evidence = evidence or {}
|
|
120
|
-
if evidence:
|
|
121
|
-
evidence_paths = {
|
|
122
|
-
"manifest": evidence.get("manifest_path"),
|
|
123
|
-
"verdict": evidence.get("verdict_path"),
|
|
124
|
-
"validation": evidence.get("validation_path"),
|
|
125
|
-
}
|
|
126
|
-
else:
|
|
127
|
-
evidence_paths = {"manifest": None, "verdict": None, "validation": None}
|
|
103
|
+
"""Build family-neutral pipeline metadata without replacing skill state."""
|
|
128
104
|
current_stage = None if terminal_status else stage
|
|
129
105
|
semantic_next_stage = None if terminal_status else next_stage
|
|
130
106
|
return {
|
|
@@ -137,7 +113,6 @@ def pipeline_checkpoint_metadata(artifact_dir, evidence=None, stage="plan",
|
|
|
137
113
|
"stage_result": stage_result,
|
|
138
114
|
"repair_scope": repair_scope,
|
|
139
115
|
"repair_round": repair_round,
|
|
140
|
-
"authoritative_evidence_paths": evidence_paths,
|
|
141
116
|
"next_stage": semantic_next_stage,
|
|
142
117
|
"resume_from": resume_from,
|
|
143
118
|
"blocked_reason": blocked_reason,
|
|
@@ -248,6 +223,29 @@ def completed_step_artifacts_valid(project_root, artifacts):
|
|
|
248
223
|
return all(artifact_exists(project_root, artifact) for artifact in artifacts)
|
|
249
224
|
|
|
250
225
|
|
|
226
|
+
def completed_test_artifacts_valid(project_root, artifacts):
|
|
227
|
+
"""Validate a sibling test-report.md and TEST_PASS test-result.json pair."""
|
|
228
|
+
reports = [item for item in artifacts if item.endswith("/test-report.md")]
|
|
229
|
+
results = [item for item in artifacts if item.endswith("/test-result.json")]
|
|
230
|
+
if len(reports) != 1 or len(results) != 1:
|
|
231
|
+
return False
|
|
232
|
+
report_path = os.path.realpath(os.path.join(project_root, reports[0]))
|
|
233
|
+
result_path = os.path.realpath(os.path.join(project_root, results[0]))
|
|
234
|
+
root_path = os.path.realpath(project_root)
|
|
235
|
+
try:
|
|
236
|
+
if os.path.commonpath([root_path, report_path]) != root_path:
|
|
237
|
+
return False
|
|
238
|
+
if os.path.commonpath([root_path, result_path]) != root_path:
|
|
239
|
+
return False
|
|
240
|
+
except ValueError:
|
|
241
|
+
return False
|
|
242
|
+
return valid_test_artifact_pair(
|
|
243
|
+
report_path,
|
|
244
|
+
result_path,
|
|
245
|
+
required_result="TEST_PASS",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
|
|
251
249
|
def checkpoint_skip():
|
|
252
250
|
"""Return an explicit no-checkpoint-step contract for a prompt section."""
|
|
253
251
|
return {"kind": "skip"}
|
|
@@ -360,7 +358,13 @@ def generate_checkpoint_from_sections(
|
|
|
360
358
|
|
|
361
359
|
def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger=None):
|
|
362
360
|
"""Merge existing checkpoint state into a freshly generated definition."""
|
|
363
|
-
validator = validator or (
|
|
361
|
+
validator = validator or (
|
|
362
|
+
lambda skill, artifacts: (
|
|
363
|
+
completed_test_artifacts_valid(project_root, artifacts)
|
|
364
|
+
if skill == "prizmkit-test"
|
|
365
|
+
else completed_step_artifacts_valid(project_root, artifacts)
|
|
366
|
+
)
|
|
367
|
+
)
|
|
364
368
|
existing_by_id = {}
|
|
365
369
|
existing_by_skill = {}
|
|
366
370
|
for step in existing.get("steps", []):
|
|
@@ -402,9 +406,6 @@ def merge_checkpoint_state(existing, fresh, project_root, validator=None, logger
|
|
|
402
406
|
step["status"] = "completed"
|
|
403
407
|
if stage_result:
|
|
404
408
|
step["stage_result"] = stage_result
|
|
405
|
-
evidence = previous.get("authoritative_evidence_paths")
|
|
406
|
-
if isinstance(evidence, dict):
|
|
407
|
-
step["authoritative_evidence_paths"] = evidence
|
|
408
409
|
continue
|
|
409
410
|
if logger is not None:
|
|
410
411
|
logger.warning(
|
|
@@ -89,7 +89,7 @@ def parse_args():
|
|
|
89
89
|
parser.add_argument("--continuation-summary-path", default=None, help="Optional continuation summary artifact path.")
|
|
90
90
|
parser.add_argument("--no-progress-count", type=int, default=None, help="Consecutive context-overflow sessions without objective progress.")
|
|
91
91
|
parser.add_argument("--progress-fingerprint", default=None, help="JSON progress fingerprint captured after the session.")
|
|
92
|
-
parser.add_argument("--checkpoint-state", default=None, help="JSON semantic
|
|
92
|
+
parser.add_argument("--checkpoint-state", default=None, help="JSON semantic pipeline checkpoint snapshot captured after the session.")
|
|
93
93
|
return parser.parse_args()
|
|
94
94
|
|
|
95
95
|
|
|
@@ -261,7 +261,6 @@ SEMANTIC_CHECKPOINT_FIELDS = (
|
|
|
261
261
|
"stage_result",
|
|
262
262
|
"repair_scope",
|
|
263
263
|
"repair_round",
|
|
264
|
-
"authoritative_evidence_paths",
|
|
265
264
|
"blocked_reason",
|
|
266
265
|
"terminal_status",
|
|
267
266
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Atomically update one semantic
|
|
2
|
+
"""Atomically update one semantic pipeline workflow checkpoint."""
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import json
|
|
@@ -120,13 +120,11 @@ def _mandatory_predecessor_verdict_error(steps, index, workflow_type):
|
|
|
120
120
|
return None
|
|
121
121
|
|
|
122
122
|
def _normalize_semantic_update(semantic_update):
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
values["authoritative_evidence_paths"] = evidence
|
|
129
|
-
return {key: value for key, value in values.items() if value is not None}
|
|
123
|
+
return {
|
|
124
|
+
key: value
|
|
125
|
+
for key, value in dict(semantic_update or {}).items()
|
|
126
|
+
if value is not None
|
|
127
|
+
}
|
|
130
128
|
|
|
131
129
|
|
|
132
130
|
def _validate_semantic_update(step, semantic_update):
|
|
@@ -145,24 +143,25 @@ def _validate_semantic_update(step, semantic_update):
|
|
|
145
143
|
terminal_status = semantic_update.get("terminal_status")
|
|
146
144
|
if terminal_status is not None and terminal_status not in VALID_TERMINAL_STATUSES:
|
|
147
145
|
return "Invalid terminal_status '{}'".format(terminal_status)
|
|
148
|
-
evidence = semantic_update.get("authoritative_evidence_paths")
|
|
149
|
-
if evidence is not None and set(evidence) != {"manifest", "verdict", "validation"}:
|
|
150
|
-
return "Authoritative test evidence requires manifest, verdict, and validation paths"
|
|
151
146
|
if terminal_status == "WORKFLOW_BLOCKED" and not semantic_update.get("blocked_reason"):
|
|
152
147
|
return "WORKFLOW_BLOCKED requires blocked_reason"
|
|
153
148
|
return None
|
|
154
149
|
|
|
155
150
|
|
|
156
151
|
def _apply_repair_policy(l4_state, stage_result, repair_scope):
|
|
157
|
-
if stage_result not in {"REVIEW_NEEDS_FIXES", "
|
|
152
|
+
if stage_result not in {"REVIEW_NEEDS_FIXES", "TEST_NEEDS_FIXES", "TEST_BLOCKED"}:
|
|
158
153
|
return
|
|
159
154
|
current_round = l4_state.get("repair_round", 0)
|
|
160
155
|
if not isinstance(current_round, int) or isinstance(current_round, bool):
|
|
161
156
|
current_round = MAX_OUTER_REPAIR_ROUNDS
|
|
162
|
-
if stage_result
|
|
157
|
+
if stage_result in {"TEST_NEEDS_FIXES", "TEST_BLOCKED"}:
|
|
163
158
|
l4_state.update(
|
|
164
159
|
terminal_status="WORKFLOW_BLOCKED",
|
|
165
|
-
blocked_reason=
|
|
160
|
+
blocked_reason=(
|
|
161
|
+
"test_needs_fixes"
|
|
162
|
+
if stage_result == "TEST_NEEDS_FIXES"
|
|
163
|
+
else "test_blocked"
|
|
164
|
+
),
|
|
166
165
|
current_stage=None,
|
|
167
166
|
next_stage=None,
|
|
168
167
|
)
|
|
@@ -202,9 +201,6 @@ def _sync_cursor(data, l4_state):
|
|
|
202
201
|
l4_state["current_stage"] = active.get("skill") if active else None
|
|
203
202
|
l4_state["next_stage"] = active.get("skill") if active else None
|
|
204
203
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
204
|
def _checkpoint_project_root(checkpoint_path):
|
|
209
205
|
"""Resolve the project root from a conventional .prizmkit checkpoint path."""
|
|
210
206
|
path = Path(os.path.abspath(checkpoint_path))
|
|
@@ -213,42 +209,6 @@ def _checkpoint_project_root(checkpoint_path):
|
|
|
213
209
|
return str(parent.parent)
|
|
214
210
|
return str(path.parent)
|
|
215
211
|
|
|
216
|
-
def _discover_test_evidence_paths(checkpoint_path, data):
|
|
217
|
-
"""Discover the latest finalized test package from the artifact handoff pointer."""
|
|
218
|
-
project_root = Path(_checkpoint_project_root(checkpoint_path))
|
|
219
|
-
candidates = []
|
|
220
|
-
artifact_dir = data.get("artifact_dir")
|
|
221
|
-
if isinstance(artifact_dir, str) and artifact_dir:
|
|
222
|
-
candidates.append(project_root / artifact_dir)
|
|
223
|
-
for state_key in ("feature_state", "bugfix_state", "refactor_state"):
|
|
224
|
-
state = data.get(state_key)
|
|
225
|
-
if isinstance(state, dict) and isinstance(state.get("artifact_dir"), str):
|
|
226
|
-
candidates.append(project_root / state["artifact_dir"])
|
|
227
|
-
item_slug = data.get("item_slug")
|
|
228
|
-
if isinstance(item_slug, str) and item_slug:
|
|
229
|
-
candidates.append(project_root / ".prizmkit" / "specs" / item_slug)
|
|
230
|
-
candidates.append(project_root / ".prizmkit" / "bugfix" / item_slug)
|
|
231
|
-
candidates.append(project_root / ".prizmkit" / "refactor" / item_slug)
|
|
232
|
-
|
|
233
|
-
for artifact in candidates:
|
|
234
|
-
pointer = artifact / "test-report-path.txt"
|
|
235
|
-
try:
|
|
236
|
-
report = Path(pointer.read_text(encoding="utf-8").strip()).resolve()
|
|
237
|
-
except (OSError, ValueError):
|
|
238
|
-
continue
|
|
239
|
-
evidence_dir = report.parent
|
|
240
|
-
paths = {
|
|
241
|
-
"manifest": str(evidence_dir / "manifest.json"),
|
|
242
|
-
"verdict": str(evidence_dir / "verdict.json"),
|
|
243
|
-
"validation": str(evidence_dir / "validation.json"),
|
|
244
|
-
}
|
|
245
|
-
if all(Path(value).is_file() for value in paths.values()):
|
|
246
|
-
return {
|
|
247
|
-
key: str(Path(value).relative_to(project_root))
|
|
248
|
-
for key, value in paths.items()
|
|
249
|
-
}
|
|
250
|
-
return None
|
|
251
|
-
|
|
252
212
|
|
|
253
213
|
def _finalize_semantics(checkpoint_path, data, state_key):
|
|
254
214
|
"""Derive a deterministic terminal status after an atomic mutation."""
|
|
@@ -286,7 +246,7 @@ def update_checkpoint(
|
|
|
286
246
|
note=None,
|
|
287
247
|
semantic_update=None,
|
|
288
248
|
):
|
|
289
|
-
"""Update one step and its cohesive semantic
|
|
249
|
+
"""Update one step and its cohesive semantic pipeline state atomically."""
|
|
290
250
|
if new_status not in VALID_STATUSES:
|
|
291
251
|
return {
|
|
292
252
|
"ok": False,
|
|
@@ -323,25 +283,11 @@ def update_checkpoint(
|
|
|
323
283
|
return {"ok": False, "error": verdict_error}
|
|
324
284
|
|
|
325
285
|
semantic_update = _normalize_semantic_update(semantic_update)
|
|
326
|
-
if (
|
|
327
|
-
semantic_update.get("stage_result") == "TEST_BLOCKED"
|
|
328
|
-
and not semantic_update.get("authoritative_evidence_paths")
|
|
329
|
-
):
|
|
330
|
-
discovered = _discover_test_evidence_paths(checkpoint_path, data)
|
|
331
|
-
if discovered:
|
|
332
|
-
semantic_update["authoritative_evidence_paths"] = discovered
|
|
333
286
|
semantic_error = _validate_semantic_update(step, semantic_update)
|
|
334
287
|
if semantic_error:
|
|
335
288
|
return {"ok": False, "error": semantic_error}
|
|
336
289
|
|
|
337
290
|
stage_result = semantic_update.get("stage_result")
|
|
338
|
-
if step.get("skill") == "prizmkit-test" and stage_result in TEST_RESULTS:
|
|
339
|
-
evidence = semantic_update.get("authoritative_evidence_paths") or step.get("authoritative_evidence_paths")
|
|
340
|
-
if not isinstance(evidence, dict) or set(evidence) != {"manifest", "verdict", "validation"}:
|
|
341
|
-
return {
|
|
342
|
-
"ok": False,
|
|
343
|
-
"error": "Every terminal test verdict requires manifest, verdict, and validation evidence paths",
|
|
344
|
-
}
|
|
345
291
|
if new_status == "completed" and step.get("skill") == "prizmkit-code-review":
|
|
346
292
|
stage_result = stage_result or step.get("stage_result")
|
|
347
293
|
if stage_result != "REVIEW_PASS":
|
|
@@ -350,9 +296,6 @@ def update_checkpoint(
|
|
|
350
296
|
stage_result = stage_result or step.get("stage_result")
|
|
351
297
|
if stage_result != "TEST_PASS":
|
|
352
298
|
return {"ok": False, "error": "Test completion requires TEST_PASS"}
|
|
353
|
-
evidence = semantic_update.get("authoritative_evidence_paths") or step.get("authoritative_evidence_paths")
|
|
354
|
-
if not isinstance(evidence, dict) or set(evidence) != {"manifest", "verdict", "validation"}:
|
|
355
|
-
return {"ok": False, "error": "Test completion requires all authoritative evidence paths"}
|
|
356
299
|
|
|
357
300
|
old_status = step.get("status", "unknown")
|
|
358
301
|
step["status"] = new_status
|
|
@@ -360,20 +303,6 @@ def update_checkpoint(
|
|
|
360
303
|
step["note"] = note
|
|
361
304
|
if stage_result:
|
|
362
305
|
step["stage_result"] = stage_result
|
|
363
|
-
if semantic_update.get("authoritative_evidence_paths"):
|
|
364
|
-
step["authoritative_evidence_paths"] = semantic_update["authoritative_evidence_paths"]
|
|
365
|
-
if new_status == "completed" and step.get("skill") == "prizmkit-test":
|
|
366
|
-
candidate = validate_checkpoint_data(
|
|
367
|
-
data,
|
|
368
|
-
path=checkpoint_path,
|
|
369
|
-
exists=True,
|
|
370
|
-
project_root=_checkpoint_project_root(checkpoint_path),
|
|
371
|
-
)
|
|
372
|
-
if not candidate.valid or not candidate.semantic.evidence_valid:
|
|
373
|
-
return {
|
|
374
|
-
"ok": False,
|
|
375
|
-
"error": "Test completion requires validator-attested authoritative evidence",
|
|
376
|
-
}
|
|
377
306
|
|
|
378
307
|
workflow_type = str(data.get("workflow_type") or "")
|
|
379
308
|
state_key = semantic_state_key(workflow_type)
|
|
@@ -384,7 +313,6 @@ def update_checkpoint(
|
|
|
384
313
|
"stage_result",
|
|
385
314
|
"repair_scope",
|
|
386
315
|
"repair_round",
|
|
387
|
-
"authoritative_evidence_paths",
|
|
388
316
|
"blocked_reason",
|
|
389
317
|
"terminal_status",
|
|
390
318
|
):
|
|
@@ -394,8 +322,6 @@ def update_checkpoint(
|
|
|
394
322
|
l4_state["orchestrator"] = "prizmkit-l4"
|
|
395
323
|
if stage_result:
|
|
396
324
|
l4_state["stage_result"] = stage_result
|
|
397
|
-
if semantic_update.get("authoritative_evidence_paths"):
|
|
398
|
-
l4_state["authoritative_evidence_paths"] = semantic_update["authoritative_evidence_paths"]
|
|
399
325
|
_apply_repair_policy(l4_state, stage_result, semantic_update.get("repair_scope") or l4_state.get("repair_scope"))
|
|
400
326
|
_sync_cursor(data, l4_state)
|
|
401
327
|
_finalize_semantics(checkpoint_path, data, state_key)
|
|
@@ -439,9 +365,6 @@ def main():
|
|
|
439
365
|
parser.add_argument("--stage-result", choices=sorted(REVIEW_RESULTS | TEST_RESULTS), default=None)
|
|
440
366
|
parser.add_argument("--repair-scope", choices=sorted(VALID_REPAIR_SCOPES), default=None)
|
|
441
367
|
parser.add_argument("--repair-round", type=int, default=None)
|
|
442
|
-
parser.add_argument("--manifest-path", default=None)
|
|
443
|
-
parser.add_argument("--verdict-path", default=None)
|
|
444
|
-
parser.add_argument("--validation-path", default=None)
|
|
445
368
|
parser.add_argument("--blocked-reason", default=None)
|
|
446
369
|
parser.add_argument("--terminal-status", choices=sorted(VALID_TERMINAL_STATUSES), default=None)
|
|
447
370
|
|
|
@@ -450,11 +373,6 @@ def main():
|
|
|
450
373
|
"stage_result": args.stage_result,
|
|
451
374
|
"repair_scope": args.repair_scope,
|
|
452
375
|
"repair_round": args.repair_round,
|
|
453
|
-
"authoritative_evidence_paths": {
|
|
454
|
-
"manifest": args.manifest_path,
|
|
455
|
-
"verdict": args.verdict_path,
|
|
456
|
-
"validation": args.validation_path,
|
|
457
|
-
},
|
|
458
376
|
"blocked_reason": args.blocked_reason,
|
|
459
377
|
"terminal_status": args.terminal_status,
|
|
460
378
|
}
|
|
@@ -156,7 +156,7 @@ def parse_args():
|
|
|
156
156
|
parser.add_argument(
|
|
157
157
|
"--checkpoint-state",
|
|
158
158
|
default=None,
|
|
159
|
-
help="JSON semantic
|
|
159
|
+
help="JSON semantic pipeline checkpoint snapshot captured after the session.",
|
|
160
160
|
)
|
|
161
161
|
return parser.parse_args()
|
|
162
162
|
|
|
@@ -370,7 +370,6 @@ SEMANTIC_CHECKPOINT_FIELDS = (
|
|
|
370
370
|
"stage_result",
|
|
371
371
|
"repair_scope",
|
|
372
372
|
"repair_round",
|
|
373
|
-
"authoritative_evidence_paths",
|
|
374
373
|
"blocked_reason",
|
|
375
374
|
"terminal_status",
|
|
376
375
|
)
|
|
@@ -101,7 +101,7 @@ def parse_args():
|
|
|
101
101
|
parser.add_argument("--continuation-summary-path", default=None, help="Optional continuation summary artifact path.")
|
|
102
102
|
parser.add_argument("--no-progress-count", type=int, default=None, help="Consecutive context-overflow sessions without objective progress.")
|
|
103
103
|
parser.add_argument("--progress-fingerprint", default=None, help="JSON progress fingerprint captured after the session.")
|
|
104
|
-
parser.add_argument("--checkpoint-state", default=None, help="JSON semantic
|
|
104
|
+
parser.add_argument("--checkpoint-state", default=None, help="JSON semantic pipeline checkpoint snapshot captured after the session.")
|
|
105
105
|
return parser.parse_args()
|
|
106
106
|
|
|
107
107
|
|
|
@@ -260,7 +260,6 @@ SEMANTIC_CHECKPOINT_FIELDS = (
|
|
|
260
260
|
"stage_result",
|
|
261
261
|
"repair_scope",
|
|
262
262
|
"repair_round",
|
|
263
|
-
"authoritative_evidence_paths",
|
|
264
263
|
"blocked_reason",
|
|
265
264
|
"terminal_status",
|
|
266
265
|
)
|
|
@@ -24,7 +24,7 @@ Infer what needs to be done from the feature context above and follow the active
|
|
|
24
24
|
|
|
25
25
|
### Execution Steps
|
|
26
26
|
|
|
27
|
-
1. **Read context**: Read `.prizmkit/prizm-docs/root.prizm` and relevant
|
|
27
|
+
1. **Read context**: Read `.prizmkit/prizm-docs/root.prizm` and the relevant module indexes and detail docs to understand the codebase.
|
|
28
28
|
|
|
29
29
|
2. **Plan**: Run `/prizmkit-plan` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to produce `spec.md` and `plan.md`.
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ Infer what needs to be done from the feature context above and follow the active
|
|
|
32
32
|
|
|
33
33
|
4. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` and follow the skill's current review contract for review execution, repairs, verification, evidence, and handoff. Require the last `## Final Result`. `REVIEW_PASS` proceeds to test; `REVIEW_NEEDS_FIXES` increments the shared outer repair round and routes implement → code-review → test. Do not invoke another review entry point or add a second review path outside the skill contract.
|
|
34
34
|
|
|
35
|
-
5. **Test**: After review passes, run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
35
|
+
5. **Test**: After review passes, run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. Consume the sibling `test-report.md` and `test-result.json`; they must agree. `TEST_PASS` proceeds to retrospective. `TEST_NEEDS_FIXES` or `TEST_BLOCKED` preserves its known correction or blocker and stops truthfully. Do not require an evidence package, reinterpret a testing result as a runtime crash, or recreate the skill's bounded review and repair loops.
|
|
36
36
|
|
|
37
37
|
6. **Retrospective**: Run `/prizmkit-retrospective` to sync `.prizmkit/prizm-docs/` with code changes.
|
|
38
38
|
|
|
@@ -46,5 +46,5 @@ Infer what needs to be done from the feature context above and follow the active
|
|
|
46
46
|
- If a step fails after 3 attempts, write a status report and stop.
|
|
47
47
|
- **Never re-read unmodified files**: once you read a file into context, do NOT read it again unless it was modified by an Edit/Write after your last read — use `grep -n`/`sed -n` for specific lines. Before issuing a Read, ask: "Have I read this file before, and has it changed since?" If no — do NOT read it. Follow the active skill and runtime contracts when an execution unit is created; do not infer its permissions, continuation, or retry behavior from this fallback prompt.
|
|
48
48
|
- **Read offset safety**: if Read returns "shorter than offset"/"empty" — run `wc -l` then `sed -n`, do NOT retry same offset.
|
|
49
|
-
-
|
|
49
|
+
- Follow each skill's own bounded loops; do not add a second cross-skill test-fix loop in this fallback prompt.
|
|
50
50
|
- **Layered test**: debug with single-file tests, only run full suite as gate when single-file is green.
|
|
@@ -128,7 +128,7 @@ If `EXISTING_CODE` is non-empty: your spec/plan/tasks must reflect this existing
|
|
|
128
128
|
|
|
129
129
|
**Step A — Build Context Snapshot** (skip if `context-snapshot.md` already exists):
|
|
130
130
|
|
|
131
|
-
1. Read `.prizmkit/prizm-docs/root.prizm` and relevant
|
|
131
|
+
1. Read `.prizmkit/prizm-docs/root.prizm` and the relevant module indexes and detail docs
|
|
132
132
|
2. Detect source code directories from KEY_FILES and STRUCTURE sections in `root.prizm`; if root docs are unavailable, use the helper to list likely source files:
|
|
133
133
|
```bash
|
|
134
134
|
{{RUNTIME_HELPER_CMD}} artifact source-files . --json
|
|
@@ -138,7 +138,7 @@ If `EXISTING_CODE` is non-empty: your spec/plan/tasks must reflect this existing
|
|
|
138
138
|
4. Write `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
|
|
139
139
|
- **Section 1 — Feature Brief**: feature description (2-3 lines) + acceptance criteria (copy from above)
|
|
140
140
|
- **Section 2 — Verification Gates**: copy the gate checklist from the Task Contract above
|
|
141
|
-
- **Section 3 — Key TRAPS & RULES**: extract only relevant TRAPS/RULES from
|
|
141
|
+
- **Section 3 — Key TRAPS & RULES**: extract only relevant TRAPS/RULES from the loaded Prizm docs that apply to files in this scope. Do NOT copy complete documentation files.
|
|
142
142
|
- **Section 4 — File Manifest**: For each file relevant to this feature, list: file path, why it's needed (modify/reference/test), key interface signatures (function names + params + return types). Do NOT include full file content — agents read files on-demand. Format:
|
|
143
143
|
### Files to Modify
|
|
144
144
|
| File | Why Needed | Key Interfaces |
|
|
@@ -151,7 +151,7 @@ If `EXISTING_CODE` is non-empty: your spec/plan/tasks must reflect this existing
|
|
|
151
151
|
| `<source-dir>/security/permission-guard.js` | Permission check integration | `checkCommandPermission(userId, cmd)` |
|
|
152
152
|
|
|
153
153
|
### Known TRAPS (from .prizmkit/prizm-docs/)
|
|
154
|
-
- <trap entries extracted from
|
|
154
|
+
- <trap entries extracted from the loaded Prizm docs>
|
|
155
155
|
4. Confirm: `{{RUNTIME_HELPER_CMD}} artifact exists .prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`
|
|
156
156
|
|
|
157
157
|
**After Step A**: Use context-snapshot.md Section 4 File Manifest to guide targeted file reads. Do NOT scan directories or read unrelated files.
|
|
@@ -252,26 +252,15 @@ Only `REVIEW_PASS` can proceed to the structured Feature test gate. `REVIEW_INCO
|
|
|
252
252
|
|
|
253
253
|
### Scoped Feature Test Gate — PrizmKit Test
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
{{RUNTIME_HELPER_CMD}} artifact ensure-dir .prizmkit/specs/{{FEATURE_SLUG}}
|
|
259
|
-
{{RUNTIME_HELPER_CMD}} artifact touch .prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started
|
|
260
|
-
```
|
|
255
|
+
Invoke the Feature test gate:
|
|
261
256
|
|
|
262
257
|
```text
|
|
263
258
|
/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/
|
|
264
259
|
```
|
|
265
260
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Repair routes:
|
|
269
|
-
- `TEST_FAIL` with `repair_scope=test-infrastructure` → implement → test, without speculative production edits.
|
|
270
|
-
- `TEST_FAIL` with production/runtime/schema/dependency/public-interface scope → implement → code-review → test.
|
|
271
|
-
- Unknown unsafe scope → `WORKFLOW_BLOCKED`; do not guess a production edit.
|
|
272
|
-
- `TEST_BLOCKED` → preserve evidence/artifacts, perform bounded environment recovery, then resume from test or finish terminal `WORKFLOW_BLOCKED`; never edit production speculatively.
|
|
261
|
+
Consume `.prizmkit/specs/{{FEATURE_SLUG}}/test-report.md` and `test-result.json`. They must agree. `TEST_PASS` completes the gate; `TEST_NEEDS_FIXES` preserves a known correction or delta-review requirement and stops truthfully; `TEST_BLOCKED` preserves the blocker and becomes `WORKFLOW_BLOCKED`. Do not require an evidence package, manifest, hashes, attestation, or test-internal checkpoint, and do not reinterpret a testing result as an AI CLI crash.
|
|
273
262
|
|
|
274
|
-
Record `stage`, `status`, `stage_result`, `repair_scope`, `repair_round`,
|
|
263
|
+
Record only caller-owned `stage`, `status`, `stage_result`, `repair_scope`, `repair_round`, `next_stage`, and `resume_from` in recovery metadata. Keep testing reports/results separate from `workflow-checkpoint.json`. The skill owns its internal ten-round Main-Agent review, five-response optional independent review, and three-round execution-failure repair budgets.
|
|
275
264
|
|
|
276
265
|
{{IF_BROWSER_INTERACTION}}
|
|
277
266
|
### Phase 5.5: Browser Verification — MANDATORY
|
|
@@ -448,7 +437,7 @@ git log --oneline
|
|
|
448
437
|
**6b.** Run `/prizmkit-retrospective` (**before commit**, maintains `.prizmkit/prizm-docs/` architecture index):
|
|
449
438
|
- **Structural sync**: update KEY_FILES/INTERFACES/DEPENDENCIES/file counts for changed modules
|
|
450
439
|
- **Architecture knowledge** (feature sessions only): extract TRAPS, RULES, DECISIONS from completed work into `.prizmkit/prizm-docs/`
|
|
451
|
-
- **
|
|
440
|
+
- **Detail-doc coverage check**: For any module/sub-module with source files created or significantly modified in this session but no detail `.prizm` doc — evaluate whether one is warranted and create it when needed. The current session has the best context for accurate KEY_FILES, TRAPS, and DECISIONS.
|
|
452
441
|
- Stage doc changes: `git add .prizmkit/prizm-docs/`
|
|
453
442
|
⚠️ Do NOT commit here. Only stage.
|
|
454
443
|
|