prizmkit 1.1.112 → 1.1.113

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 (29) 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/templates/bootstrap-tier1.md +7 -1
  7. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +7 -1
  8. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -1
  9. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +1 -1
  10. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +7 -1
  11. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +7 -1
  12. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +7 -1
  13. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +87 -21
  14. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +14 -0
  15. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +42 -0
  16. package/bundled/skills/_metadata.json +1 -1
  17. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +43 -3
  18. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +6 -6
  19. package/bundled/skills/feature-pipeline-launcher/SKILL.md +7 -16
  20. package/bundled/skills/feature-workflow/SKILL.md +8 -7
  21. package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +2 -2
  22. package/bundled/skills/prizmkit-deploy/references/database-setup.md +12 -3
  23. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +11 -13
  24. package/bundled/skills/prizmkit-test/SKILL.md +1 -1
  25. package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +1 -1
  26. package/bundled/skills/prizmkit-test/references/examples.md +2 -2
  27. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +3 -2
  28. package/bundled/skills/refactor-workflow/SKILL.md +6 -5
  29. package/package.json +1 -1
@@ -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.113",
3
+ "bundledAt": "2026-07-09T01:22:22.762Z",
4
+ "bundledFrom": "09ad715"
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")),
@@ -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:
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.112",
2
+ "version": "1.1.113",
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.",
@@ -34,6 +34,38 @@ BUG_ID_PATTERN = re.compile(r"^B-\d{3}$")
34
34
  SCHEMA_VERSION = "dev-pipeline-bug-fix-list-v1"
35
35
 
36
36
 
37
+ def _find_dependency_cycle(dep_map, item_ids):
38
+ """Return one dependency cycle as a list of bug IDs, or an empty list."""
39
+ visiting = set()
40
+ visited = set()
41
+ stack = []
42
+
43
+ def visit(node):
44
+ visiting.add(node)
45
+ stack.append(node)
46
+ for dep in dep_map.get(node, []):
47
+ if dep not in item_ids:
48
+ continue
49
+ if dep in visiting:
50
+ start = stack.index(dep)
51
+ return stack[start:] + [dep]
52
+ if dep not in visited:
53
+ cycle = visit(dep)
54
+ if cycle:
55
+ return cycle
56
+ stack.pop()
57
+ visiting.remove(node)
58
+ visited.add(node)
59
+ return []
60
+
61
+ for bug_id in sorted(item_ids):
62
+ if bug_id not in visited:
63
+ cycle = visit(bug_id)
64
+ if cycle:
65
+ return cycle
66
+ return []
67
+
68
+
37
69
  def _err(msg):
38
70
  """Print an error message to stderr."""
39
71
  print("ERROR: {}".format(msg), file=sys.stderr)
@@ -181,15 +213,23 @@ def validate(data, feature_ids=None):
181
213
  for bug in bugs
182
214
  if BUG_ID_PATTERN.match(str(bug.get("id", "")))
183
215
  }
216
+ dep_map = {bug_id: [] for bug_id in known_ids}
184
217
  for i, bug in enumerate(bugs):
185
218
  bug_id = bug.get("id", "")
186
219
  deps = bug.get("dependencies", []) or []
187
220
  if not isinstance(deps, list):
188
221
  continue
189
222
  for dep in deps:
190
- if isinstance(dep, str) and BUG_ID_PATTERN.match(dep) and dep not in known_ids:
191
- errors.append("bugs[{}] ({}): dependency '{}' does not exist".format(
192
- i, bug_id, dep))
223
+ if isinstance(dep, str) and BUG_ID_PATTERN.match(dep):
224
+ if dep not in known_ids:
225
+ errors.append("bugs[{}] ({}): dependency '{}' does not exist".format(
226
+ i, bug_id, dep))
227
+ elif BUG_ID_PATTERN.match(str(bug_id)):
228
+ dep_map.setdefault(bug_id, []).append(dep)
229
+
230
+ cycle = _find_dependency_cycle(dep_map, known_ids)
231
+ if cycle:
232
+ errors.append("Dependency cycle detected: {}".format(" -> ".join(cycle)))
193
233
 
194
234
  return {
195
235
  "valid": len(errors) == 0,
@@ -5,7 +5,7 @@ description: "Launch and manage the bugfix pipeline from within an AI CLI sessio
5
5
 
6
6
  # Bugfix-Pipeline Launcher
7
7
 
8
- Launch the autonomous bug fix pipeline from within an AI CLI conversation. Supports foreground and background execution modes.
8
+ Launch the autonomous bug fix pipeline from within an AI CLI conversation. Only Background daemon mode is fully detached and survives AI CLI session closure; Foreground runs in the current session, and Manual prints commands without launching.
9
9
 
10
10
  ### Execution Mode
11
11
 
@@ -15,7 +15,7 @@ Three execution modes are available. The user chooses one before configuring oth
15
15
  2. **Background daemon** — `python3 ./.prizmkit/dev-pipeline/cli.py daemon bugfix start .prizmkit/plans/bug-fix-list.json`. Runs fully detached, survives AI CLI session closure.
16
16
  3. **Manual** — Display the assembled command(s) only. Do not execute anything. User runs them on their own.
17
17
 
18
- **Background mode traceability**: Daemon mode metadata and logs are written by the Python runtime (`daemon bugfix start/status/logs`). Do not append a separate skill-managed audit log.
18
+ **Background mode traceability**: Daemon mode metadata and logs are written by the Python runtime (`daemon bugfix start/status/logs`). Do not create any extra launcher-managed audit file.
19
19
 
20
20
  ### When to Use
21
21
 
@@ -90,7 +90,6 @@ Detect user intent from their message, then follow the corresponding workflow:
90
90
  data = json.load(f)
91
91
  bugs = data.get('bugs', [])
92
92
  severity_order = {'critical': 0, 'high': 1, 'medium': 2, 'low': 3}
93
- bugs_sorted = sorted(bugs, key=lambda b: (severity_order.get(b.get('severity', 'medium'), 2), b.get('priority', 99)))
94
93
  print(f'Total bugs: {len(bugs)}')
95
94
  sev_counts = {}
96
95
  for b in bugs:
@@ -98,7 +97,7 @@ Detect user intent from their message, then follow the corresponding workflow:
98
97
  sev_counts[s] = sev_counts.get(s, 0) + 1
99
98
  print(f'By severity: {dict(sorted(sev_counts.items(), key=lambda x: severity_order.get(x[0], 2)))}')
100
99
  print()
101
- for b in bugs_sorted:
100
+ for b in bugs:
102
101
  print(f\" {b['id']}: [{b.get('severity','?').upper()}] {b.get('title', 'untitled')}\")
103
102
  "
104
103
  ```
@@ -165,6 +164,7 @@ Detect user intent from their message, then follow the corresponding workflow:
165
164
  - Summarize results: total bugs, fixed, failed, skipped
166
165
  - If all fixed: each bug session has already run `prizmkit-retrospective` internally (structural sync by default; full retrospective when the fix changed interfaces, dependencies, or observable behavior). Ask user what's next.
167
166
  - If some failed: show failed bug IDs and suggest `python3 ./.prizmkit/dev-pipeline/cli.py reset bugfix <B-XXX> --clean --run` for a fresh retry
167
+ - **Browser verification**: Bug sessions with `browser_interaction` perform their own verification attempts during execution. After completion, use `python3 ./.prizmkit/dev-pipeline/cli.py bugfix status .prizmkit/plans/bug-fix-list.json` and per-bug session logs as the source of truth before summarizing browser verification results.
168
168
 
169
169
  **If background daemon**:
170
170
  1. Verify launch:
@@ -264,9 +264,9 @@ Read `${SKILL_DIR}/references/configuration.md` for the full error handling tabl
264
264
  ### Integration Notes
265
265
 
266
266
  - **After bug-planner**: This is the natural next step. When user finishes bug planning and has `.prizmkit/plans/bug-fix-list.json`, suggest launching the bugfix pipeline.
267
- - **Session independence**: In daemon mode, the bugfix pipeline runs completely detached. User can close the AI CLI, open a new session later, and use this skill to check progress or stop the pipeline.
267
+ - **Session independence**: Only Background daemon mode runs detached. Foreground runs in the current AI CLI session, and Manual mode prints commands without launching.
268
268
  - **Single instance per family**: Only one bugfix pipeline can run at a time. Different pipeline families may coexist because they use separate daemon metadata and state directories.
269
- - **Feature pipeline coexistence**: Bugfix and feature pipelines use separate state directories (`.prizmkit/state/bugfix/` vs `.prizmkit/state/features/`), so they can run simultaneously without conflict.
269
+ - **Pipeline coexistence**: Bugfix, feature, and refactor pipelines use separate state directories (`.prizmkit/state/bugfix/`, `.prizmkit/state/features/`, `.prizmkit/state/refactor/`), so all three can run simultaneously without conflict.
270
270
  - **State preservation**: Stopping and restarting the bugfix pipeline resumes from where it left off -- completed bugs are not re-fixed.
271
271
  - **Bug ordering**: Dependencies are active. Runtime selects eligible bugs in stable list order after dependencies are completed; planners should order unrelated bugs by severity/priority before launch.
272
272
  - **Background mode traceability**: Daemon mode metadata/logging is runtime-owned; use `daemon bugfix status` and `daemon bugfix logs`.
@@ -309,22 +309,13 @@ Notes:
309
309
 
310
310
  After pipeline completion, if features have `browser_interaction` fields and the corresponding browser tool (`playwright-cli` or `opencli`) is installed:
311
311
 
312
- If list status may be stale, prefer the runtime status command before deciding which completed features qualify:
312
+ If list status may be stale, use the runtime status command as the source of truth for completion state:
313
313
  `python3 ./.prizmkit/dev-pipeline/cli.py feature status .prizmkit/plans/feature-list.json`.
314
314
 
315
- 1. **Check which features qualify**:
316
- ```bash
317
- python3 -c "
318
- import json
319
- with open('.prizmkit/plans/feature-list.json') as f:
320
- data = json.load(f)
321
- for feat in data.get('features', []):
322
- bi = feat.get('browser_interaction')
323
- if bi and feat.get('status') == 'completed':
324
- tool = bi.get('tool', 'auto') if isinstance(bi, dict) else 'auto'
325
- print(f\" {feat['id']}: {feat.get('title','')} (tool: {tool})\")
326
- " 2>/dev/null
327
- ```
315
+ 1. **Check which completed features have browser verification configured**:
316
+ - Read `browser_interaction` configuration from `.prizmkit/plans/feature-list.json`.
317
+ - Use the runtime status command output to decide which configured features are actually completed.
318
+ - Do not rely on list-file `status` alone when runtime state exists, because daemon/foreground bookkeeping may be newer than the plan file.
328
319
 
329
320
  2. **Ask user**: "N features have browser verification configured. Run browser verification now? (Y/n)"
330
321
 
@@ -352,8 +343,8 @@ Read `${SKILL_DIR}/references/configuration.md` for the full error handling tabl
352
343
  ### Integration Notes
353
344
 
354
345
  - **After feature-planner**: This is the natural next step. When user finishes planning and has `.prizmkit/plans/feature-list.json`, suggest launching the pipeline.
355
- - **Session independence**: The pipeline runs completely detached. User can close the AI CLI session, open a new session later, and use this skill to check progress or stop the pipeline.
346
+ - **Session independence**: Only Background daemon mode runs detached. Foreground runs in the current AI CLI session, and Manual mode prints commands without launching.
356
347
  - **Single instance per family**: Only one feature pipeline can run at a time. Different pipeline families may coexist because they use separate daemon metadata and state directories.
357
- - **Pipeline coexistence**: Feature and bugfix pipelines use separate state directories (`.prizmkit/state/features/` vs `.prizmkit/state/bugfix/`), so they can run simultaneously without conflict.
348
+ - **Pipeline coexistence**: Feature, bugfix, and refactor pipelines use separate state directories (`.prizmkit/state/features/`, `.prizmkit/state/bugfix/`, `.prizmkit/state/refactor/`), so all three can run simultaneously without conflict.
358
349
  - **State preservation**: Stopping and restarting the pipeline resumes from where it left off -- completed features are not re-run.
359
350
  - **HANDOFF**: After pipeline completes all features, each session has already run `prizmkit-retrospective` internally. Ask user what's next.
@@ -87,7 +87,7 @@ For existing-project feature work:
87
87
  Question: How would you like to proceed?
88
88
  Header: Approach
89
89
  Options:
90
- - Implement now (Fast Path) — current session/current workspace via /prizmkit-plan -> /prizmkit-implement -> review/retro/commit
90
+ - Implement now (Fast Path) — current session/current workspace via simplified /prizmkit-plan -> /prizmkit-implement -> conditional test/review/retro -> /prizmkit-committer
91
91
  - Use Pipeline Path — feature-planner creates/reviews feature-list.json, then feature-pipeline-launcher configures execution
92
92
  - Continue clarifying — ask a few more route-level questions before choosing
93
93
  ```
@@ -166,12 +166,13 @@ Do not generate `feature-list.json` inside this workflow; `feature-planner` owns
166
166
 
167
167
  Use Fast Path only after explicit user selection.
168
168
 
169
- 1. Invoke `/prizmkit-plan` with the handoff brief.
169
+ 1. Invoke `/prizmkit-plan` with the handoff brief; use simplified planning for this scoped feature.
170
170
  2. Invoke `/prizmkit-implement` after the plan is ready.
171
- 3. Run `/prizmkit-code-review` as the quality gate.
172
- 4. Run `/prizmkit-retrospective` for feature changes before commit.
173
- 5. Run `/prizmkit-committer` with a `feat(<scope>):` message.
174
- 6. End the workflow after commit; do not call `feature-planner`, `feature-pipeline-launcher`, or monitoring.
171
+ 3. Run `/prizmkit-test` only when risk triggers match: behavior, public interface, data model, security/permission/payment, deployment readiness, or explicit user verification request.
172
+ 4. Run `/prizmkit-code-review` when the user requested review, implementation uncertainty is high, or Full-path-level risk appears during implementation.
173
+ 5. Run `/prizmkit-retrospective` only when structure, interfaces, dependencies, behavior, or durable project knowledge changed.
174
+ 6. Run `/prizmkit-committer` with a `feat(<scope>):` message.
175
+ 7. End the workflow after commit; do not call `feature-planner`, `feature-pipeline-launcher`, or monitoring.
175
176
 
176
177
  If implementation scope grows beyond the Fast Path criteria, pause and ask whether to switch to Pipeline Path.
177
178
 
@@ -236,6 +237,6 @@ For start/stop/logs/retry execution, hand off to `feature-pipeline-launcher`; do
236
237
 
237
238
  ## Output
238
239
 
239
- - Fast Path: `spec.md`, `plan.md`, code changes, review result, Prizm docs sync, and one feature commit.
240
+ - Fast Path: concise `spec.md`, simplified `plan.md`, code changes, conditional test/review evidence when triggered, Prizm docs sync only when durable knowledge changed, and one feature commit.
240
241
  - Pipeline Path: handoff brief, validated `.prizmkit/plans/feature-list.json` from `feature-planner`, and pipeline launch/status handled by `feature-pipeline-launcher`.
241
242
  - Greenfield path: app-level planning artifacts from `app-planner`, optionally followed by feature planning and launch.
@@ -12,7 +12,7 @@ You are the dedicated PrizmKit Reviewer agent (`prizm-dev-team-reviewer`). Revie
12
12
  {architecture decisions and task list from plan.md}
13
13
 
14
14
  ## Scoped Test Report
15
- {summary from artifact_dir/test-report-path.txt and test-report.md, including Scope, Generated / Updated Tests, In-Scope Failures, Baseline Failures, Out of Scope Gaps, Boundary Matrix / Boundary Completion Gate if present, and Verdict. If no scoped report exists for a feature artifact, write "No scoped /prizmkit-test report found (expected for pre-test review)." Treat that absence as informational unless the calling workflow explicitly requires a prior test report.}
15
+ {summary from artifact_dir/test-report-path.txt and test-report.md, including Scope, Generated / Updated Tests, In-Scope Failures, Baseline Failures, Out of Scope Gaps, Boundary Matrix / Boundary Completion Gate if present, and Verdict. If no scoped report exists for a change artifact, write "No scoped /prizmkit-test report found (expected for pre-test review)." Treat that absence as informational unless the calling workflow explicitly requires a prior test report.}
16
16
 
17
17
  ## Workspace Context
18
18
  {git status, unstaged diff summary, staged diff summary, current working directory, expected active checkout git top-level, and new-file paths captured by the Main Agent in Phase 0 from the active checkout. This is your primary review scope — use this context to understand what changed. Request targeted file reads only when you need specific line-level detail for a finding, not to re-discover or re-index the repository. Do not read files that are not in the workspace context unless you need them to verify impact (callers, dependents, shared patterns). Do not switch to a separate worktree or repository copy — the Main Agent has provided everything needed to understand the change set.}
@@ -49,7 +49,7 @@ Evaluate the changes across these dimensions (focus on what's relevant):
49
49
  3. **Completeness**: Files that should have been changed but weren't? Missing tests, types, imports, exports?
50
50
  4. **Consistency**: Do changes follow the project's existing patterns, naming conventions, and code style?
51
51
  5. **Security**: Hardcoded secrets, injection vulnerabilities, unsafe operations.
52
- 6. **Test quality**: If a scoped `/prizmkit-test` report is present, verify the report scope is `this-change`, the artifact dir matches the feature, generated/updated tests assert real behavior rather than mock success or empty assertions, in-scope failures are not mislabeled as baseline failures, baseline failures are genuinely unrelated or pre-existing, out-of-scope gaps were not turned into unrelated test changes, and the report verdict is compatible with proceeding.
52
+ 6. **Test quality**: If a scoped `/prizmkit-test` report is present, verify the report scope is `this-change`, the artifact dir matches the reviewed change, generated/updated tests assert real behavior rather than mock success or empty assertions, in-scope failures are not mislabeled as baseline failures, baseline failures are genuinely unrelated or pre-existing, out-of-scope gaps were not turned into unrelated test changes, and the report verdict is compatible with proceeding.
53
53
  7. **Rules compliance**: (Skip this dimension if no dev rules were provided.) Do changes follow the per-layer dev rules? Flag violations of framework conventions, naming patterns, state management, or other rules defined for that layer.
54
54
 
55
55
  ## Output Format
@@ -10,7 +10,14 @@ During Discovery Step 1 (Project Detection), database drivers were already scann
10
10
  > - **Yes** → proceed with database installation
11
11
  > - **No** → skip, record in deploy.md with note "database must be configured by user"
12
12
 
13
- ## PostgreSQL setup
13
+ ## Secrets file safety
14
+
15
+ Before writing `.prizmkit/deploy/secrets.local.json`:
16
+
17
+ 1. Verify `.gitignore` or an equivalent ignore rule covers `.prizmkit/deploy/secrets.local.json` and any `.prizmkit/deploy/*.local.json` pattern used by the project.
18
+ 2. If the ignore rule is missing, pause and add or request the ignore rule before writing secrets.
19
+ 3. Set the secrets file permissions to current-user read/write only, for example `chmod 600 .prizmkit/deploy/secrets.local.json` on POSIX systems.
20
+ 4. Record only presence metadata in deploy config, docs, reports, and history. Never copy raw passwords, connection strings, passphrases, decryption keys, unsalted hashes, or full env var values into committed files.
14
21
 
15
22
  ```
16
23
  apt-get install -y postgresql postgresql-contrib
@@ -21,7 +28,8 @@ sudo -u postgres psql -c "GRANT ALL ON DATABASE <project> TO <project>;"
21
28
 
22
29
  - Generate a secure random password (32 chars, alphanumeric + symbols).
23
30
  - Write the connection string to `.prizmkit/deploy/secrets.local.json`: `DATABASE_URL=postgresql://<project>:<password>@localhost:5432/<project>`.
24
- - In deploy.md, write: "PostgreSQL installed, connection info recorded in `.prizmkit/deploy/secrets.local.json` (not committed to git)".
31
+ - Set `.prizmkit/deploy/secrets.local.json` permissions to current-user read/write only after writing.
32
+ - In deploy.md, write: "PostgreSQL installed, connection info recorded in `.prizmkit/deploy/secrets.local.json` (gitignored; raw value not committed)".
25
33
 
26
34
  ## MySQL setup (future)
27
35
 
@@ -37,10 +45,11 @@ redis-cli CONFIG REWRITE
37
45
 
38
46
  - Bind to localhost only (modify `/etc/redis/redis.conf` if needed).
39
47
  - Write `REDIS_URL=redis://:<password>@localhost:6379` to `.prizmkit/deploy/secrets.local.json`.
48
+ - Set `.prizmkit/deploy/secrets.local.json` permissions to current-user read/write only after writing.
40
49
 
41
50
  ## Security notes
42
51
 
43
52
  - Never write database passwords to deploy.md, because deploy.md may be committed to git and passwords would leak.
44
- - Passwords stored in `.prizmkit/deploy/secrets.local.json` (gitignored).
53
+ - Passwords stored in `.prizmkit/deploy/secrets.local.json` only after verifying the file is ignored by git and locked down to current-user read/write permissions.
45
54
  - Default: database binds to localhost, no external access, because most indie projects only need local connections.
46
55
  - Record a `"database-setup"` event in deploy history (presence metadata only, no passwords).
@@ -21,8 +21,8 @@ STEPS:
21
21
  - Top-level module M → write .prizmkit/prizm-docs/<M>.prizm (include SUBDIRS section with pointers to sub-module docs)
22
22
  - Sub-module S inside M → write .prizmkit/prizm-docs/<M>/<S>.prizm
23
23
  Each L1 includes MODULE (full relative path), FILES count, RESPONSIBILITY, SUBDIRS with pointers, KEY_FILES (5-10 most important), DEPENDENCIES (imports, imported-by, external), RULES (1-3 most critical only). L1 does NOT include INTERFACES, DATA_FLOW, TRAPS, or DECISIONS (those are L2, generated lazily). Max 4KB each.
24
- 6. Skip L2 docs during init — L2 is created lazily on first file modification or when AI needs deep understanding (ON_DEEP_READ trigger). L2 contains behavioral detail: INTERFACES, DATA_FLOW, TRAPS, DECISIONS, full RULES, domain-specific sections.
25
- 7. Configure UserPromptSubmit hook in platform settings per ${SKILL_DIR}/assets/prizm-docs-format.md.md Section 11.
24
+ 6. Skip L2 docs during init — L2 docs are created after real context exists, not as placeholders. During implementation, if relevant L2 is missing, the implementing skill reads target source files as fallback and proceeds. `/prizmkit-retrospective` creates or updates L2 after the change only when durable structure, behavior, dependencies, interfaces, or TRAPS exist. Explicit `/prizmkit-prizm-docs` repair/rebuild may also create L2 when fixing out-of-band doc drift.
25
+ 7. Configure UserPromptSubmit hook in platform settings per ${SKILL_DIR}/assets/prizm-docs-format.md Section 11.
26
26
  8. Validate all generated docs: size limits (L0 <= 4KB, L1 <= 4KB), pointer resolution (every -> reference resolves), no circular dependencies, KEY: value format compliance, no anti-patterns (prose, code blocks, markdown headers), L1 does not contain INTERFACES/DATA_FLOW/TRAPS/DECISIONS, no CHANGELOG sections/files, no UPDATED/date metadata, no feature/bug/refactor/task/session/run/pipeline/workflow IDs, no branch names, no absolute worktree paths, and no `.prizmkit/specs` / `.prizmkit/dev-pipeline` artifact paths.
27
27
  9. Report summary: modules discovered, L1 docs generated, files excluded, warnings.
28
28
 
@@ -30,16 +30,14 @@ OUTPUT: List of generated files, module count, and validation results.
30
30
 
31
31
  ## Post-Init Behavior
32
32
 
33
- After initialization, L2 docs are created incrementally:
33
+ After initialization, L2 docs are created only when durable context exists:
34
34
 
35
- ON_MODIFY trigger:
36
- - First time AI modifies a file in sub-module S within module M:
37
- IF .prizmkit/prizm-docs/<M>/<S>.prizm does not exist:
38
- AI reads the source files in S, generates L2 doc, then proceeds with modification
39
- - This ensures L2 docs have real depth, written when AI has actual context
35
+ ON_MODIFY behavior:
36
+ - When an AI modifies a file in sub-module S within module M and `.prizmkit/prizm-docs/<M>/<S>.prizm` does not exist, the implementation reads the source files in S as fallback context and proceeds.
37
+ - Do not block implementation only to create a placeholder L2 doc.
38
+ - After the change, run `/prizmkit-retrospective` when structure, interfaces, dependencies, behavior, or durable TRAPS changed; retrospective creates or updates L2 then.
40
39
 
41
- ON_DEEP_READ trigger:
42
- - When AI needs to deeply understand a module but not modify it (e.g., code review, architecture analysis, dependency tracing, explaining complex logic):
43
- IF .prizmkit/prizm-docs/<M>/<S>.prizm does not exist:
44
- AI reads the source files in S, generates L2 doc for future reference
45
- - This ensures L2 docs are available for read-heavy analysis tasks, not just modifications
40
+ ON_DEEP_READ behavior:
41
+ - When an AI needs deep understanding but L2 is absent, read the relevant source files directly as fallback context.
42
+ - Create L2 through `/prizmkit-retrospective` after normal development work, or through explicit `/prizmkit-prizm-docs` repair/rebuild when fixing out-of-band doc drift.
43
+ - Do not create L2 merely because a module was read; L2 should capture durable knowledge, not transient investigation notes.
@@ -100,7 +100,7 @@ Interactive mode options:
100
100
 
101
101
  1. Full project
102
102
  2. Single module
103
- 3. Single feature/spec directory
103
+ 3. Single historical feature/spec directory
104
104
  4. Current change artifact when an artifact directory is available
105
105
 
106
106
  For `scope=this-change`, build the in-scope source set using this priority:
@@ -4,7 +4,7 @@ Use this protocol during `/prizmkit-test` Phase 4 and update it during Phase 5.
4
4
 
5
5
  ## Required Boundary Matrix
6
6
 
7
- Build this matrix before writing tests and update it after generated tests pass or produce `needs-review` findings. In `scope=this-change`, build the matrix only for in-scope feature interfaces/endpoints; unrelated interfaces are recorded under `Out of Scope Gaps` and do not trigger generated tests.
7
+ Build this matrix before writing tests and update it after generated tests pass or produce `needs-review` findings. In `scope=this-change`, build the matrix only for interfaces/endpoints in the reviewed change artifact or changed-file set; unrelated interfaces are recorded under `Out of Scope Gaps` and do not trigger generated tests.
8
8
 
9
9
  | Module | Interface | Service Type | Happy Path | Request Validation | Auth / Permission / Ownership | Domain Invariants | Collection / Pagination | Date / Time | State Transitions | Dependency Failure | Response Contract | N/A Reasons | Final Status |
10
10
  |--------|-----------|--------------|------------|--------------------|-------------------------------|-------------------|-------------------------|-------------|-------------------|-------------------|-------------------|-------------|--------------|
@@ -118,7 +118,7 @@ Do not report `user` as covered just because both endpoints have success tests.
118
118
 
119
119
  **Caller**: `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`
120
120
 
121
- For non-feature changes, use the same command shape with any explicit change artifact directory that contains `spec.md` + `plan.md` and has a changed-files source.
121
+ For non-feature changes, use the same command shape with any explicit change artifact directory that contains `spec.md` + `plan.md` and has a changed-files source. The `{{FEATURE_SLUG}}` path below is a compatibility example for existing feature artifacts; it does not limit `scope=this-change` to feature work.
122
122
 
123
123
  **Expected behavior**:
124
124
  - Reads the change artifact's `spec.md`, `plan.md`, and optional `context-snapshot.md`.
@@ -136,7 +136,7 @@ For non-feature changes, use the same command shape with any explicit change art
136
136
  - Generation Policy: in-scope-only
137
137
 
138
138
  ## Out of Scope Gaps
139
- - payment: missing legacy tests, but this feature did not change payment code.
139
+ - payment: missing legacy tests, but this change did not affect payment code.
140
140
 
141
141
  ## Verdict
142
142
  PASS
@@ -169,7 +169,7 @@ Detect user intent from their message, then follow the corresponding workflow:
169
169
  - No (default) — Use defaults for critic review and failure behavior
170
170
  - Yes — Configure critic review, stop-on-failure, and reasoning effort options
171
171
 
172
- Note: Refactor filter defaults to all refactor items (by priority order). If the user selects "Other" on any option, handle their custom input.
172
+ Note: Refactor filter defaults to all refactor items. Runtime selects eligible refactors in stable list order after dependencies are completed; planners should order unrelated refactors by user priority before launch. If the user selects "Other" on any option, handle their custom input.
173
173
 
174
174
  **If user chose "Yes" to Advanced config**, run the advanced configuration round (a second `AskUserQuestion` round, plus a reasoning-effort follow-up). It applies to a minority of sessions, so the full question set lives in `${SKILL_DIR}/references/configuration.md` → **Advanced Configuration Round**. Default Critic to Off unless refactor items have `priority: "critical"` (in which case default to On).
175
175
 
@@ -225,6 +225,7 @@ Detect user intent from their message, then follow the corresponding workflow:
225
225
  - Summarize results: total refactors, succeeded, failed, skipped
226
226
  - If all succeeded: each refactor session has already run `prizmkit-retrospective` internally. Ask user what's next.
227
227
  - If some failed: show failed refactor IDs and suggest `python3 ./.prizmkit/dev-pipeline/cli.py reset refactor <R-XXX> --clean --run` for a fresh retry
228
+ - **Browser verification**: Refactor sessions with `browser_interaction` perform supplemental UI verification during execution. After completion, use `python3 ./.prizmkit/dev-pipeline/cli.py refactor status .prizmkit/plans/refactor-list.json` and per-refactor session logs as the source of truth before summarizing browser verification results.
228
229
 
229
230
  **If background daemon**:
230
231
  1. Verify launch:
@@ -328,7 +329,7 @@ Read the error-handling table in `${SKILL_DIR}/references/configuration.md` for
328
329
  ### Integration Notes
329
330
 
330
331
  - **After refactor-planner**: This is the natural next step. When user finishes refactor planning and has `.prizmkit/plans/refactor-list.json`, suggest launching the refactor pipeline.
331
- - **Session independence**: The pipeline runs completely detached. User can close the AI CLI session, open a new session later, and use this skill to check progress or stop the pipeline.
332
+ - **Session independence**: Only Background daemon mode runs detached. Foreground runs in the current AI CLI session, and Manual mode prints commands without launching.
332
333
  - **Single instance per family**: Only one refactor pipeline can run at a time. Different pipeline families may coexist because they use separate daemon metadata and state directories.
333
334
  - **Pipeline coexistence**: Refactor pipeline uses `.prizmkit/state/refactor/` separate from `.prizmkit/state/features/` (features) and `.prizmkit/state/bugfix/` (bugs), so all three pipelines can run simultaneously without conflict.
334
335
  - **State preservation**: Stopping and restarting the pipeline resumes from where it left off -- completed refactors are not re-run.
@@ -172,10 +172,11 @@ Use Fast Path only after explicit user selection.
172
172
  1. Invoke `/prizmkit-plan` with the handoff brief and behavior-preservation expectations.
173
173
  2. Invoke `/prizmkit-implement` after the plan is ready.
174
174
  3. Run behavior-preservation checks identified in the plan.
175
- 4. Run `/prizmkit-code-review` as the quality and behavior-preservation gate.
176
- 5. Run `/prizmkit-retrospective` before commit because refactors often change durable structure.
177
- 6. Run `/prizmkit-committer` with a `refactor(<scope>):` message.
178
- 7. End the workflow after commit; do not call `refactor-planner`, `refactor-pipeline-launcher`, or monitoring.
175
+ 4. Run `/prizmkit-test` only when risk triggers match: public contracts, data models, migration behavior, weak behavior-preservation evidence, or explicit user verification request.
176
+ 5. Run `/prizmkit-code-review` when the user requested review, behavior-preservation uncertainty is high, or Full-path-level risk appears during implementation.
177
+ 6. Run `/prizmkit-retrospective` only when structure, interfaces, dependencies, behavior, or durable project knowledge changed.
178
+ 7. Run `/prizmkit-committer` with a `refactor(<scope>):` message.
179
+ 8. End the workflow after commit; do not call `refactor-planner`, `refactor-pipeline-launcher`, or monitoring.
179
180
 
180
181
  If the refactor starts changing behavior or grows beyond Fast Path criteria, pause and ask whether to switch to `feature-workflow` or Pipeline Path.
181
182
 
@@ -241,5 +242,5 @@ For start/stop/logs/retry execution, hand off to `refactor-pipeline-launcher`; d
241
242
 
242
243
  ## Output
243
244
 
244
- - Fast Path: `spec.md`, `plan.md`, behavior-preserving code changes, behavior-check evidence, review result, Prizm docs sync, and one refactor commit.
245
+ - Fast Path: `spec.md`, `plan.md`, behavior-preserving code changes, behavior-check evidence, conditional test/review evidence when triggered, Prizm docs sync only when durable knowledge changed, and one refactor commit.
245
246
  - Pipeline Path: handoff brief, validated `.prizmkit/plans/refactor-list.json` from `refactor-planner`, and pipeline launch/status handled by `refactor-pipeline-launcher`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.1.112",
3
+ "version": "1.1.113",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {