prizmkit 1.1.154 → 1.1.155
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 +11 -1
- package/bundled/skills/prizmkit-retrospective/SKILL.md +63 -77
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -3
- package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +17 -23
- 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/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
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate app-planner Rules Configuration resources as one coherent contract."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import re
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
LAYERS = ("frontend", "backend", "database", "mobile")
|
|
13
|
+
SCHEMA_VERSION = "app-planner-question-manifest-v2"
|
|
14
|
+
REQUIRED_RENDER_CONTRACT = {
|
|
15
|
+
"fixed_rules_policy": "invariants_only",
|
|
16
|
+
"selected_decision_precedence": True,
|
|
17
|
+
"quick_mode_requires_explicit_authorization": True,
|
|
18
|
+
"unmapped_option_policy": "semantic_fallback",
|
|
19
|
+
"not_applicable_policy": "explicit_statement",
|
|
20
|
+
"conflict_policy": "fail_generation",
|
|
21
|
+
}
|
|
22
|
+
QUESTION_HEADING_RE = re.compile(r"^###\s+(Q[0-9]+[a-z]?)\.", re.MULTILINE)
|
|
23
|
+
PLACEHOLDER_RE = re.compile(r"\{\{\s*([A-Za-z0-9_]+)\s*\}\}")
|
|
24
|
+
CONDITION_RE = re.compile(
|
|
25
|
+
r"^(Q[0-9]+[a-z]?)\s*(?:==|!=)\s*[A-Z][A-Z0-9_-]*$"
|
|
26
|
+
r"|^(Q[0-9]+[a-z]?)\s+in\s+\[[A-Z][A-Z0-9_-]*(?:,\s*[A-Z][A-Z0-9_-]*)*\]$"
|
|
27
|
+
)
|
|
28
|
+
CONDITION_FIELDS = (
|
|
29
|
+
"required_if",
|
|
30
|
+
"auto_derived_when",
|
|
31
|
+
"dual_native_repeat_when",
|
|
32
|
+
"note_open_ended_when",
|
|
33
|
+
)
|
|
34
|
+
FIXED_RULE_FORBIDDEN_PATTERNS = (
|
|
35
|
+
"all user-facing text must use i18n keys",
|
|
36
|
+
"only add dependencies after explicit permission",
|
|
37
|
+
"all apis must follow rest conventions",
|
|
38
|
+
"jwt is the default authentication mechanism",
|
|
39
|
+
"every module must have unit tests",
|
|
40
|
+
"all deep links must use universal links",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _load_json(path: Path) -> dict[str, Any]:
|
|
45
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
46
|
+
if not isinstance(data, dict):
|
|
47
|
+
raise ValueError("root must be a JSON object")
|
|
48
|
+
return data
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _as_string_list(value: object, label: str, errors: list[str]) -> list[str]:
|
|
52
|
+
if not isinstance(value, list) or not all(isinstance(item, str) for item in value):
|
|
53
|
+
errors.append(f"{label} must be an array of strings")
|
|
54
|
+
return []
|
|
55
|
+
return list(value)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _validate_layer(rules_root: Path, layer: str, errors: list[str]) -> None:
|
|
59
|
+
layer_root = rules_root / layer
|
|
60
|
+
required_files = {
|
|
61
|
+
"manifest": layer_root / "question-manifest.json",
|
|
62
|
+
"bank": layer_root / "question-bank.md",
|
|
63
|
+
"fixed": layer_root / "fixed-rules.md",
|
|
64
|
+
"derivation": layer_root / "derivation-rules.md",
|
|
65
|
+
"template": layer_root / "template.md",
|
|
66
|
+
}
|
|
67
|
+
missing = [name for name, path in required_files.items() if not path.is_file()]
|
|
68
|
+
if missing:
|
|
69
|
+
errors.append(f"{layer}: missing resources: {', '.join(missing)}")
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
manifest = _load_json(required_files["manifest"])
|
|
74
|
+
except (OSError, json.JSONDecodeError, ValueError) as exc:
|
|
75
|
+
errors.append(f"{layer}: invalid question-manifest.json: {exc}")
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
if manifest.get("schema_version") != SCHEMA_VERSION:
|
|
79
|
+
errors.append(
|
|
80
|
+
f"{layer}: schema_version must be {SCHEMA_VERSION!r}, "
|
|
81
|
+
f"got {manifest.get('schema_version')!r}"
|
|
82
|
+
)
|
|
83
|
+
if manifest.get("layer") != layer:
|
|
84
|
+
errors.append(f"{layer}: manifest layer must equal directory name")
|
|
85
|
+
|
|
86
|
+
render_contract = manifest.get("render_contract")
|
|
87
|
+
if not isinstance(render_contract, dict):
|
|
88
|
+
errors.append(f"{layer}: render_contract must be an object")
|
|
89
|
+
render_contract = {}
|
|
90
|
+
for key, expected in REQUIRED_RENDER_CONTRACT.items():
|
|
91
|
+
if render_contract.get(key) != expected:
|
|
92
|
+
errors.append(
|
|
93
|
+
f"{layer}: render_contract.{key} must be {expected!r}, "
|
|
94
|
+
f"got {render_contract.get(key)!r}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
questions = manifest.get("questions")
|
|
98
|
+
if not isinstance(questions, list) or not all(isinstance(item, dict) for item in questions):
|
|
99
|
+
errors.append(f"{layer}: questions must be an array of objects")
|
|
100
|
+
questions = []
|
|
101
|
+
question_ids = [str(item.get("id") or "") for item in questions]
|
|
102
|
+
if any(not question_id for question_id in question_ids):
|
|
103
|
+
errors.append(f"{layer}: every question must have a non-empty id")
|
|
104
|
+
if len(question_ids) != len(set(question_ids)):
|
|
105
|
+
errors.append(f"{layer}: duplicate question ids in manifest")
|
|
106
|
+
if manifest.get("total_questions") != len(question_ids):
|
|
107
|
+
errors.append(
|
|
108
|
+
f"{layer}: total_questions={manifest.get('total_questions')!r} "
|
|
109
|
+
f"does not match {len(question_ids)} manifest questions"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
groups = manifest.get("groups")
|
|
113
|
+
if not isinstance(groups, list) or not all(isinstance(item, dict) for item in groups):
|
|
114
|
+
errors.append(f"{layer}: groups must be an array of objects")
|
|
115
|
+
groups = []
|
|
116
|
+
group_ids = {str(item.get("id") or "") for item in groups}
|
|
117
|
+
question_positions = {question_id: index for index, question_id in enumerate(question_ids)}
|
|
118
|
+
for index, question in enumerate(questions):
|
|
119
|
+
question_id = str(question.get("id") or "")
|
|
120
|
+
if question.get("group") not in group_ids:
|
|
121
|
+
errors.append(
|
|
122
|
+
f"{layer}: question {question_id!r} references unknown group "
|
|
123
|
+
f"{question.get('group')!r}"
|
|
124
|
+
)
|
|
125
|
+
varying_parent = question.get("options_vary_by")
|
|
126
|
+
if varying_parent is not None:
|
|
127
|
+
if not isinstance(varying_parent, str) or varying_parent not in question_positions:
|
|
128
|
+
errors.append(
|
|
129
|
+
f"{layer}: question {question_id} options_vary_by references "
|
|
130
|
+
f"unknown question {varying_parent!r}"
|
|
131
|
+
)
|
|
132
|
+
elif question_positions[varying_parent] >= index:
|
|
133
|
+
errors.append(
|
|
134
|
+
f"{layer}: question {question_id} options_vary_by must reference "
|
|
135
|
+
"an earlier question"
|
|
136
|
+
)
|
|
137
|
+
for field in CONDITION_FIELDS:
|
|
138
|
+
condition = question.get(field)
|
|
139
|
+
if condition is None:
|
|
140
|
+
continue
|
|
141
|
+
if not isinstance(condition, str):
|
|
142
|
+
errors.append(f"{layer}: question {question_id} {field} must be a string")
|
|
143
|
+
continue
|
|
144
|
+
match = CONDITION_RE.fullmatch(condition)
|
|
145
|
+
if match is None:
|
|
146
|
+
errors.append(
|
|
147
|
+
f"{layer}: question {question_id} {field} has invalid option-ID "
|
|
148
|
+
f"condition syntax: {condition!r}"
|
|
149
|
+
)
|
|
150
|
+
continue
|
|
151
|
+
referenced_question = match.group(1) or match.group(2)
|
|
152
|
+
if referenced_question not in question_positions:
|
|
153
|
+
errors.append(
|
|
154
|
+
f"{layer}: question {question_id} {field} references unknown "
|
|
155
|
+
f"question {referenced_question}"
|
|
156
|
+
)
|
|
157
|
+
elif question_positions[referenced_question] >= index:
|
|
158
|
+
errors.append(
|
|
159
|
+
f"{layer}: question {question_id} {field} must reference an earlier question"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
bank_text = required_files["bank"].read_text(encoding="utf-8")
|
|
163
|
+
bank_question_ids = QUESTION_HEADING_RE.findall(bank_text)
|
|
164
|
+
if question_ids != bank_question_ids:
|
|
165
|
+
errors.append(
|
|
166
|
+
f"{layer}: question bank/manifest drift; manifest={question_ids}, "
|
|
167
|
+
f"question_bank={bank_question_ids}"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
fallback_questions = _as_string_list(
|
|
171
|
+
render_contract.get("semantic_fallback_questions"),
|
|
172
|
+
f"{layer}: render_contract.semantic_fallback_questions",
|
|
173
|
+
errors,
|
|
174
|
+
)
|
|
175
|
+
if fallback_questions != question_ids:
|
|
176
|
+
errors.append(
|
|
177
|
+
f"{layer}: semantic_fallback_questions must match manifest question order; "
|
|
178
|
+
f"got {fallback_questions}"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
placeholders = manifest.get("template_placeholders")
|
|
182
|
+
if not isinstance(placeholders, dict):
|
|
183
|
+
errors.append(f"{layer}: template_placeholders must be an object")
|
|
184
|
+
placeholders = {}
|
|
185
|
+
declared: set[str] = set()
|
|
186
|
+
for category in ("from_questions", "from_fixed_rules", "auto_generated", "metadata"):
|
|
187
|
+
values = _as_string_list(
|
|
188
|
+
placeholders.get(category),
|
|
189
|
+
f"{layer}: template_placeholders.{category}",
|
|
190
|
+
errors,
|
|
191
|
+
)
|
|
192
|
+
overlap = declared.intersection(values)
|
|
193
|
+
if overlap:
|
|
194
|
+
errors.append(
|
|
195
|
+
f"{layer}: placeholders declared in multiple categories: {sorted(overlap)}"
|
|
196
|
+
)
|
|
197
|
+
declared.update(values)
|
|
198
|
+
|
|
199
|
+
template_text = required_files["template"].read_text(encoding="utf-8")
|
|
200
|
+
actual = set(PLACEHOLDER_RE.findall(template_text))
|
|
201
|
+
undeclared = sorted(actual - declared)
|
|
202
|
+
unused = sorted(declared - actual)
|
|
203
|
+
if undeclared:
|
|
204
|
+
errors.append(f"{layer}: template has undeclared placeholders: {undeclared}")
|
|
205
|
+
if unused:
|
|
206
|
+
errors.append(f"{layer}: manifest declares unused placeholders: {unused}")
|
|
207
|
+
if "Generated by app-planner Rules Configuration" not in template_text:
|
|
208
|
+
errors.append(f"{layer}: template must identify app-planner Rules Configuration as owner")
|
|
209
|
+
if ".claude/skills/" in template_text:
|
|
210
|
+
errors.append(f"{layer}: template contains a platform-specific source pointer")
|
|
211
|
+
if re.search(r"generated by the `(?:frontend|backend|database|mobile)-rules` skill", template_text, re.I):
|
|
212
|
+
errors.append(f"{layer}: template references a retired independent layer-rules skill")
|
|
213
|
+
|
|
214
|
+
fixed_text = required_files["fixed"].read_text(encoding="utf-8")
|
|
215
|
+
if "POLICY_CLASS: invariant" not in fixed_text:
|
|
216
|
+
errors.append(f"{layer}: fixed-rules.md must declare POLICY_CLASS: invariant")
|
|
217
|
+
if "Selected-decision boundary" not in fixed_text:
|
|
218
|
+
errors.append(f"{layer}: fixed-rules.md must state the selected-decision boundary")
|
|
219
|
+
normalized_fixed_text = " ".join(fixed_text.lower().split())
|
|
220
|
+
for forbidden_pattern in FIXED_RULE_FORBIDDEN_PATTERNS:
|
|
221
|
+
if forbidden_pattern in normalized_fixed_text:
|
|
222
|
+
errors.append(
|
|
223
|
+
f"{layer}: fixed-rules.md contains decision-owned policy: "
|
|
224
|
+
f"{forbidden_pattern!r}"
|
|
225
|
+
)
|
|
226
|
+
for placeholder in placeholders.get("from_fixed_rules", []):
|
|
227
|
+
if f"{{{{ {placeholder} }}}}" not in fixed_text:
|
|
228
|
+
errors.append(
|
|
229
|
+
f"{layer}: fixed-rules.md has no injection mapping for {{{{ {placeholder} }}}}"
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
derivation_text = required_files["derivation"].read_text(encoding="utf-8")
|
|
233
|
+
if "SEMANTIC_FALLBACK_POLICY" not in derivation_text:
|
|
234
|
+
errors.append(f"{layer}: derivation-rules.md must define SEMANTIC_FALLBACK_POLICY")
|
|
235
|
+
|
|
236
|
+
multi_profile = manifest.get("multi_profile_contract")
|
|
237
|
+
if layer == "mobile":
|
|
238
|
+
expected_multi_profile = {
|
|
239
|
+
"when": "Q1 == E",
|
|
240
|
+
"dimensions": ["Q4", "Q6", "Q7", "Q8", "Q13", "Q14"],
|
|
241
|
+
"profiles": ["ios", "android"],
|
|
242
|
+
"output_placeholder": "platform_profiles",
|
|
243
|
+
}
|
|
244
|
+
if multi_profile != expected_multi_profile:
|
|
245
|
+
errors.append("mobile: multi_profile_contract does not match the dual-native contract")
|
|
246
|
+
if "platform_profiles" not in placeholders.get("auto_generated", []):
|
|
247
|
+
errors.append("mobile: platform_profiles must be an auto-generated placeholder")
|
|
248
|
+
elif multi_profile is not None:
|
|
249
|
+
errors.append(f"{layer}: multi_profile_contract is only valid for mobile")
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def validate_rules_root(rules_root: Path) -> dict[str, object]:
|
|
253
|
+
errors: list[str] = []
|
|
254
|
+
if not rules_root.is_dir():
|
|
255
|
+
errors.append(f"rules root does not exist: {rules_root}")
|
|
256
|
+
else:
|
|
257
|
+
actual_layers = sorted(path.name for path in rules_root.iterdir() if path.is_dir())
|
|
258
|
+
unexpected = sorted(set(actual_layers) - set(LAYERS))
|
|
259
|
+
missing = sorted(set(LAYERS) - set(actual_layers))
|
|
260
|
+
if unexpected:
|
|
261
|
+
errors.append(f"unexpected rules layers: {unexpected}")
|
|
262
|
+
if missing:
|
|
263
|
+
errors.append(f"missing rules layers: {missing}")
|
|
264
|
+
for layer in LAYERS:
|
|
265
|
+
if (rules_root / layer).is_dir():
|
|
266
|
+
_validate_layer(rules_root, layer, errors)
|
|
267
|
+
return {
|
|
268
|
+
"valid": not errors,
|
|
269
|
+
"layers": list(LAYERS),
|
|
270
|
+
"errors": errors,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def main() -> int:
|
|
275
|
+
parser = argparse.ArgumentParser(
|
|
276
|
+
description="Validate app-planner Rules Configuration manifests and rendering resources."
|
|
277
|
+
)
|
|
278
|
+
parser.add_argument(
|
|
279
|
+
"--rules-root",
|
|
280
|
+
type=Path,
|
|
281
|
+
default=Path(__file__).resolve().parent.parent / "references" / "rules",
|
|
282
|
+
help="Path containing frontend/backend/database/mobile rules resources.",
|
|
283
|
+
)
|
|
284
|
+
args = parser.parse_args()
|
|
285
|
+
report = validate_rules_root(args.rules_root.expanduser().resolve())
|
|
286
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
287
|
+
return 0 if report["valid"] else 1
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
if __name__ == "__main__":
|
|
291
|
+
raise SystemExit(main())
|
|
@@ -57,7 +57,7 @@ prizmkit-plan
|
|
|
57
57
|
→ prizmkit-committer
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
For a one-entry experience, invoke `/prizmkit-workflow`; it owns ordering, state, repair routing, and stage invocation without replacing stage responsibilities. Atomic Skills receive explicit stage-local input, return stage-local results, and never read or write the coordinator's state. External injected Prompts may provide the same orchestration around atomic Skills.
|
|
61
61
|
|
|
62
62
|
All six stages are required for a formal requirement. A stage may choose a verification depth appropriate to the change, but it may not be silently skipped.
|
|
63
63
|
|
|
@@ -67,14 +67,14 @@ Typos, pure formatting, small documentation edits, and other explicitly low-risk
|
|
|
67
67
|
|
|
68
68
|
### Stage Responsibilities
|
|
69
69
|
|
|
70
|
-
| Stage | Responsibility |
|
|
70
|
+
| Stage | Responsibility | Stage-local success |
|
|
71
71
|
|---|---|---|
|
|
72
|
-
| `prizmkit-plan` | Clarify the requirement and create/review `spec.md` and `plan.md`. | `
|
|
73
|
-
| `prizmkit-implement` | Execute
|
|
74
|
-
| `prizmkit-code-review` |
|
|
75
|
-
| `prizmkit-test` |
|
|
76
|
-
| `prizmkit-retrospective` | Synchronize durable
|
|
77
|
-
| `prizmkit-committer` |
|
|
72
|
+
| `prizmkit-plan` | Clarify the requirement and create/review `spec.md` and `plan.md`. | `PLAN_READY` |
|
|
73
|
+
| `prizmkit-implement` | Execute supplied plan tasks and record completion. | `IMPLEMENTED` |
|
|
74
|
+
| `prizmkit-code-review` | Review, repair, verify, and converge on the supplied change. | `PASS` |
|
|
75
|
+
| `prizmkit-test` | Test the supplied change with a consistent report/result pair. | `TEST_PASS` |
|
|
76
|
+
| `prizmkit-retrospective` | Synchronize durable documentation or record no change. | `RETRO_COMPLETE` |
|
|
77
|
+
| `prizmkit-committer` | Create a confirmed interactive commit or prepare an exact Runtime request. | `COMMITTED` or `COMMIT_REQUEST_READY` |
|
|
78
78
|
|
|
79
79
|
### `prizmkit-workflow`
|
|
80
80
|
|
|
@@ -86,9 +86,8 @@ Use for a one-entry formal requirement workflow. It coordinates all six lifecycl
|
|
|
86
86
|
|
|
87
87
|
Initialization is a soft prerequisite, not a hard dependency:
|
|
88
88
|
|
|
89
|
-
- If project initialization is missing, `/prizmkit-
|
|
90
|
-
-
|
|
91
|
-
- Planning then reads the source tree, README, manifests, and available project rules as fallback context.
|
|
89
|
+
- If project initialization is missing, the user may still invoke `/prizmkit-init` separately or continue without it.
|
|
90
|
+
- Planning reads the source tree, README, manifests, and available project rules as fallback context.
|
|
92
91
|
- Later documentation synchronization reports when the Prizm documentation system is not initialized instead of pretending that synchronization completed.
|
|
93
92
|
|
|
94
93
|
## Independent Skills
|
|
@@ -110,7 +109,7 @@ REVIEW_NEEDS_FIXES
|
|
|
110
109
|
|
|
111
110
|
TEST_NEEDS_FIXES
|
|
112
111
|
→ preserve test-report.md and test-result.json
|
|
113
|
-
→ stop with the known correction
|
|
112
|
+
→ stop with the known correction
|
|
114
113
|
→ caller owns any later review/retest route
|
|
115
114
|
|
|
116
115
|
TEST_BLOCKED
|
|
@@ -122,7 +121,7 @@ Automatic outer repair is limited to three rounds. The workflow stops with a res
|
|
|
122
121
|
|
|
123
122
|
## Commit and Deployment Boundary
|
|
124
123
|
|
|
125
|
-
`prizmkit-committer`
|
|
124
|
+
The active coordinator validates all required evidence before invoking `prizmkit-committer` with exact `evidence_paths` and any caller-state `excluded_paths`. Interactive use confirms and creates a local commit. Preparation use returns `COMMIT_REQUEST_READY` without Git mutation; the injected Prompt records its pending state and Python Runtime executes the request.
|
|
126
125
|
|
|
127
126
|
Pushing to a remote is a separate explicit action. Deployment is always a separate invocation of `/prizmkit-deploy`.
|
|
128
127
|
|
|
@@ -131,10 +130,10 @@ Pushing to a remote is a separate explicit action. Deployment is always a separa
|
|
|
131
130
|
An active requirement may use:
|
|
132
131
|
|
|
133
132
|
```text
|
|
134
|
-
.prizmkit/state/workflows/<requirement-
|
|
133
|
+
.prizmkit/state/workflows/<requirement-identity>.json
|
|
135
134
|
```
|
|
136
135
|
|
|
137
|
-
This
|
|
136
|
+
`<requirement-identity>` is the validated exact basename of the active artifact directory. An existing state file that records a different artifact directory is a blocking collision and is never silently overwritten or suffixed. This coordinator-owned state records current stage, terminal status, repair scope, repair round, and resume entry. Atomic Skills do not read or write it. The target project controls whether the file is committed, ignored, or shared.
|
|
138
137
|
|
|
139
138
|
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.
|
|
140
139
|
|
|
@@ -152,19 +151,19 @@ Then:
|
|
|
152
151
|
1. Optionally run /prizmkit-init when entering a project for the first time.
|
|
153
152
|
2. Start a formal requirement with /prizmkit-plan.
|
|
154
153
|
3. Continue through implement → code-review → test → retrospective → committer.
|
|
155
|
-
4.
|
|
154
|
+
4. For interactive use, confirm the local commit when `/prizmkit-committer operation=interactive-commit` presents it; pipeline runtimes use preparation mode and execute Git themselves.
|
|
156
155
|
5. Invoke /prizmkit-deploy separately when deployment or operations work is needed.
|
|
157
156
|
```
|
|
158
157
|
|
|
159
158
|
## Scope Boundary
|
|
160
159
|
|
|
161
|
-
This toolkit is self-contained
|
|
160
|
+
This toolkit is self-contained. External coordinators integrate through atomic stage inputs, stage-owned artifacts, and domain results; coordinator state and routing remain outside atomic Skill contracts.
|
|
162
161
|
|
|
163
162
|
The toolkit does not promise universal automatic handoff, universal deployment automation, automatic remote push, or access beyond the host platform's permissions and environment.
|
|
164
163
|
|
|
165
164
|
If the user says only "ship it", ask whether they mean:
|
|
166
165
|
|
|
167
|
-
1.
|
|
166
|
+
1. Use `/prizmkit-committer operation=interactive-commit` for a user-confirmed local commit, or preparation mode when a Python pipeline runtime owns Git execution.
|
|
168
167
|
2. Deploy or operate the project with `/prizmkit-deploy`.
|
|
169
168
|
|
|
170
169
|
Do not route an ambiguous "ship it" directly to either action.
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
## Location and Identity
|
|
6
6
|
|
|
7
|
+
The state filename uses the validated exact basename of `artifact_dir` without a second slug transformation:
|
|
8
|
+
|
|
7
9
|
```text
|
|
8
|
-
.prizmkit/state/workflows/<requirement-
|
|
10
|
+
.prizmkit/state/workflows/<requirement-identity>.json
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
The active `artifact_dir` is preserved exactly across every stage:
|
|
13
|
+
An existing state path whose recorded `artifact_dir` differs from the active artifact is a blocking collision; never overwrite, merge, or suffix it automatically. The active `artifact_dir` is preserved exactly across every stage:
|
|
12
14
|
|
|
13
15
|
```text
|
|
14
16
|
.prizmkit/specs/<requirement-slug>/
|
|
@@ -31,7 +33,7 @@ The state file is an index, not the authority for stage completion:
|
|
|
31
33
|
| Terminal testing result | `{artifact_dir}/test-result.json` |
|
|
32
34
|
| Retrospective completion | `{artifact_dir}/retrospective-result.json` |
|
|
33
35
|
| Durable architecture knowledge | `.prizmkit/prizm-docs/` |
|
|
34
|
-
| Local commit | Git history and
|
|
36
|
+
| Local commit | Git history and runtime- or user-verified commit identity |
|
|
35
37
|
| Current stage, orchestrator, and resume entry | Workflow state |
|
|
36
38
|
| External orchestration progress | External host checkpoint |
|
|
37
39
|
|
|
@@ -64,7 +66,7 @@ Every consumer compares workflow state with the skill-owned artifacts and curren
|
|
|
64
66
|
| `orchestrator` | Semantic coordinator identifier, or null for direct stage use. |
|
|
65
67
|
| `stage` | Stage that most recently wrote state. |
|
|
66
68
|
| `status` | Lifecycle status: `pending`, `in_progress`, `completed`, `failed`, or `skipped`. |
|
|
67
|
-
| `stage_result` |
|
|
69
|
+
| `stage_result` | Coordinator-recorded lifecycle result mapped from a validated atomic result and its required artifacts, such as `PLAN_READY`, `IMPLEMENTED`, `REVIEW_PASS`, `REVIEW_NEEDS_FIXES`, `TEST_*`, `RETRO_COMPLETE`, or `COMMITTED`. |
|
|
68
70
|
| `completed_stages` | Ordered stages completed for this requirement. |
|
|
69
71
|
| `repair_scope` | Optional caller-owned routing scope. The test skill reports high-risk repairs through `test-result.json` instead of scheduling another stage. |
|
|
70
72
|
| `repair_round` | Optional outer cross-stage repair round, from 0 through 3. It is not a test-internal repair counter. |
|
|
@@ -97,10 +99,10 @@ review-report NEEDS_FIXES → status=failed, stage_result=REVIEW_NEED
|
|
|
97
99
|
test-result TEST_PASS → status=completed, stage_result=TEST_PASS
|
|
98
100
|
test-result TEST_NEEDS_FIXES → status=failed, stage_result=TEST_NEEDS_FIXES
|
|
99
101
|
test-result TEST_BLOCKED → status=failed, stage_result=TEST_BLOCKED
|
|
100
|
-
retrospective DOCS_UPDATED
|
|
101
|
-
retrospective NO_DOC_CHANGE
|
|
102
|
-
retrospective
|
|
103
|
-
commit
|
|
102
|
+
retrospective outcome=RETRO_COMPLETE, result=DOCS_UPDATED → status=completed, stage_result=RETRO_COMPLETE
|
|
103
|
+
retrospective outcome=RETRO_COMPLETE, result=NO_DOC_CHANGE → status=completed, stage_result=RETRO_COMPLETE
|
|
104
|
+
retrospective outcome=RETRO_BLOCKED → status=failed, stage_result=RETRO_BLOCKED
|
|
105
|
+
runtime commit preparation → status=in_progress, stage_result=COMMIT_PENDING
|
|
104
106
|
local commit confirmed → status=completed, stage_result=COMMITTED
|
|
105
107
|
commit blocked → status=failed, stage_result=COMMIT_BLOCKED
|
|
106
108
|
```
|
|
@@ -115,8 +117,8 @@ commit blocked → status=failed, stage_result=COMMIT_BLOC
|
|
|
115
117
|
|
|
116
118
|
```text
|
|
117
119
|
TEST_NEEDS_FIXES
|
|
118
|
-
→ known correction
|
|
119
|
-
→ caller decides whether and how to arrange another
|
|
120
|
+
→ a known correction remains
|
|
121
|
+
→ caller decides whether and how to arrange another invocation
|
|
120
122
|
|
|
121
123
|
TEST_BLOCKED
|
|
122
124
|
→ truth, input, safe environment, or reliable execution prevents a verdict
|
|
@@ -132,30 +134,32 @@ Any outer repair or continuation policy is independently owned by the caller and
|
|
|
132
134
|
|
|
133
135
|
1. An atomic stage performs only its own stage, writes its truthful result and artifact paths, and returns control.
|
|
134
136
|
2. When `orchestrator` is non-null, only that orchestrator invokes the next skill.
|
|
135
|
-
3. Direct
|
|
137
|
+
3. Direct atomic use returns only its local result and artifacts; it does not report or select another invocation.
|
|
136
138
|
4. Every handoff preserves the same `artifact_dir`.
|
|
137
139
|
5. External automation invokes atomic stages directly and does not nest the composite workflow.
|
|
138
140
|
6. Workflow state never replaces or absorbs an external host checkpoint.
|
|
139
141
|
|
|
140
|
-
## Commit
|
|
142
|
+
## Commit Execution Ownership
|
|
141
143
|
|
|
142
144
|
Interactive execution:
|
|
143
145
|
|
|
144
146
|
```text
|
|
145
147
|
committer previews intended files and message
|
|
146
148
|
→ waits for explicit current-user confirmation
|
|
147
|
-
→ creates the local commit
|
|
149
|
+
→ stages, creates, and verifies the local commit
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
Pipeline execution:
|
|
151
153
|
|
|
152
154
|
```text
|
|
153
|
-
|
|
154
|
-
→ committer
|
|
155
|
+
external coordinator validates its required gates and supplies exact readiness evidence
|
|
156
|
+
→ committer validates only that evidence and writes an exact runtime-commit-request.json
|
|
157
|
+
→ external coordinator maps COMMIT_REQUEST_READY to its checkpoint's in_progress/COMMIT_PENDING state
|
|
158
|
+
→ Python runtime validates the request, commits, verifies Git, and writes checkpoint completed/COMMITTED
|
|
155
159
|
→ remote publication remains separate
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
The preparation request is data for runtime validation, not prompt-level authorization. The committer must not stage, commit, or predeclare COMMITTED in pipeline preparation mode.
|
|
159
163
|
|
|
160
164
|
## Recovery
|
|
161
165
|
|
|
@@ -171,4 +175,4 @@ When state is missing, stale, or inconsistent:
|
|
|
171
175
|
8. Reconstruct the latest safe predecessor and report the reconstruction.
|
|
172
176
|
9. Continue only from the first incomplete or invalid stage.
|
|
173
177
|
|
|
174
|
-
Stale state never bypasses review, testing, retrospective, commit
|
|
178
|
+
Stale state never bypasses review, testing, retrospective, commit preparation/execution, or external checkpoint enforcement.
|
|
@@ -1,49 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "prizmkit-code-review"
|
|
3
|
-
description: "Review
|
|
3
|
+
description: "Review one supplied complete change with a bounded Main-Agent review/repair loop and optional capability-gated independent correctness review. Produces review-report.md and returns PASS or NEEDS_FIXES. (project)"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PrizmKit Code Review
|
|
7
7
|
|
|
8
|
-
`/prizmkit-code-review`
|
|
8
|
+
`/prizmkit-code-review` reviews one caller-supplied complete change. The current Main Agent owns the complete baseline review loop: it discovers findings, adjudicates them, directly repairs accepted findings, verifies repairs, and continues until the review converges or stops safely. After convergence, one strictly capability-gated independent Reviewer may objectively check the complete current implementation without taking mutation or final-decision authority.
|
|
9
9
|
|
|
10
10
|
## Execution Boundary
|
|
11
11
|
|
|
12
12
|
- Main-Agent review remains mandatory and must not be delegated directly or indirectly.
|
|
13
13
|
- After Main-Agent convergence only, this skill may create the single independent Reviewer defined by `${SKILL_DIR}/references/independent-code-review.md` when every structural capability in that reference is proven.
|
|
14
|
-
- Do not invoke another review
|
|
14
|
+
- Do not invoke another review process from inside this skill.
|
|
15
15
|
- Do not launch any additional review work through a general-purpose execution unit or relabel it as a finder, verifier, audit, compatibility review, verification, or gap sweep.
|
|
16
16
|
- The independent Reviewer cannot mutate, execute arbitrary commands, or create downstream execution units; prompt instructions never substitute for these structural guarantees.
|
|
17
17
|
- The Main Agent may directly read, search, edit, and run targeted verification in the active workspace.
|
|
18
|
-
- Review repairs
|
|
18
|
+
- Review repairs use targeted verification appropriate to each accepted finding.
|
|
19
19
|
- `{artifact_dir}/review-report.md` is the only persisted review artifact for this execution.
|
|
20
20
|
|
|
21
21
|
## Atomic Stage Boundary
|
|
22
22
|
|
|
23
|
-
`prizmkit-code-review` owns the complete
|
|
23
|
+
`prizmkit-code-review` owns the complete review, accepted-correction repairs, targeted verification, and `review-report.md` for one supplied change. It returns `PASS` or `NEEDS_FIXES` and stops.
|
|
24
24
|
|
|
25
25
|
## When to Use
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
- When the user asks for a complete review or commit readiness decision.
|
|
27
|
+
- A caller supplies a complete implementation for review.
|
|
28
|
+
- A caller supplies a production-affecting repair for delta review.
|
|
29
|
+
- The user asks for a complete current-change correctness review.
|
|
31
30
|
|
|
32
31
|
## When NOT to Use
|
|
33
32
|
|
|
34
33
|
- No valid `spec.md` and `plan.md` exist for the active requirement.
|
|
35
34
|
- Implementation tasks or required repair work remain incomplete.
|
|
36
|
-
-
|
|
37
|
-
- The request is a direct low-risk edit outside the formal requirement lifecycle.
|
|
35
|
+
- The request has no review input and does not require this bounded review contract.
|
|
38
36
|
|
|
39
|
-
## Input
|
|
37
|
+
## Input
|
|
40
38
|
|
|
41
39
|
| Parameter | Required | Description |
|
|
42
40
|
|---|---|---|
|
|
43
|
-
| `artifact_dir` |
|
|
41
|
+
| `artifact_dir` | Yes | Caller-supplied directory containing the exact `spec.md` and `plan.md` for this review. |
|
|
44
42
|
| `review_scope` | No | `full` for the initial review; `delta` for a production-affecting repair after a prior review pass. |
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
Review only the caller-supplied `artifact_dir`; never discover a different recent artifact. Missing or inconsistent stage input produces `NEEDS_FIXES` with the exact input blocker.
|
|
47
45
|
|
|
48
46
|
## Phase 0: Initialize Report and Reuse Current Context
|
|
49
47
|
|
|
@@ -51,7 +49,7 @@ Every invocation must reuse the same `artifact_dir`. If workflow state is missin
|
|
|
51
49
|
2. At the start of each execution, replace any prior report with a new execution header using `${SKILL_DIR}/references/review-report-template.md`.
|
|
52
50
|
3. Within that execution, append progress after every review round, repair batch, final verification, and exactly one `## Final Result`.
|
|
53
51
|
4. Start from the Main Agent's current requirement context and inspect the complete workspace change first: `git status --short`, the staged diff, and the unstaged diff. Include untracked, deleted, and renamed files in the review scope.
|
|
54
|
-
5.
|
|
52
|
+
5. Reuse current context and load only missing or potentially stale material required to resolve a concrete ambiguity, verify an acceptance criterion, or understand a changed contract.
|
|
55
53
|
6. Inspect unchanged callers, dependents, contracts, or tests only when the diff changes or may violate an interface, shared behavior, or regression boundary. Do not perform an unconditional repository-wide dependency sweep.
|
|
56
54
|
7. For `review_scope=delta`, focus on files and behavior affected since the prior review pass and expand only across contracts implicated by that delta.
|
|
57
55
|
8. If no changes exist, record final verification and `PASS` only when the current requirement context and prior implementation state prove there is nothing left to review.
|
|
@@ -109,7 +107,7 @@ For accepted findings while the round limit remains:
|
|
|
109
107
|
3. Inspect the complete resulting diff for unrelated changes and regressions.
|
|
110
108
|
4. Append repair verification and continue the review loop.
|
|
111
109
|
|
|
112
|
-
Do not
|
|
110
|
+
Do not turn review verification into a broad unrelated test campaign; use targeted checks that establish each repair.
|
|
113
111
|
|
|
114
112
|
If a repair is unsafe, incomplete, or unverifiable, record an unresolved finding and finish with `NEEDS_FIXES`.
|
|
115
113
|
|
|
@@ -141,49 +139,15 @@ Valid results:
|
|
|
141
139
|
PASS | NEEDS_FIXES
|
|
142
140
|
```
|
|
143
141
|
|
|
144
|
-
`PASS` requires review convergence, no unresolved findings, and credible targeted verification. `NEEDS_FIXES` means
|
|
142
|
+
`PASS` requires review convergence, no unresolved findings, and credible targeted verification. `NEEDS_FIXES` means a concrete correction remains or safe completion was not established.
|
|
145
143
|
|
|
146
|
-
##
|
|
144
|
+
## Output
|
|
147
145
|
|
|
148
|
-
|
|
146
|
+
Return only review-stage outputs:
|
|
149
147
|
|
|
150
|
-
|
|
148
|
+
- `artifact_dir` and `review-report.md` path;
|
|
149
|
+
- `PASS` when review converged with all accepted findings repaired;
|
|
150
|
+
- `NEEDS_FIXES` when accepted or unresolved findings remain;
|
|
151
|
+
- finding counts, repair verification, and concrete remaining findings.
|
|
151
152
|
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
"stage": "code-review",
|
|
155
|
-
"status": "completed",
|
|
156
|
-
"stage_result": "REVIEW_PASS",
|
|
157
|
-
"completed_stages": ["plan", "implement", "code-review"],
|
|
158
|
-
"next_stage": "test",
|
|
159
|
-
"resume_from": "prizmkit-test"
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
On `NEEDS_FIXES` caused by code findings, update workflow state:
|
|
164
|
-
|
|
165
|
-
```json
|
|
166
|
-
{
|
|
167
|
-
"stage": "code-review",
|
|
168
|
-
"status": "failed",
|
|
169
|
-
"stage_result": "REVIEW_NEEDS_FIXES",
|
|
170
|
-
"repair_scope": "production",
|
|
171
|
-
"next_stage": "implement",
|
|
172
|
-
"resume_from": "prizmkit-implement"
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Increment the outer `repair_round` only when returning to implementation; the review-internal ten-round loop never increments it. The outer workflow permits at most three repair rounds and must return a truthful unresolved `NEEDS_FIXES` result instead of beginning a fourth.
|
|
177
|
-
|
|
178
|
-
## Handoff
|
|
179
|
-
|
|
180
|
-
After `PASS`:
|
|
181
|
-
|
|
182
|
-
```text
|
|
183
|
-
REVIEW_PASS
|
|
184
|
-
→ /prizmkit-test
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
If workflow state names an active `orchestrator`, return `REVIEW_PASS`, the report/state paths, and `next_stage=test` to it; do not invoke test independently. For direct stage use, report the exact `/prizmkit-test` invocation and same `artifact_dir`; a host may perform that semantic handoff on the user's behalf.
|
|
188
|
-
|
|
189
|
-
After `NEEDS_FIXES`, stop and hand off to `/prizmkit-implement`; do not test or commit the unrepaired production change.
|
|
153
|
+
Return only the listed review outputs. Do not invoke another Skill.
|