prizmkit 1.1.112 → 1.1.114

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 (48) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codex/skill-adapter.js +4 -0
  3. package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +10 -10
  4. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +1 -0
  5. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -0
  6. package/bundled/dev-pipeline/scripts/utils.py +8 -3
  7. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +7 -1
  8. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +7 -1
  9. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -1
  10. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +1 -1
  11. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +7 -1
  12. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +7 -1
  13. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +7 -1
  14. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +87 -21
  15. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +14 -0
  16. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +42 -0
  17. package/bundled/dev-pipeline/tests/test_runtime_helper.py +23 -0
  18. package/bundled/skills/_metadata.json +1 -1
  19. package/bundled/skills/app-planner/SKILL.md +18 -2
  20. package/bundled/skills/app-planner/references/generated-plan-review.md +67 -0
  21. package/bundled/skills/bug-planner/SKILL.md +19 -24
  22. package/bundled/skills/bug-planner/references/generated-plan-review.md +63 -0
  23. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +43 -3
  24. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +6 -6
  25. package/bundled/skills/feature-pipeline-launcher/SKILL.md +7 -16
  26. package/bundled/skills/feature-planner/SKILL.md +17 -22
  27. package/bundled/skills/feature-planner/references/generated-plan-review.md +63 -0
  28. package/bundled/skills/feature-workflow/SKILL.md +8 -7
  29. package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +2 -2
  30. package/bundled/skills/prizmkit-deploy/references/database-setup.md +12 -3
  31. package/bundled/skills/prizmkit-init/SKILL.md +2 -2
  32. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +12 -14
  33. package/bundled/skills/prizmkit-test/SKILL.md +1 -1
  34. package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +1 -1
  35. package/bundled/skills/prizmkit-test/references/examples.md +2 -2
  36. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +3 -2
  37. package/bundled/skills/refactor-planner/SKILL.md +20 -26
  38. package/bundled/skills/refactor-planner/references/fast-path.md +2 -2
  39. package/bundled/skills/refactor-planner/references/generated-plan-review.md +63 -0
  40. package/bundled/skills/refactor-workflow/SKILL.md +6 -5
  41. package/package.json +1 -1
  42. package/src/clean.js +60 -7
  43. package/src/config.js +61 -20
  44. package/src/gitignore-template.js +6 -3
  45. package/src/manifest.js +6 -2
  46. package/src/platforms.js +14 -0
  47. package/src/scaffold.js +198 -34
  48. package/src/upgrade.js +5 -2
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.112",
3
- "bundledAt": "2026-07-08T16:44:52.355Z",
4
- "bundledFrom": "544bc17"
2
+ "frameworkVersion": "1.1.114",
3
+ "bundledAt": "2026-07-09T06:02:07.402Z",
4
+ "bundledFrom": "b1b5595"
5
5
  }
@@ -21,6 +21,10 @@ function applyCodexInteractionCompatibility(content) {
21
21
 
22
22
  return content
23
23
  .replace(/\bAskUserQuestion\b/g, 'request_user_input')
24
+ .replace(
25
+ /Use `request_user_input`; do not render path options as plain text\./g,
26
+ fallbackInstruction
27
+ )
24
28
  .replace(
25
29
  /Do NOT render options as plain text — the user must be able to click\/select\./g,
26
30
  fallbackInstruction
@@ -81,8 +81,8 @@ acceptance_criteria, status
81
81
 
82
82
  **Optional fields:**
83
83
  ```
84
- priority, affected_feature, affected_modules, environment, critic,
85
- critic_count, model
84
+ priority, dependencies, affected_feature, affected_modules, environment, critic,
85
+ critic_count, model, browser_interaction
86
86
  ```
87
87
 
88
88
  | Property | Type | Enum/Pattern | Notes |
@@ -95,7 +95,8 @@ critic_count, model
95
95
  | `error_source` | object | type enum: `stack_trace, user_report, failed_test, log_pattern, monitoring_alert` | ✓ REQUIRED |
96
96
  | `verification_type` | string | `automated, manual, hybrid` | ✓ REQUIRED |
97
97
  | `acceptance_criteria` | array | N/A | minItems: 1 |
98
- | `status` | string | `pending, triaging, reproducing, fixing, verifying, completed, failed, needs_info, skipped` | ✓ REQUIRED; more states than Feature |
98
+ | `status` | string | `pending, in_progress, completed, failed, skipped, needs_info` | ✓ REQUIRED; external list status only |
99
+ | `dependencies` | array | Pattern: `^B-\d{3}$` | Optional; bug IDs that must complete first |
99
100
  | `affected_feature` | string | Pattern: `^F-\d{3}(-[A-Z])?$` | Optional; link to original feature |
100
101
  | `affected_modules` | array | N/A | Optional; module names |
101
102
  | `environment` | object | N/A | Optional; os, runtime, browser, version |
@@ -209,12 +210,11 @@ design_system, ci_pipeline
209
210
  pending, in_progress, completed, failed, skipped, split, auto_skipped
210
211
  ```
211
212
 
212
- **Bug Fix Status (9 values):**
213
+ **Bug Fix Status (6 external values):**
213
214
  ```
214
- pending, triaging, reproducing, fixing, verifying, completed, failed, needs_info, skipped
215
+ pending, in_progress, completed, failed, skipped, needs_info
215
216
  ```
216
- *Includes intermediate workflow states: triaging, reproducing, fixing, verifying, needs_info*
217
- *NO "split" or "auto_skipped"*
217
+ *External bug-list status stays coarse. Fine-grained triage/reproduction/fix/verification phases belong in logs, checkpoints, and session metadata, not `bugs[].status`.*
218
218
 
219
219
  **Refactor Status (5 values):**
220
220
  ```
@@ -227,10 +227,10 @@ pending, in_progress, completed, failed, skipped
227
227
  | Schema | Dependencies | Pattern |
228
228
  |--------|--------------|---------|
229
229
  | Feature | `dependencies` (required) | `^F-\d{3}(-[A-Z])?$` - can reference sub-features |
230
- | Bug Fix | N/A | No `dependencies` field |
230
+ | Bug Fix | `dependencies` (optional) | `^B-\d{3}$` - can reference prerequisite bug fixes |
231
231
  | Refactor | `dependencies` (required) | `^R-\d{3}$` - ONLY refactor IDs, no sub-IDs |
232
232
 
233
- **Issue:** Bug Fix schema lacks dependency tracking. Bugs cannot declare prerequisites. Feature dependencies support sub-features; Refactor dependencies do not.
233
+ **Contract:** Bug Fix dependencies are supported as optional prerequisites. Runtime selects eligible bugs in stable list order after dependencies are completed.
234
234
 
235
235
  ### 4.5 Acceptance Criteria vs Task Lists
236
236
 
@@ -493,7 +493,7 @@ Located in `/dev-pipeline/templates/`:
493
493
 
494
494
  ### Status Enums
495
495
  - **Feature**: `[pending, in_progress, completed, failed, skipped, split, auto_skipped]` (7 values)
496
- - **Bug Fix**: `[pending, triaging, reproducing, fixing, verifying, completed, failed, needs_info, skipped]` (9 values)
496
+ - **Bug Fix**: `[pending, in_progress, completed, failed, skipped, needs_info]` (6 external values)
497
497
  - **Refactor**: `[pending, in_progress, completed, failed, skipped]` (5 values)
498
498
 
499
499
  ### Complexity/Estimated Complexity Enums
@@ -1906,6 +1906,7 @@ def build_replacements(args, feature, features, global_context, script_dir):
1906
1906
  "{{HAS_PLAN}}": "true" if artifacts["has_plan"] else "false",
1907
1907
  "{{BROWSER_VERIFY_STEPS}}": browser_verify_steps,
1908
1908
  "{{BROWSER_TOOL}}": browser_tool,
1909
+ "{{BROWSER_BLOCKING}}": "true" if browser_blocking else "false",
1909
1910
  "{{AC_CHECKLIST}}": format_ac_checklist(
1910
1911
  feature.get("acceptance_criteria", [])
1911
1912
  ),
@@ -417,6 +417,13 @@ def assemble_bugfix_sections(pipeline_mode, sections_dir, critic_enabled, browse
417
417
  sections.append(("phase-browser", load_section(sections_dir, "phase-browser-verification-auto.md")))
418
418
  if manual_gate:
419
419
  sections.append(("bugfix-manual-gate", load_section(sections_dir, "bugfix-phase-manual-verification.md")))
420
+ sections.extend([
421
+ ("bugfix-session-status", load_section(sections_dir, "bugfix-session-status.md")),
422
+ ("bugfix-critical-paths", load_section(sections_dir, "bugfix-critical-paths.md")),
423
+ ("failure-capture", load_section(sections_dir, "failure-capture.md")),
424
+ ("bugfix-reminders", load_section(sections_dir, "bugfix-reminders.md")),
425
+ ])
426
+ return sections
420
427
  sections.extend([
421
428
  ("bugfix-phase-commit-report", load_section(sections_dir, "bugfix-phase-commit-report.md")),
422
429
  ("bugfix-session-status", load_section(sections_dir, "bugfix-session-status.md")),
@@ -746,12 +746,17 @@ def resolve_prompt_platform(project_root):
746
746
  )
747
747
 
748
748
  def read_platform_conventions(project_root):
749
- """Resolve the platform-specific project conventions file.
749
+ """Resolve the platform-specific main project conventions file.
750
750
 
751
751
  Returns a path reference for the AI agent to read at runtime,
752
- rather than inlining the full file content into the prompt.
752
+ rather than inlining the full file content into the prompt. Private
753
+ framework memory files are intentionally excluded because project
754
+ conventions and Infrastructure live in the user-facing main files.
753
755
  """
754
- platform = os.environ.get("PRIZMKIT_PLATFORM", "claude")
756
+ try:
757
+ platform = resolve_prompt_platform(project_root)
758
+ except RuntimeError:
759
+ platform = os.environ.get("PRIZMKIT_PLATFORM", "claude")
755
760
  if platform == "codebuddy":
756
761
  candidates = ["CODEBUDDY.md", "CLAUDE.md", "AGENTS.md"]
757
762
  elif platform == "codex":
@@ -338,7 +338,13 @@ Append results to `context-snapshot.md`:
338
338
  Browser cleanup: confirmed
339
339
  ```
340
340
 
341
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
341
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
342
+
343
+ If verification fails:
344
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
345
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
346
+
347
+ You MUST attempt verification and MUST clean up the dev server in both cases.
342
348
  {{END_IF_BROWSER_INTERACTION}}
343
349
 
344
350
  ### Phase 4: Architecture Sync & Commit (SINGLE COMMIT)
@@ -488,7 +488,13 @@ Append results to `context-snapshot.md`:
488
488
  Browser cleanup: confirmed
489
489
  ```
490
490
 
491
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
491
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
492
+
493
+ If verification fails:
494
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
495
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
496
+
497
+ You MUST attempt verification and MUST clean up the dev server in both cases.
492
498
  {{END_IF_BROWSER_INTERACTION}}
493
499
 
494
500
  ### Phase 6: Architecture Sync & Commit (SINGLE COMMIT)
@@ -483,7 +483,13 @@ Append results to `context-snapshot.md`:
483
483
  Browser cleanup: confirmed
484
484
  ```
485
485
 
486
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
486
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
487
+
488
+ If verification fails:
489
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
490
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
491
+
492
+ You MUST attempt verification and MUST clean up the dev server in both cases.
487
493
  {{END_IF_BROWSER_INTERACTION}}
488
494
 
489
495
  ### Phase 6: Retrospective & Commit (SINGLE COMMIT) — DO NOT SKIP
@@ -1,6 +1,6 @@
1
1
  ### Phase 4: Commit & Learn
2
2
 
3
- Skip this phase only when the Manual / Hybrid Verification Gate stopped the fresh session before commit.
3
+ This phase is included only for sessions allowed to commit. Fresh manual/hybrid bugfix prompts omit this phase entirely and stop as partial before retrospective/commit.
4
4
 
5
5
  **Bug Fix Documentation Policy**:
6
6
  - Default: run `/prizmkit-retrospective` with structural sync only.
@@ -117,5 +117,11 @@ Append results to `context-snapshot.md`:
117
117
  Browser cleanup: confirmed
118
118
  ```
119
119
 
120
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
120
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
121
+
122
+ If verification fails:
123
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
124
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
125
+
126
+ You MUST attempt verification and MUST clean up the dev server in both cases.
121
127
 
@@ -114,5 +114,11 @@ Append results to `context-snapshot.md`:
114
114
  Browser cleanup: confirmed
115
115
  ```
116
116
 
117
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
117
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
118
+
119
+ If verification fails:
120
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
121
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
122
+
123
+ You MUST attempt verification and MUST clean up the dev server in both cases.
118
124
 
@@ -101,5 +101,11 @@ Server cleanup: confirmed
101
101
  Browser cleanup: confirmed
102
102
  ```
103
103
 
104
- If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
104
+ Browser blocking policy: `{{BROWSER_BLOCKING}}`.
105
+
106
+ If verification fails:
107
+ - If `{{BROWSER_BLOCKING}}` is `true`: mark checkpoint step `browser-verification` as `failed`, write `failure-log.md` with browser evidence, clean up the dev server/browser, and stop before commit.
108
+ - If `{{BROWSER_BLOCKING}}` is `false`: log the failure details, mark checkpoint step `browser-verification` according to the evidence, clean up the dev server/browser, and continue.
109
+
110
+ You MUST attempt verification and MUST clean up the dev server in both cases.
105
111
 
@@ -1100,7 +1100,10 @@ def _ensure_agent_files(project, platforms=("claude", "codex")):
1100
1100
  (agents_dir / f"prizm-dev-team-{name}{suffix}").write_text("agent\n", encoding="utf-8")
1101
1101
 
1102
1102
 
1103
- def _render_bugfix_prompt(tmp_path, platform="claude", explicit_platform=None):
1103
+ def _render_bugfix_prompt(
1104
+ tmp_path, platform="claude", explicit_platform=None,
1105
+ bug_overrides=None, retry_count="0", resume_phase="null",
1106
+ ):
1104
1107
  from generate_bugfix_prompt import main as bugfix_main
1105
1108
 
1106
1109
  project = tmp_path / "bugfix-project"
@@ -1112,8 +1115,11 @@ def _render_bugfix_prompt(tmp_path, platform="claude", explicit_platform=None):
1112
1115
  _ensure_agent_files(project)
1113
1116
  bug_list = project / ".prizmkit" / "plans" / "bug-fix-list.json"
1114
1117
  bug_list.parent.mkdir(parents=True)
1118
+ bug = {"id": "B-001", "title": "Broken", "description": "Fix it", "acceptance_criteria": ["Works"]}
1119
+ if bug_overrides:
1120
+ bug.update(bug_overrides)
1115
1121
  bug_list.write_text(json.dumps({
1116
- "bugs": [{"id": "B-001", "title": "Broken", "description": "Fix it", "acceptance_criteria": ["Works"]}],
1122
+ "bugs": [bug],
1117
1123
  "global_context": {"language": "Python"},
1118
1124
  }), encoding="utf-8")
1119
1125
  output = project / "bugfix-prompt.md"
@@ -1130,8 +1136,8 @@ def _render_bugfix_prompt(tmp_path, platform="claude", explicit_platform=None):
1130
1136
  "--bug-id", "B-001",
1131
1137
  "--session-id", "session-1",
1132
1138
  "--run-id", "run-1",
1133
- "--retry-count", "0",
1134
- "--resume-phase", "null",
1139
+ "--retry-count", retry_count,
1140
+ "--resume-phase", resume_phase,
1135
1141
  "--state-dir", str(project / ".prizmkit" / "state" / "bugfix"),
1136
1142
  "--project-root", str(project),
1137
1143
  "--output", str(output),
@@ -1150,7 +1156,7 @@ def _render_bugfix_prompt(tmp_path, platform="claude", explicit_platform=None):
1150
1156
  return output.read_text(encoding="utf-8")
1151
1157
 
1152
1158
 
1153
- def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None):
1159
+ def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None, refactor_overrides=None):
1154
1160
  from generate_refactor_prompt import main as refactor_main
1155
1161
 
1156
1162
  project = tmp_path / "refactor-project"
@@ -1162,14 +1168,17 @@ def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None)
1162
1168
  _ensure_agent_files(project)
1163
1169
  refactor_list = project / ".prizmkit" / "plans" / "refactor-list.json"
1164
1170
  refactor_list.parent.mkdir(parents=True)
1171
+ refactor = {
1172
+ "id": "R-001",
1173
+ "title": "Restructure",
1174
+ "description": "Preserve behavior",
1175
+ "acceptance_criteria": ["Behavior preserved"],
1176
+ "scope": {"files": ["src/a.py"], "modules": ["src"]},
1177
+ }
1178
+ if refactor_overrides:
1179
+ refactor.update(refactor_overrides)
1165
1180
  refactor_list.write_text(json.dumps({
1166
- "refactors": [{
1167
- "id": "R-001",
1168
- "title": "Restructure",
1169
- "description": "Preserve behavior",
1170
- "acceptance_criteria": ["Behavior preserved"],
1171
- "scope": {"files": ["src/a.py"], "modules": ["src"]},
1172
- }],
1181
+ "refactors": [refactor],
1173
1182
  "global_context": {"language": "Python"},
1174
1183
  }), encoding="utf-8")
1175
1184
  output = project / "refactor-prompt.md"
@@ -1189,18 +1198,14 @@ def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None)
1189
1198
  "--retry-count", "0",
1190
1199
  "--resume-phase", "null",
1191
1200
  "--state-dir", str(project / ".prizmkit" / "state" / "refactor"),
1201
+ "--project-root", str(project),
1192
1202
  "--output", str(output),
1193
1203
  ]
1194
- old_cwd = os.getcwd()
1195
- os.chdir(project)
1196
1204
  try:
1197
- try:
1198
- refactor_main()
1199
- except SystemExit as exc:
1200
- if exc.code not in (0, None):
1201
- raise
1202
- finally:
1203
- os.chdir(old_cwd)
1205
+ refactor_main()
1206
+ except SystemExit as exc:
1207
+ if exc.code not in (0, None):
1208
+ raise
1204
1209
  finally:
1205
1210
  os.sys.argv = old_argv
1206
1211
  if old_platform is None:
@@ -1210,6 +1215,67 @@ def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None)
1210
1215
  return output.read_text(encoding="utf-8")
1211
1216
 
1212
1217
 
1218
+ class TestBrowserBlockingPromptPolicy:
1219
+ def test_feature_bugfix_refactor_blocking_browser_policy_stops_before_commit(self, tmp_path):
1220
+ browser_interaction = {
1221
+ "tool": "auto",
1222
+ "blocking": True,
1223
+ "verify_steps": ["Open the page"],
1224
+ }
1225
+ prompts = [
1226
+ _render_feature_prompt(tmp_path / "feature-browser-blocking", browser_interaction=browser_interaction),
1227
+ _render_bugfix_prompt(tmp_path / "bugfix-browser-blocking", bug_overrides={"browser_interaction": browser_interaction}),
1228
+ _render_refactor_prompt(tmp_path / "refactor-browser-blocking", refactor_overrides={"browser_interaction": browser_interaction}),
1229
+ ]
1230
+
1231
+ for prompt in prompts:
1232
+ assert "Browser blocking policy: `true`" in prompt
1233
+ assert "stop before commit" in prompt
1234
+ assert "Failures do NOT block the commit" not in prompt
1235
+
1236
+ def test_feature_bugfix_refactor_nonblocking_browser_policy_continues(self, tmp_path):
1237
+ browser_interaction = {
1238
+ "tool": "auto",
1239
+ "blocking": False,
1240
+ "verify_steps": ["Open the page"],
1241
+ }
1242
+ prompts = [
1243
+ _render_feature_prompt(tmp_path / "feature-browser-nonblocking", browser_interaction=browser_interaction),
1244
+ _render_bugfix_prompt(tmp_path / "bugfix-browser-nonblocking", bug_overrides={"browser_interaction": browser_interaction}),
1245
+ _render_refactor_prompt(tmp_path / "refactor-browser-nonblocking", refactor_overrides={"browser_interaction": browser_interaction}),
1246
+ ]
1247
+
1248
+ for prompt in prompts:
1249
+ assert "Browser blocking policy: `false`" in prompt
1250
+ assert "clean up the dev server/browser, and continue" in prompt
1251
+ assert "Failures do NOT block the commit" not in prompt
1252
+
1253
+
1254
+ class TestManualHybridBugfixPromptPolicy:
1255
+ def test_fresh_manual_bugfix_prompt_stops_before_commit_phase(self, tmp_path):
1256
+ prompt = _render_bugfix_prompt(
1257
+ tmp_path / "fresh-manual-bugfix",
1258
+ bug_overrides={"verification_type": "manual"},
1259
+ )
1260
+
1261
+ assert "Manual / Hybrid Verification Gate" in prompt
1262
+ assert "Stop before `/prizmkit-retrospective` and `/prizmkit-committer`" in prompt
1263
+ assert "### Phase 4: Commit & Learn" not in prompt
1264
+ assert "Run `/prizmkit-committer` with commit prefix" not in prompt
1265
+
1266
+ def test_recovery_manual_bugfix_prompt_includes_commit_phase_with_substitution_policy(self, tmp_path):
1267
+ prompt = _render_bugfix_prompt(
1268
+ tmp_path / "recovery-manual-bugfix",
1269
+ bug_overrides={"verification_type": "manual"},
1270
+ retry_count="1",
1271
+ )
1272
+
1273
+ assert "Manual / Hybrid Verification Gate" not in prompt
1274
+ assert "Recovery-class session: automated verification may substitute for manual/hybrid UAT" in prompt
1275
+ assert "### Phase 4: Commit & Learn" in prompt
1276
+ assert "Run `/prizmkit-committer` with commit prefix" in prompt
1277
+
1278
+
1213
1279
  class TestHeadlessPromptCleanupF033:
1214
1280
  def test_rendered_feature_bugfix_refactor_prompts_are_clean(self, tmp_path):
1215
1281
  prompts = []
@@ -307,6 +307,20 @@ def test_template_source_is_clean_for_headless_prompt_contract():
307
307
  assert forbidden not in content
308
308
 
309
309
 
310
+ def test_bugfix_prompt_keeps_fine_grained_phases_out_of_external_status_contract():
311
+ content = Path("dev-pipeline/templates/bugfix-bootstrap-prompt.md").read_text(encoding="utf-8")
312
+ old_statuses = ["triaging", "reproducing", "fixing", "verifying"]
313
+
314
+ assert "external bug-list status field" in content
315
+ assert "pending`, `in_progress`, `completed`, `failed`, `skipped`, or `needs_info`" in content
316
+ for status in old_statuses:
317
+ assert f"status=\"{status}\"" not in content
318
+ assert f"status = \"{status}\"" not in content
319
+ assert f"status='{status}'" not in content
320
+ assert f"status = '{status}'" not in content
321
+ assert f"Set bug status to `{status}`" not in content
322
+
323
+
310
324
  # ---------------------------------------------------------------------------
311
325
  # Anti-Bash regression guardrails (F-039)
312
326
  # Note: grep -n, sed -n, grep -q, wc -l excluded — referenced in bugfix context
@@ -514,6 +514,48 @@ def test_init_scripts_reject_missing_self_and_cycle_dependencies(tmp_path):
514
514
  assert any(expected_fragments[scenario] in error for error in payload["errors"])
515
515
 
516
516
 
517
+ def test_bug_planner_validator_rejects_dependency_cycles():
518
+ from importlib.util import module_from_spec, spec_from_file_location
519
+
520
+ script_path = REPO_ROOT / "core" / "skills" / "orchestration-skill" / "pipelines" / "bug-planner" / "scripts" / "validate-bug-list.py"
521
+ spec = spec_from_file_location("bug_planner_validate_bug_list", script_path)
522
+ module = module_from_spec(spec)
523
+ spec.loader.exec_module(module)
524
+
525
+ result = module.validate({
526
+ "$schema": "dev-pipeline-bug-fix-list-v1",
527
+ "project_name": "Fake",
528
+ "bugs": [
529
+ {
530
+ "id": "B-001",
531
+ "title": "First",
532
+ "description": "First bug",
533
+ "severity": "medium",
534
+ "error_source": {"type": "user_report"},
535
+ "verification_type": "manual",
536
+ "acceptance_criteria": ["fixed"],
537
+ "dependencies": ["B-002"],
538
+ "status": "pending",
539
+ },
540
+ {
541
+ "id": "B-002",
542
+ "title": "Second",
543
+ "description": "Second bug",
544
+ "severity": "medium",
545
+ "error_source": {"type": "user_report"},
546
+ "verification_type": "manual",
547
+ "acceptance_criteria": ["fixed"],
548
+ "dependencies": ["B-001"],
549
+ "status": "pending",
550
+ },
551
+ ],
552
+ })
553
+
554
+ assert result["valid"] is False
555
+ assert any("Dependency cycle detected" in error for error in result["errors"])
556
+
557
+
558
+
517
559
  def _family_items(kind, entries):
518
560
  items = []
519
561
  for item_id, dependencies, status in entries:
@@ -99,6 +99,29 @@ class TestPlatformExecutableAndPortHelpers:
99
99
  assert payload["platform"] == "codex"
100
100
  assert payload["path"].endswith(".agents/skills/playwright-cli")
101
101
 
102
+ def test_read_platform_conventions_uses_resolved_main_memory_file(self, tmp_path, monkeypatch):
103
+ from scripts.utils import read_platform_conventions
104
+
105
+ project = tmp_path / "project"
106
+ (project / ".prizmkit").mkdir(parents=True)
107
+ (project / ".prizmkit" / "config.json").write_text(
108
+ json.dumps({"platform": "codex", "ai_cli": "codex"}), encoding="utf-8"
109
+ )
110
+ (project / "AGENTS.md").write_text("### Project Conventions\n", encoding="utf-8")
111
+ (project / "AGENTS.private.md").write_text("framework protocol\n", encoding="utf-8")
112
+ monkeypatch.delenv("PRIZMKIT_PLATFORM", raising=False)
113
+
114
+ assert read_platform_conventions(project) == "`AGENTS.md`"
115
+
116
+ (project / ".prizmkit" / "config.json").write_text(
117
+ json.dumps({"platform": "codebuddy", "ai_cli": "cbc"}), encoding="utf-8"
118
+ )
119
+ (project / "CODEBUDDY.md").write_text("### Infrastructure\n", encoding="utf-8")
120
+ (project / "CODEBUDDY.private.md").write_text("framework protocol\n", encoding="utf-8")
121
+
122
+ assert read_platform_conventions(project) == "`CODEBUDDY.md`"
123
+ assert ".private.md" not in read_platform_conventions(project)
124
+
102
125
  def test_codebuddy_cli_env_wins_over_filesystem_markers(self, tmp_path, monkeypatch):
103
126
  from prizmkit_runtime.platform_detection import resolve_platform
104
127
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.112",
2
+ "version": "1.1.114",
3
3
  "skills": {
4
4
  "prizmkit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
@@ -180,7 +180,7 @@ Route by answer:
180
180
  - Proactively scan the project (same as brownfield behavior)
181
181
  - Generate project-brief.md from inferred context
182
182
  - Skip extensive brainstorming and constraint phases
183
- - Present brief for user confirmation → write → done
183
+ - Present brief for user confirmation → write → run CP-AP-6 Generated App-Plan Review Gate → completion summary
184
184
 
185
185
  Session goal tracking: Track the intent (`produce`, `explore`, or `quick_context`) throughout the session. If `explore`, always re-prompt before ending.
186
186
 
@@ -240,6 +240,21 @@ Checkpoints catch cascading errors early — skipping one means the next phase b
240
240
  | **CP-AP-3** | Frontend Design Evaluated | For frontend projects: checked for existing UI/UX design system; user was asked if missing. **Auto-pass** for backend-only or non-UI projects. | 2 |
241
241
  | **CP-AP-4** | Project Brief Accumulated | `.prizmkit/plans/project-brief.md` exists at `.prizmkit/plans/` with at least 3 ideas listed. For brownfield: already-implemented items marked `[x]` count toward this total. | 3 |
242
242
  | **CP-AP-5** | Planning Complete | All project-level context captured: conventions, infrastructure config, tech stack, architecture decisions, project brief finalized | 4 |
243
+ | **CP-AP-6** | Local Plan Review Passed | Local generated-plan review loaded `${SKILL_DIR}/references/generated-plan-review.md`, directly reviewed current-session final app-planning artifacts, applied accepted fixes through source/writer paths, and rechecked changed sections | 4 |
244
+
245
+ ## Generated App-Plan Review Gate
246
+
247
+ User requirement preserved verbatim: `Add generated-plan review in app-planner also .`
248
+
249
+ Run this gate before any final handoff whenever the current `app-planner` session wrote or rewrote final app-level planning content. In full produce mode this runs after CP-AP-5; in Quick Context Mode it runs after the confirmed `.prizmkit/plans/project-brief.md` write; in conventions, infrastructure, architecture-decision, or rules-only final-write flows it runs after those writes and before the completion summary. This gate reviews generated planning artifacts directly, not implementation diffs.
250
+
251
+ 1. **Load the local reference**: read `${SKILL_DIR}/references/generated-plan-review.md` and follow it as the source of truth for app-planner generated content review.
252
+ 2. **Read actual planning artifacts directly**: inspect current-session final outputs such as `.prizmkit/plans/project-brief.md`, selected `AGENTS.md` / `CLAUDE.md` / `CODEBUDDY.md` sections, `.prizmkit/rules/<layer>-rules.md`, and `.prizmkit/prizm-docs/root.prizm` `RULES:` pointer line. Do not rely on `git status`, `git diff`, or `git diff --cached`, because `.prizmkit` planning artifacts are often gitignored or untracked.
253
+ 3. **Scope to new/changed app-planning content**: compare against pre-session snapshots or in-memory drafts when available. Preserve unchanged historical brief items, instruction-file sections, rules files, and Prizm doc content. For explore-only sessions, draft-save exits, or flows with no new final planning content, report: `Local generated-plan review: not applicable — no new final planning content written.`
254
+ 4. **Run the local checklist** from the reference: project brief completeness, consistency of conventions/infrastructure/architecture decisions, rules pointer consistency, user-provided wording preservation, app-planner writable-boundary compliance, and downstream `feature-planner` readiness to produce `.prizmkit/plans/feature-list.json` without guessing.
255
+ 5. **Apply accepted fixes through the source/writer path**: project brief fixes go through the draft/checklist source, instruction-file section fixes go through the selected platform instruction file section source with user confirmation when changing approved wording, rules fixes re-render from rules configuration answers/templates when available, and `root.prizm` fixes are limited to the `RULES:` pointer line.
256
+ 6. **Recheck changed sections directly** after every accepted fix batch.
257
+ 7. **Report CP-AP-6** in the completion summary: include local generated-plan review verdict, reviewed app-planning artifacts/sections, accepted fixes (or "none"), and final writer/validation result.
243
258
 
244
259
  ## Architecture Decision Capture
245
260
 
@@ -277,7 +292,7 @@ When the session appears to be ending:
277
292
 
278
293
  ## Completion Summary
279
294
 
280
- After all checkpoints pass, present a summary and end the session:
295
+ After CP-AP-6 passes or is reported not applicable, present a summary and end the session:
281
296
 
282
297
  1. **Summary** (as text): List all project-level artifacts produced:
283
298
  - Project conventions → `AGENTS.md` / `CLAUDE.md` / `CODEBUDDY.md` `### Project Conventions`
@@ -286,6 +301,7 @@ After all checkpoints pass, present a summary and end the session:
286
301
  - Architecture decisions (if any) → `AGENTS.md` / `CLAUDE.md` / `CODEBUDDY.md` `### Architecture Decisions`
287
302
  - Dev rules (if configured) → `.prizmkit/rules/<layer>-rules.md` (with `root.prizm` `RULES:` pointer)
288
303
  - Project brief → `.prizmkit/plans/project-brief.md`
304
+ - Local generated-plan review → verdict, reviewed app-planning artifacts/sections, accepted fixes (or "none"), and final writer/validation result
289
305
 
290
306
  2. **Suggest possible next steps** (as text, NOT auto-invoked):
291
307
  > Project-level planning is complete. When you're ready, here are some possible next steps:
@@ -0,0 +1,67 @@
1
+ # Generated Plan Review — App Planner
2
+
3
+ Use this local review loop before app-planner presents the final completion summary for current-session final planning artifacts. This is a planner-output review, not an implementation/code-diff review.
4
+
5
+ ## Trigger
6
+
7
+ Run only when the current `app-planner` session wrote or rewrote final app-level planning content. This includes project brief finalization, project conventions, infrastructure configuration, architecture decisions, rules files, or a `root.prizm` `RULES:` pointer update.
8
+
9
+ For explore-only sessions, draft-save exits, validate-only checks, or other flows with no new final planning content, report: `Local generated-plan review: not applicable — no new final planning content written.`
10
+
11
+ ## Direct Artifact Reads
12
+
13
+ Planning artifacts may be gitignored, untracked, or absent from staged and unstaged diffs. Read the actual files and source sections directly when they were produced or changed in the current session:
14
+
15
+ - Project brief: `.prizmkit/plans/project-brief.md`
16
+ - Draft brief when present: `.prizmkit/plans/project-brief.draft.md`
17
+ - Project instruction files selected by `.prizmkit/manifest.json`: `AGENTS.md`, `CLAUDE.md`, `CODEBUDDY.md`
18
+ - Generated rule files: `.prizmkit/rules/<layer>-rules.md`
19
+ - Prizm docs root pointer: `.prizmkit/prizm-docs/root.prizm` `RULES:` line only
20
+ - In-memory answers, draft brief data, rules configuration answers, or section snapshots captured before writes
21
+
22
+ Do not rely on `git status`, `git diff`, or `git diff --cached` to decide whether app-planner output exists or changed. Do not invoke `/prizmkit-code-review` for this planner-output gate; `/prizmkit-code-review` remains the implementation/code-diff review gate after `/prizmkit-implement`.
23
+
24
+ ## Review Scope
25
+
26
+ 1. Compare current final artifacts with pre-session snapshots or in-memory drafts when available.
27
+ 2. Review only newly added or changed app-planning sections from the current session.
28
+ 3. Preserve unchanged historical project brief ideas, instruction-file sections, rules files, and Prizm doc content.
29
+ 4. For `.prizmkit/prizm-docs/root.prizm`, review only the `RULES:` pointer line managed by rules configuration.
30
+ 5. If no snapshot exists, review only the artifacts the current app-planner session reports as produced.
31
+
32
+ ## Source-of-Truth Map
33
+
34
+ - `project-brief.md` fixes go through the draft/checklist project brief source representation described in `project-brief-guide.md`, then rewrite the final brief through the existing project brief writer path.
35
+ - Project conventions, infrastructure, and architecture decisions are source sections in `AGENTS.md`, `CLAUDE.md`, or `CODEBUDDY.md`. If a fix changes user-approved wording or meaning, ask for user confirmation before rewriting.
36
+ - `.prizmkit/rules/<layer>-rules.md` fixes should re-render from the rules configuration answers and template inputs when available. If no structured source remains, update the source rule section explicitly and report that source path.
37
+ - `root.prizm` fixes are limited to correcting or adding the `RULES:` pointer line; do not rewrite unrelated root content.
38
+
39
+ ## Review Checklist
40
+
41
+ For every reviewed app-planning artifact or section, check:
42
+
43
+ - Project brief completeness: goal, users, differentiators, constraints, tech stack assumptions, and at least three actionable ideas when producing a final brief
44
+ - Consistency among conventions, infrastructure, architecture decisions, and project brief content
45
+ - Infrastructure completeness or explicit deferral for database, deployment, and cloud services topics when those flows ran
46
+ - Rules pointer consistency: generated `.prizmkit/rules/<layer>-rules.md` files are referenced by the `root.prizm` `RULES:` line when rules were configured
47
+ - User-provided wording preservation in project brief ideas, conventions, infrastructure notes, architecture decisions, and rules
48
+ - Downstream readiness: `feature-planner` has enough context to produce `.prizmkit/plans/feature-list.json` without guessing core app purpose, stack, constraints, or implementation conventions
49
+ - No implementation/scaffolding actions are introduced by the app plan; outputs stay within app-planner's writable boundary
50
+
51
+ ## Fix Loop
52
+
53
+ 1. Present findings with artifact path, section name, severity, evidence, and suggested source change.
54
+ 2. Accept only findings that improve planner correctness, consistency, user wording preservation, or downstream feature-planner readiness.
55
+ 3. Apply accepted fixes to the source representation first: brief draft/checklist, instruction-file section source, rules answer/template source, or `root.prizm` `RULES:` pointer source.
56
+ 4. Regenerate or rewrite final artifacts through the same writer path used by app-planner. Do not hand-patch final artifacts as a shortcut when a draft/source representation exists.
57
+ 5. Re-read the changed final artifacts directly and re-run the local review only for changed sections.
58
+
59
+ ## Report Format
60
+
61
+ Report in the final completion summary:
62
+
63
+ - `Local generated-plan review: PASS` or `NEEDS_FIXES`
64
+ - Reviewed app-planning sections/artifacts
65
+ - Accepted fixes, or `none`
66
+ - Final writer/validation result for each changed artifact
67
+ - Note when review was not applicable because no new final planning content was written