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.
Files changed (157) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codex/skill-adapter.js +1 -1
  3. package/bundled/adapters/pi/skill-adapter.js +2 -1
  4. package/bundled/dev-pipeline/.env.example +2 -6
  5. package/bundled/dev-pipeline/README.md +21 -27
  6. package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +341 -15
  7. package/bundled/dev-pipeline/prizmkit_runtime/cli.py +0 -3
  8. package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +1 -15
  9. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +48 -14
  10. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +50 -2
  11. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -9
  12. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +3 -3
  13. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +120 -22
  14. package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +482 -0
  15. package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +64 -11
  16. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +145 -367
  17. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +91 -62
  18. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +105 -69
  19. package/bundled/dev-pipeline/scripts/prompt_framework.py +36 -41
  20. package/bundled/dev-pipeline/scripts/update-bug-status.py +1 -4
  21. package/bundled/dev-pipeline/scripts/update-checkpoint.py +61 -13
  22. package/bundled/dev-pipeline/scripts/update-feature-status.py +1 -4
  23. package/bundled/dev-pipeline/scripts/update-refactor-status.py +1 -4
  24. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +22 -27
  25. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +71 -104
  26. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +59 -111
  27. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +37 -72
  28. package/bundled/dev-pipeline/templates/sections/artifact-manifest.md +39 -0
  29. package/bundled/dev-pipeline/templates/sections/bugfix-critical-paths.md +3 -1
  30. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +8 -25
  31. package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +3 -3
  32. package/bundled/dev-pipeline/templates/sections/bugfix-phase-implement.md +2 -2
  33. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
  34. package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +2 -2
  35. package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +4 -4
  36. package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +0 -1
  37. package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +7 -4
  38. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +14 -27
  39. package/bundled/dev-pipeline/templates/sections/feature-completion-summary.md +20 -0
  40. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -71
  41. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -7
  42. package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +3 -3
  43. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -4
  44. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +5 -17
  45. package/bundled/dev-pipeline/templates/sections/refactor-critical-paths.md +3 -1
  46. package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +10 -23
  47. package/bundled/dev-pipeline/templates/sections/refactor-phase-implement.md +2 -2
  48. package/bundled/dev-pipeline/templates/sections/refactor-phase-plan.md +2 -2
  49. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
  50. package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +2 -2
  51. package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +7 -7
  52. package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +0 -1
  53. package/bundled/dev-pipeline/templates/sections/retrospective.md +12 -0
  54. package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +35 -0
  55. package/bundled/dev-pipeline/templates/session-status-schema.json +45 -62
  56. package/bundled/dev-pipeline/tests/test_checkpoint_state.py +469 -18
  57. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +262 -175
  58. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +62 -23
  59. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +76 -28
  60. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +168 -18
  61. package/bundled/dev-pipeline/tests/test_recovery_workflow.py +111 -0
  62. package/bundled/dev-pipeline/tests/test_reset_preserve.py +0 -2
  63. package/bundled/dev-pipeline/tests/test_runtime_commit.py +608 -0
  64. package/bundled/dev-pipeline/tests/test_unified_cli.py +167 -25
  65. package/bundled/skills/_metadata.json +9 -9
  66. package/bundled/skills/app-planner/SKILL.md +3 -3
  67. package/bundled/skills/app-planner/references/generated-plan-review.md +2 -1
  68. package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +56 -64
  69. package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +85 -240
  70. package/bundled/skills/app-planner/references/rules/backend/question-bank.md +25 -25
  71. package/bundled/skills/app-planner/references/rules/backend/question-manifest.json +16 -7
  72. package/bundled/skills/app-planner/references/rules/backend/template.md +74 -92
  73. package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +93 -93
  74. package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +66 -173
  75. package/bundled/skills/app-planner/references/rules/database/question-bank.md +31 -26
  76. package/bundled/skills/app-planner/references/rules/database/question-manifest.json +13 -4
  77. package/bundled/skills/app-planner/references/rules/database/template.md +76 -98
  78. package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +68 -95
  79. package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +93 -166
  80. package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +46 -36
  81. package/bundled/skills/app-planner/references/rules/frontend/question-manifest.json +11 -2
  82. package/bundled/skills/app-planner/references/rules/frontend/template.md +79 -257
  83. package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +91 -99
  84. package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +73 -246
  85. package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +17 -17
  86. package/bundled/skills/app-planner/references/rules/mobile/question-manifest.json +17 -2
  87. package/bundled/skills/app-planner/references/rules/mobile/template.md +73 -85
  88. package/bundled/skills/app-planner/references/rules-configuration.md +133 -65
  89. package/bundled/skills/app-planner/scripts/validate-rules-configuration.py +291 -0
  90. package/bundled/skills/prizmkit/SKILL.md +17 -18
  91. package/bundled/skills/prizmkit/references/workflow-state-protocol.md +22 -18
  92. package/bundled/skills/prizmkit-code-review/SKILL.md +22 -58
  93. package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +6 -6
  94. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +2 -2
  95. package/bundled/skills/prizmkit-committer/SKILL.md +82 -132
  96. package/bundled/skills/prizmkit-deploy/SKILL.md +27 -11
  97. package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +89 -0
  98. package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +44 -14
  99. package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +19 -3
  100. package/bundled/skills/prizmkit-deploy/references/database-setup.md +22 -12
  101. package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +3 -1
  102. package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +22 -6
  103. package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +49 -0
  104. package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +1 -1
  105. package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +164 -0
  106. package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +9 -8
  107. package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +6 -6
  108. package/bundled/skills/prizmkit-implement/SKILL.md +30 -66
  109. package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +4 -4
  110. package/bundled/skills/prizmkit-init/SKILL.md +4 -0
  111. package/bundled/skills/prizmkit-plan/SKILL.md +21 -64
  112. package/bundled/skills/prizmkit-plan/references/artifact-identity.md +38 -0
  113. package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +4 -4
  114. package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +5 -5
  115. package/bundled/skills/prizmkit-prizm-docs/SKILL.md +11 -1
  116. package/bundled/skills/prizmkit-retrospective/SKILL.md +63 -77
  117. package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -3
  118. package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
  119. package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +17 -23
  120. package/bundled/skills/prizmkit-test/SKILL.md +64 -51
  121. package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +206 -0
  122. package/bundled/skills/prizmkit-test/references/independent-test-review.md +17 -9
  123. package/bundled/skills/prizmkit-test/references/test-coverage-model.md +45 -21
  124. package/bundled/skills/prizmkit-test/references/test-report-template.md +20 -13
  125. package/bundled/skills/prizmkit-workflow/SKILL.md +35 -37
  126. package/bundled/skills/prizmkit-workflow/references/artifact-identity.md +34 -0
  127. package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +22 -18
  128. package/bundled/skills/recovery-workflow/SKILL.md +2 -1
  129. package/bundled/skills/recovery-workflow/references/detection.md +4 -3
  130. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +15 -5
  131. package/package.json +1 -1
  132. package/src/scaffold.js +33 -22
  133. package/bundled/dev-pipeline/templates/sections/bugfix-artifacts.md +0 -16
  134. package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +0 -31
  135. package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -7
  136. package/bundled/dev-pipeline/templates/sections/critical-paths-lite.md +0 -7
  137. package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +0 -9
  138. package/bundled/dev-pipeline/templates/sections/directory-convention-lite.md +0 -6
  139. package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +0 -15
  140. package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -61
  141. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -24
  142. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -12
  143. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +0 -44
  144. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -25
  145. package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +0 -20
  146. package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +0 -20
  147. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +0 -20
  148. package/bundled/dev-pipeline/templates/sections/refactor-artifacts.md +0 -17
  149. package/bundled/dev-pipeline/templates/sections/refactor-session-status.md +0 -28
  150. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +0 -52
  151. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +0 -52
  152. package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +0 -174
  153. package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +0 -174
  154. package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +0 -174
  155. package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +0 -174
  156. package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +0 -174
  157. 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
- The lifecycle starts at `/prizmkit-plan`. For a one-entry experience, invoke `/prizmkit-workflow` with the requirement; it coordinates the same stages without replacing their responsibilities. When the host supports skill-to-skill handoff, the stages continue automatically. Otherwise, each stage writes the next semantic skill and the workflow state provides the deterministic resume context.
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 | Success handoff |
70
+ | Stage | Responsibility | Stage-local success |
71
71
  |---|---|---|
72
- | `prizmkit-plan` | Clarify the requirement and create/review `spec.md` and `plan.md`. | `status=completed`, `stage_result=PLAN_READY` → `prizmkit-implement` |
73
- | `prizmkit-implement` | Execute the plan tasks and record completion. | `status=completed`, `stage_result=IMPLEMENTED` → `prizmkit-code-review` |
74
- | `prizmkit-code-review` | Main Agent reviews, repairs, verifies, and loops until convergence. | `status=completed`, `stage_result=REVIEW_PASS` → `prizmkit-test` |
75
- | `prizmkit-test` | Validate the final reviewed workspace with project-native tests and a consistent terminal report/result pair. | `status=completed`, `stage_result=TEST_PASS` → `prizmkit-retrospective` |
76
- | `prizmkit-retrospective` | Synchronize durable project documentation or record no documentation change. | `status=completed`, `stage_result=RETRO_COMPLETE` → `prizmkit-committer` |
77
- | `prizmkit-committer` | Verify gates, request commit confirmation, and create the local commit. | `status=completed`, `stage_result=COMMITTED` |
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-plan` recommends `/prizmkit-init`.
90
- - The user may continue without initialization.
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 or delta-review requirement
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` must not create a commit until the preceding five formal stages have succeeded. Before creating the local commit, it presents the intended files, diff summary, and Conventional Commit message and waits for user confirmation.
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-slug>.json
133
+ .prizmkit/state/workflows/<requirement-identity>.json
135
134
  ```
136
135
 
137
- This runtime state records the current stage, terminal status, repair scope, repair round, and resume entry. The skill set does not prescribe whether the target project commits, ignores, or shares this file.
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. Confirm the local commit when /prizmkit-committer presents it.
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: its skills describe only this toolkit's lifecycle and independent entry points. External systems may integrate through the published skill inputs, outputs, state, and authorization contracts, but their internal architecture and names are outside this toolkit's protocol.
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. Commit the current changes with `/prizmkit-committer`.
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-slug>.json
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 confirmed or authorized commit identity |
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` | Domain result for the current stage, such as `PLAN_READY`, `IMPLEMENTED`, `REVIEW_PASS`, `REVIEW_NEEDS_FIXES`, `TEST_*`, `RETRO_COMPLETE`, or `COMMITTED`. |
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 → status=completed, stage_result=RETRO_COMPLETE
101
- retrospective NO_DOC_CHANGE → status=completed, stage_result=RETRO_COMPLETE
102
- retrospective blocked → status=failed, stage_result=RETRO_BLOCKED
103
- commit authorization pending → status=in_progress, stage_result=COMMIT_PENDING
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 or required delta review remains
119
- → caller decides whether and how to arrange another stage
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 stage use may report a possible next invocation but does not claim it ran.
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 Authorization
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
- Trusted headless execution:
152
+ Pipeline execution:
151
153
 
152
154
  ```text
153
- trusted host explicitly authorizes the current local task commit
154
- → committer verifies gates and commits automatically
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
- A self-declared or untrusted headless context does not authorize a commit.
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 authorization, or external checkpoint enforcement.
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 the complete current change for a formal PrizmKit requirement with a mandatory bounded Main-Agent loop and optional capability-gated independent correctness review. Directly repair accepted corrections, verify repairs, converge to PASS or stop with NEEDS_FIXES, and hand off to prizmkit-test. (project)"
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` is the mandatory review stage after implementation and before the full test stage. 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.
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 skill or review workflow from inside this skill.
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 occur before the full `/prizmkit-test` stage so project-native tests run against the final reviewed workspace.
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 mandatory Main-Agent review, the optional independent correctness review, accepted-correction repairs, and review verification. It writes its truthful terminal result and `next_stage`, then returns control. It must not invoke `prizmkit-test` or `prizmkit-implement` itself; the active orchestrator owns outer repair routing and the next-stage invocation.
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
- - After `/prizmkit-implement` reports `IMPLEMENTED`.
28
- - After implementation repairs that changed production code, runtime configuration, schema, dependencies, or public interfaces.
29
- - When a caller routes a high-risk production repair reported by `prizmkit-test` back for delta review.
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
- - A test-stage environment stop is caused by availability rather than a review concern; resume from test when the environment is available.
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 and State
37
+ ## Input
40
38
 
41
39
  | Parameter | Required | Description |
42
40
  |---|---|---|
43
- | `artifact_dir` | No | Directory containing `spec.md` and `plan.md`. Reuse the caller's directory or workflow-state value. |
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
- Every invocation must reuse the same `artifact_dir`. If workflow state is missing, reconstruct it from `spec.md`, `plan.md`, `review-report.md`, the current diff, and any current test report/result pair, and report the reconstruction.
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. Do not reread `spec.md`, `plan.md`, project rules, progressive docs, or unchanged source merely to recreate context the Main Agent already holds. Load only the missing or potentially stale material required to resolve a concrete ambiguity, verify an acceptance criterion, understand a changed contract, or reconstruct missing workflow state.
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 run the full auditable testing protocol as a substitute for this review stage. The full testing stage follows only after review `PASS`.
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 an outer implementation repair is required or completion must stop safely.
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
- ## Workflow State and Outer Repair Routing
144
+ ## Output
147
145
 
148
- Before reading or updating workflow state, read `${SKILL_DIR}/references/workflow-state-protocol.md`.
146
+ Return only review-stage outputs:
149
147
 
150
- On `PASS`, update workflow state:
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
- ```json
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.