prizmkit 1.1.35 → 1.1.36

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 (24) hide show
  1. package/bin/create-prizmkit.js +4 -0
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +66 -18
  4. package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +4 -5
  5. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
  6. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +74 -4
  7. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +84 -15
  8. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +84 -22
  9. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +4 -4
  10. package/bundled/dev-pipeline/templates/feature-list-schema.json +8 -2
  11. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +5 -6
  12. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +153 -0
  13. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +124 -0
  14. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +10 -17
  15. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +11 -18
  16. package/bundled/skills/_metadata.json +1 -1
  17. package/bundled/skills/feature-planner/SKILL.md +6 -5
  18. package/bundled/skills/feature-planner/references/browser-interaction.md +14 -1
  19. package/bundled/skills/prizmkit-code-review/SKILL.md +176 -45
  20. package/package.json +1 -1
  21. package/src/index.js +10 -1
  22. package/src/scaffold.js +52 -3
  23. package/bundled/skills/prizmkit-code-review/rules/dimensions.md +0 -85
  24. package/bundled/skills/prizmkit-code-review/rules/fix-strategy.md +0 -61
@@ -37,6 +37,10 @@ program
37
37
  .option('--no-team', 'Disable multi-agent team mode')
38
38
  .option('--pipeline', 'Install dev-pipeline (default: true)')
39
39
  .option('--no-pipeline', 'Disable dev-pipeline')
40
+ .option('--playwright-cli', 'Install playwright-cli browser tool (default: true)')
41
+ .option('--no-playwright-cli', 'Disable playwright-cli installation')
42
+ .option('--open-cli', 'Install opencli browser tool (default: true)')
43
+ .option('--no-open-cli', 'Disable opencli installation')
40
44
  .option('--rules <preset>', 'Rules preset: recommended, minimal, or none', 'recommended')
41
45
  .option('--ai-cli <command>', 'AI CLI executable command (e.g. cbc, claude, claude-internal)')
42
46
  .option('--external-skills <names>', 'Comma-separated external skill names to install (e.g. find-skills,impeccable)')
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.35",
3
- "bundledAt": "2026-04-16T01:23:04.438Z",
4
- "bundledFrom": "253edf2"
2
+ "frameworkVersion": "1.1.36",
3
+ "bundledAt": "2026-04-18T05:19:19.256Z",
4
+ "bundledFrom": "bee43f6"
5
5
  }
@@ -460,12 +460,14 @@ def process_conditional_blocks(content, resume_phase):
460
460
 
461
461
 
462
462
  def process_mode_blocks(content, pipeline_mode, init_done, critic_enabled=False,
463
- browser_interaction=False):
463
+ browser_interaction=False, browser_tool="auto"):
464
464
  """Process pipeline mode, init, critic, and browser conditional blocks.
465
465
 
466
466
  Keeps the block matching the current mode, removes the others.
467
467
  Handles {{IF_CRITIC_ENABLED}} / {{END_IF_CRITIC_ENABLED}} blocks.
468
468
  Handles {{IF_BROWSER_INTERACTION}} / {{END_IF_BROWSER_INTERACTION}} blocks.
469
+ Handles {{IF_BROWSER_TOOL_PLAYWRIGHT}} / {{IF_BROWSER_TOOL_OPENCLI}} /
470
+ {{IF_BROWSER_TOOL_AUTO}} blocks (nested inside browser interaction block).
469
471
  """
470
472
  # Handle lite/standard/full blocks
471
473
  modes = ["lite", "standard", "full"]
@@ -527,6 +529,29 @@ def process_mode_blocks(content, pipeline_mode, init_done, critic_enabled=False,
527
529
  pattern = re.escape(browser_open) + r".*?" + re.escape(browser_close) + r"\n?"
528
530
  content = re.sub(pattern, "", content, flags=re.DOTALL)
529
531
 
532
+ # Browser tool selection blocks (nested inside browser interaction)
533
+ tool_variants = ["PLAYWRIGHT", "OPENCLI", "AUTO"]
534
+ # Map browser_tool value to the variant tag name
535
+ active_variant = {
536
+ "playwright-cli": "PLAYWRIGHT",
537
+ "opencli": "OPENCLI",
538
+ "auto": "AUTO",
539
+ }.get(browser_tool, "AUTO")
540
+
541
+ for variant in tool_variants:
542
+ tool_open = "{{{{IF_BROWSER_TOOL_{}}}}}".format(variant)
543
+ tool_close = "{{{{END_IF_BROWSER_TOOL_{}}}}}".format(variant)
544
+ if variant == active_variant and browser_interaction:
545
+ # Keep content, remove tags
546
+ content = content.replace(tool_open + "\n", "")
547
+ content = content.replace(tool_open, "")
548
+ content = content.replace(tool_close + "\n", "")
549
+ content = content.replace(tool_close, "")
550
+ else:
551
+ # Remove entire block
552
+ pat = re.escape(tool_open) + r".*?" + re.escape(tool_close) + r"\n?"
553
+ content = re.sub(pat, "", content, flags=re.DOTALL)
554
+
530
555
  return content
531
556
 
532
557
 
@@ -869,7 +894,8 @@ def _tier_reminders(pipeline_mode, critic_enabled=False):
869
894
 
870
895
 
871
896
  def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
872
- critic_enabled, browser_enabled, retry_count=0):
897
+ critic_enabled, browser_enabled, retry_count=0,
898
+ browser_tool="auto"):
873
899
  """Assemble prompt sections based on tier and conditions.
874
900
 
875
901
  Uses Python code for conditional logic instead of regex-based
@@ -1040,11 +1066,18 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
1040
1066
  load_section(sections_dir,
1041
1067
  "phase-review-agent.md")))
1042
1068
 
1043
- # --- Browser Verification (conditional) ---
1069
+ # --- Browser Verification (conditional, tool-aware) ---
1044
1070
  if browser_enabled:
1071
+ if browser_tool == "opencli":
1072
+ browser_section_file = "phase-browser-verification-opencli.md"
1073
+ elif browser_tool == "playwright-cli":
1074
+ browser_section_file = "phase-browser-verification.md"
1075
+ else:
1076
+ # "auto" or unknown → let AI choose at runtime
1077
+ browser_section_file = "phase-browser-verification-auto.md"
1045
1078
  sections.append(("phase-browser",
1046
1079
  load_section(sections_dir,
1047
- "phase-browser-verification.md")))
1080
+ browser_section_file)))
1048
1081
 
1049
1082
  # --- Deploy Verification ---
1050
1083
  sections.append(("phase-deploy",
@@ -1289,26 +1322,37 @@ def build_replacements(args, feature, features, global_context, script_dir):
1289
1322
  )
1290
1323
  critic_enabled = False
1291
1324
 
1292
- # Browser interaction - extract from feature if present and playwright-cli available
1325
+ # Browser interaction - extract from feature if present
1293
1326
  browser_interaction = feature.get("browser_interaction")
1294
1327
  browser_enabled = False
1295
1328
  browser_verify_steps = ""
1329
+ browser_tool = "auto" # default: AI chooses at runtime
1296
1330
 
1297
1331
  browser_verify_env = os.environ.get("BROWSER_VERIFY", "").lower()
1298
1332
  if browser_verify_env == "false":
1299
1333
  browser_interaction = None
1300
1334
 
1301
- if browser_interaction and isinstance(browser_interaction, dict):
1335
+ if browser_interaction and isinstance(browser_interaction, bool):
1336
+ # Simple boolean: browser verification enabled, no specific goals
1337
+ browser_enabled = True
1338
+ browser_tool = "auto"
1339
+ browser_verify_steps = (
1340
+ " # (no specific verify goals — explore the app and "
1341
+ "verify the feature works as expected)")
1342
+ elif browser_interaction and isinstance(browser_interaction, dict):
1343
+ # Extract tool preference (playwright-cli / opencli / auto)
1344
+ browser_tool = browser_interaction.get("tool", "auto")
1345
+ if browser_tool not in ("playwright-cli", "opencli", "auto"):
1346
+ LOGGER.warning(
1347
+ "Unknown browser_interaction.tool '%s', defaulting to 'auto'",
1348
+ browser_tool,
1349
+ )
1350
+ browser_tool = "auto"
1351
+
1302
1352
  # browser_interaction only needs verify_steps — AI auto-detects
1303
1353
  # dev server command, URL, and port from project config
1304
1354
  steps = browser_interaction.get("verify_steps", [])
1305
- if isinstance(browser_interaction, bool) and browser_interaction:
1306
- # Simple boolean: browser verification enabled, no specific goals
1307
- browser_enabled = True
1308
- browser_verify_steps = (
1309
- " # (no specific verify goals — explore the app and "
1310
- "verify the feature works as expected)")
1311
- elif steps:
1355
+ if steps:
1312
1356
  browser_enabled = True
1313
1357
  browser_verify_steps = "\n".join(
1314
1358
  " # Goal {}: {}".format(i + 1, step)
@@ -1404,6 +1448,7 @@ def build_replacements(args, feature, features, global_context, script_dir):
1404
1448
  "{{HAS_SPEC}}": "true" if artifacts["has_spec"] else "false",
1405
1449
  "{{HAS_PLAN}}": "true" if artifacts["has_plan"] else "false",
1406
1450
  "{{BROWSER_VERIFY_STEPS}}": browser_verify_steps,
1451
+ "{{BROWSER_TOOL}}": browser_tool,
1407
1452
  "{{AC_CHECKLIST}}": format_ac_checklist(
1408
1453
  feature.get("acceptance_criteria", [])
1409
1454
  ),
@@ -1414,10 +1459,11 @@ def build_replacements(args, feature, features, global_context, script_dir):
1414
1459
  "{{DEV_URL}}": dev_url,
1415
1460
  }
1416
1461
 
1417
- return replacements, effective_resume, browser_enabled
1462
+ return replacements, effective_resume, browser_enabled, browser_tool
1418
1463
 
1419
1464
 
1420
- def render_template(template_content, replacements, resume_phase, browser_enabled=False):
1465
+ def render_template(template_content, replacements, resume_phase,
1466
+ browser_enabled=False, browser_tool="auto"):
1421
1467
  """Render the template by processing conditionals and replacing placeholders."""
1422
1468
  # Step 1: Process fresh_start/resume conditional blocks
1423
1469
  content = process_conditional_blocks(template_content, resume_phase)
@@ -1427,7 +1473,7 @@ def render_template(template_content, replacements, resume_phase, browser_enable
1427
1473
  init_done = replacements.get("{{INIT_DONE}}", "false") == "true"
1428
1474
  critic_enabled = replacements.get("{{CRITIC_ENABLED}}", "false") == "true"
1429
1475
  content = process_mode_blocks(content, pipeline_mode, init_done, critic_enabled,
1430
- browser_enabled)
1476
+ browser_enabled, browser_tool)
1431
1477
 
1432
1478
  # Step 3: Replace all {{PLACEHOLDER}} variables (two passes for nested
1433
1479
  # agent prompt templates that may contain their own placeholders)
@@ -1489,7 +1535,7 @@ def main():
1489
1535
  global_context = {}
1490
1536
 
1491
1537
  # Build replacements (shared by both code paths)
1492
- replacements, effective_resume, browser_enabled = build_replacements(
1538
+ replacements, effective_resume, browser_enabled, browser_tool = build_replacements(
1493
1539
  args, feature, features, global_context, script_dir
1494
1540
  )
1495
1541
 
@@ -1514,6 +1560,7 @@ def main():
1514
1560
  pipeline_mode, sections_dir, init_done, is_resume,
1515
1561
  critic_enabled, browser_enabled,
1516
1562
  retry_count=int(args.retry_count),
1563
+ browser_tool=browser_tool,
1517
1564
  )
1518
1565
  rendered = render_from_sections(sections, replacements)
1519
1566
  except FileNotFoundError as exc:
@@ -1552,7 +1599,8 @@ def main():
1552
1599
  emit_failure("Template error: {}".format(err))
1553
1600
 
1554
1601
  rendered = render_template(
1555
- template_content, replacements, effective_resume, browser_enabled
1602
+ template_content, replacements, effective_resume, browser_enabled,
1603
+ browser_tool
1556
1604
  )
1557
1605
 
1558
1606
  # ── Validate rendered output ───────────────────────────────────────
@@ -1,8 +1,7 @@
1
1
  "Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
2
2
  1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` (if it exists) for goals and acceptance criteria; if spec.md does not exist, read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` Section 1 instead
3
3
  2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
4
- 3. Read `.prizm-docs/root.prizm` and relevant L1/L2 docs for RULES, PATTERNS, TRAPS
5
- 4. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/: Phase 1 diagnostic review across all applicable dimensions, then Phase 2 fix strategy for any findings. Read ONLY files referenced in completed plan.md tasks for diagnosis; MAY read additional files for impact analysis.
6
- 5. Run the full test suite using `{{TEST_CMD}}`. When running tests: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details — do NOT re-run the suite multiple times. Write and execute integration tests covering all goals from spec.md.
7
- 6. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
8
- Report: number of findings found, or 'no findings' if clean."
4
+ 3. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/. The skill will run its internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and write review-report.md.
5
+ 4. Run the full test suite using `{{TEST_CMD}}`. When running tests: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details do NOT re-run the suite multiple times.
6
+ 5. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
7
+ Report: verdict (PASS/NEEDS_FIXES), number of rounds, findings fixed/rejected."
@@ -32,7 +32,7 @@ Infer what needs to be done from the feature context above and follow the standa
32
32
 
33
33
  4. **Test**: Run the project test suite to verify all tests pass with no regressions.
34
34
 
35
- 5. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to review changes against the spec. If findings exist, fix them and re-review (max 2 rounds).
35
+ 5. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to review and auto-fix changes against the spec (internal review-fix loop, max 3 rounds).
36
36
 
37
37
  6. **Retrospective**: Run `/prizmkit-retrospective` to sync `.prizm-docs/` with code changes.
38
38
 
@@ -164,9 +164,14 @@ When tests fail, use convergence recovery — keep fixing while progress is bein
164
164
 
165
165
 
166
166
  {{IF_BROWSER_INTERACTION}}
167
- ### Phase 3.5: Browser Verification (playwright-cli) — MANDATORY
167
+ ### Phase 3.5: Browser Verification — MANDATORY
168
168
 
169
- You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
169
+ You MUST execute this phase. Do NOT skip it.
170
+
171
+ **Browser Tool**: {{BROWSER_TOOL}}
172
+
173
+ {{IF_BROWSER_TOOL_PLAYWRIGHT}}
174
+ **Using: playwright-cli**
170
175
 
171
176
  **CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
172
177
  - You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
@@ -253,16 +258,81 @@ Construct your verification workflow based on: (1) the playwright-cli skill docu
253
258
  1. Close the playwright-cli browser: `playwright-cli close`
254
259
  2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
255
260
  3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
261
+ {{END_IF_BROWSER_TOOL_PLAYWRIGHT}}
262
+ {{IF_BROWSER_TOOL_OPENCLI}}
263
+ **Using: opencli** (reuses Chrome logged-in sessions)
264
+
265
+ **CRITICAL CONSTRAINT — opencli browser ONLY**:
266
+ - You MUST use `opencli browser` for ALL browser interactions in this phase
267
+ - All browser actions go through `opencli browser <command>` in the Bash tool
268
+
269
+ **Step 0 — OpenCLI Readiness Check (BLOCKING)**:
270
+
271
+ 0a. Check if `opencli` is installed:
272
+ ```bash
273
+ which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
274
+ ```
275
+ If `NOT_INSTALLED`: `npm install -g @jackwener/opencli@latest`. If installation fails, log `## Browser Verification: SKIPPED — opencli installation failed` and proceed.
276
+
277
+ 0b. Verify Browser Bridge: `opencli doctor`. If fails, log skip and proceed.
278
+
279
+ 0c. Learn usage: `opencli browser --help 2>/dev/null || opencli --help`
280
+
281
+ **Step 1 — Start Dev Server**: (same port detection as playwright path)
282
+ ```bash
283
+ DEV_PORT={{DEV_PORT}}
284
+ if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
285
+ DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')" 2>/dev/null)
286
+ DEV_PORT=${DEV_PORT:-3000}
287
+ fi
288
+ ```
289
+ Start server, wait for ready, then: `opencli browser open http://localhost:$DEV_PORT && opencli browser state`
290
+
291
+ **Step 2 — Verification**:
292
+
293
+ Use `opencli browser state` to discover elements with `[N]` indices, then verify:
294
+ {{BROWSER_VERIFY_STEPS}}
295
+
296
+ Chain commands: `opencli browser click <N> && opencli browser wait time 1 && opencli browser state`
297
+
298
+ **Step 3 — Cleanup**:
299
+ 1. `opencli browser close`
300
+ 2. `kill $DEV_SERVER_PID 2>/dev/null || true`
301
+ 3. `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
302
+ {{END_IF_BROWSER_TOOL_OPENCLI}}
303
+ {{IF_BROWSER_TOOL_AUTO}}
304
+ **Tool Selection**: Choose the best browser tool at runtime.
305
+
306
+ **Step 0 — Detect available tools**:
307
+ ```bash
308
+ echo "=== playwright-cli ===" && which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
309
+ echo "=== opencli ===" && which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
310
+ ```
311
+ If opencli installed: `opencli doctor 2>/dev/null || echo "OPENCLI_BRIDGE_FAILED"`
312
+
313
+ **Decision table**:
314
+ | Condition | Tool |
315
+ |-----------|------|
316
+ | Only playwright-cli available | playwright-cli |
317
+ | Only opencli available (doctor passes) | opencli |
318
+ | Both — local dev server, forms, components | playwright-cli |
319
+ | Both — needs real login state (OAuth/SSO) | opencli |
320
+ | Both — third-party integration verification | opencli |
321
+ | Neither available | Install playwright-cli as default |
322
+
323
+ Then follow the corresponding tool's workflow above (Steps 1-3).
324
+ {{END_IF_BROWSER_TOOL_AUTO}}
256
325
 
257
326
  **Step 4 — Reporting**:
258
327
 
259
328
  Append results to `context-snapshot.md`:
260
329
  ```
261
330
  ## Browser Verification
331
+ Tool: <playwright-cli or opencli>
262
332
  URL: http://localhost:$DEV_PORT
263
333
  Dev Server Command: <actual command used>
264
- playwright-cli version: <version>
265
- Steps executed: [list of playwright-cli commands used]
334
+ Tool version: <version>
335
+ Steps executed: [list of commands used]
266
336
  Screenshot: [path]
267
337
  Result: PASS / FAIL (reason)
268
338
  Server cleanup: confirmed
@@ -263,31 +263,35 @@ Prompt:
263
263
  > "Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
264
264
  > 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` for goals and acceptance criteria
265
265
  > 2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
266
- > 3. Read `.prizm-docs/root.prizm` and relevant L1/L2 docs for RULES, PATTERNS, TRAPS
267
- > 4. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/: Phase 1 diagnostic review across all applicable dimensions, then Phase 2 fix strategy formulation for any findings. Read ONLY files referenced in completed plan.md tasks for diagnosis; MAY read additional files for impact analysis.
268
- > 5. Run the full test suite using `{{TEST_CMD}}`. When running: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep the file for details — do NOT re-run the suite multiple times. Write and execute integration tests covering all goals.
269
- > 6. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
270
- > Report: number of findings found, or 'no findings' if clean."
266
+ > 3. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/. The skill runs an internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and writes review-report.md.
267
+ > 4. Run the full test suite using `{{TEST_CMD}}`. When running: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep the file for details do NOT re-run the suite multiple times.
268
+ > 5. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
269
+ > Report: verdict (PASS/NEEDS_FIXES), number of rounds, findings fixed/rejected."
271
270
 
272
271
  Wait for Reviewer to return.
273
272
 
274
273
  **Gate Check — Review Report**:
275
274
  After Reviewer agent returns, verify the review report was written:
276
275
  ```bash
277
- grep -q "## Findings" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "GATE:PASS" || echo "GATE:MISSING"
276
+ grep -q "## Verdict" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "GATE:PASS" || echo "GATE:MISSING"
278
277
  ```
279
- If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review-report.md to .prizmkit/specs/{{FEATURE_SLUG}}/ with findings."
278
+ If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review-report.md to .prizmkit/specs/{{FEATURE_SLUG}}/."
280
279
 
281
- **Verdict decision** (L4 responsibility): Read review-report.md findings count. If findings exist → NEEDS_FIXES. If no findings → PASS.
280
+ Read `review-report.md` and check the Verdict:
281
+ - `PASS` → proceed to next phase
282
+ - `NEEDS_FIXES` → the skill exhausted its max rounds; log the remaining findings and proceed
282
283
 
283
- - If NEEDS_FIXES: spawn Dev to fix (Dev reads Fix Instructions in review-report.md), re-run Review (max 3 rounds)
284
-
285
- **CP-3**: Tests pass, no unresolved findings.
284
+ **CP-3**: Tests pass, review complete.
286
285
 
287
286
  {{IF_BROWSER_INTERACTION}}
288
- ### Phase 5.5: Browser Verification (playwright-cli) — MANDATORY
287
+ ### Phase 5.5: Browser Verification — MANDATORY
288
+
289
+ You MUST execute this phase. Do NOT skip it.
289
290
 
290
- You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
291
+ **Browser Tool**: {{BROWSER_TOOL}}
292
+
293
+ {{IF_BROWSER_TOOL_PLAYWRIGHT}}
294
+ **Using: playwright-cli**
291
295
 
292
296
  **CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
293
297
  - You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
@@ -374,16 +378,81 @@ Construct your verification workflow based on: (1) the playwright-cli skill docu
374
378
  1. Close the playwright-cli browser: `playwright-cli close`
375
379
  2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
376
380
  3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
381
+ {{END_IF_BROWSER_TOOL_PLAYWRIGHT}}
382
+ {{IF_BROWSER_TOOL_OPENCLI}}
383
+ **Using: opencli** (reuses Chrome logged-in sessions)
384
+
385
+ **CRITICAL CONSTRAINT — opencli browser ONLY**:
386
+ - You MUST use `opencli browser` for ALL browser interactions in this phase
387
+ - All browser actions go through `opencli browser <command>` in the Bash tool
388
+
389
+ **Step 0 — OpenCLI Readiness Check (BLOCKING)**:
390
+
391
+ 0a. Check if `opencli` is installed:
392
+ ```bash
393
+ which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
394
+ ```
395
+ If `NOT_INSTALLED`: `npm install -g @jackwener/opencli@latest`. If installation fails, log `## Browser Verification: SKIPPED — opencli installation failed` and proceed.
396
+
397
+ 0b. Verify Browser Bridge: `opencli doctor`. If fails, log skip and proceed.
398
+
399
+ 0c. Learn usage: `opencli browser --help 2>/dev/null || opencli --help`
400
+
401
+ **Step 1 — Start Dev Server**: (same port detection as playwright path)
402
+ ```bash
403
+ DEV_PORT={{DEV_PORT}}
404
+ if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
405
+ DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')" 2>/dev/null)
406
+ DEV_PORT=${DEV_PORT:-3000}
407
+ fi
408
+ ```
409
+ Start server, wait for ready, then: `opencli browser open http://localhost:$DEV_PORT && opencli browser state`
410
+
411
+ **Step 2 — Verification**:
412
+
413
+ Use `opencli browser state` to discover elements with `[N]` indices, then verify:
414
+ {{BROWSER_VERIFY_STEPS}}
415
+
416
+ Chain commands: `opencli browser click <N> && opencli browser wait time 1 && opencli browser state`
417
+
418
+ **Step 3 — Cleanup**:
419
+ 1. `opencli browser close`
420
+ 2. `kill $DEV_SERVER_PID 2>/dev/null || true`
421
+ 3. `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
422
+ {{END_IF_BROWSER_TOOL_OPENCLI}}
423
+ {{IF_BROWSER_TOOL_AUTO}}
424
+ **Tool Selection**: Choose the best browser tool at runtime.
425
+
426
+ **Step 0 — Detect available tools**:
427
+ ```bash
428
+ echo "=== playwright-cli ===" && which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
429
+ echo "=== opencli ===" && which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
430
+ ```
431
+ If opencli installed: `opencli doctor 2>/dev/null || echo "OPENCLI_BRIDGE_FAILED"`
432
+
433
+ **Decision table**:
434
+ | Condition | Tool |
435
+ |-----------|------|
436
+ | Only playwright-cli available | playwright-cli |
437
+ | Only opencli available (doctor passes) | opencli |
438
+ | Both — local dev server, forms, components | playwright-cli |
439
+ | Both — needs real login state (OAuth/SSO) | opencli |
440
+ | Both — third-party integration verification | opencli |
441
+ | Neither available | Install playwright-cli as default |
442
+
443
+ Then follow the corresponding tool's workflow above (Steps 1-3).
444
+ {{END_IF_BROWSER_TOOL_AUTO}}
377
445
 
378
446
  **Step 4 — Reporting**:
379
447
 
380
448
  Append results to `context-snapshot.md`:
381
449
  ```
382
450
  ## Browser Verification
451
+ Tool: <playwright-cli or opencli>
383
452
  URL: http://localhost:$DEV_PORT
384
453
  Dev Server Command: <actual command used>
385
- playwright-cli version: <version>
386
- Steps executed: [list of playwright-cli commands used]
454
+ Tool version: <version>
455
+ Steps executed: [list of commands used]
387
456
  Screenshot: [path]
388
457
  Result: PASS / FAIL (reason)
389
458
  Server cleanup: confirmed
@@ -328,38 +328,35 @@ Prompt:
328
328
  > "Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
329
329
  > 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` for goals and acceptance criteria
330
330
  > 2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
331
- > 3. Read `.prizm-docs/root.prizm` and relevant L1/L2 docs for RULES, PATTERNS, TRAPS
332
- > 4. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/: Phase 1 diagnostic review across all applicable dimensions, then Phase 2 fix strategy formulation for any findings. Read ONLY files referenced in completed plan.md tasks for diagnosis; MAY read additional files for impact analysis.
333
- > 5. Run the full test suite using `{{TEST_CMD}}`. When running tests: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details — do NOT re-run the suite multiple times. Write and execute integration tests covering all goals from spec.md.
334
- > 6. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
335
- > Report: number of findings found, or 'no findings' if clean."
331
+ > 3. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/. The skill runs an internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and writes review-report.md.
332
+ > 4. Run the full test suite using `{{TEST_CMD}}`. When running tests: `({{TEST_CMD}}) 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details do NOT re-run the suite multiple times.
333
+ > 5. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
334
+ > Report: verdict (PASS/NEEDS_FIXES), number of rounds, findings fixed/rejected."
336
335
 
337
336
  Wait for Reviewer to return.
338
337
 
339
338
  **Gate Check — Review Report**:
340
339
  After Reviewer agent returns, verify the review report was written:
341
340
  ```bash
342
- grep -q "## Findings" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "GATE:PASS" || echo "GATE:MISSING"
341
+ grep -q "## Verdict" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "GATE:PASS" || echo "GATE:MISSING"
343
342
  ```
344
- If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review-report.md to .prizmkit/specs/{{FEATURE_SLUG}}/ with findings."
343
+ If GATE:MISSING — send message to Reviewer (re-spawn if needed): "Write review-report.md to .prizmkit/specs/{{FEATURE_SLUG}}/."
345
344
 
346
- **Verdict decision** (L4 responsibility): Read review-report.md findings count. If findings exist → NEEDS_FIXES. If no findings → PASS.
345
+ Read `review-report.md` and check the Verdict:
346
+ - `PASS` → proceed to next phase
347
+ - `NEEDS_FIXES` → the skill exhausted its max rounds; log the remaining findings and proceed
347
348
 
348
- - If NEEDS_FIXES: spawn Dev to fix with this prompt:
349
- > "Read {{DEV_SUBAGENT_PATH}}. Fix issues for feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
350
- > 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/review-report.md` — contains structured Fix Instructions with exact steps.
351
- > 2. Follow Fix Instructions in order (respect Depends On / Blocks dependencies). Each finding has: Root Cause, Fix Strategy, Code Guidance, and Verification criteria.
352
- > 3. After each fix, run the Verification command listed in that finding to confirm it works.
353
- > 4. Run `{{TEST_CMD}}` to verify no regressions.
354
- > 5. Do NOT execute any git commands."
355
- Then re-run Review (max 3 rounds).
356
-
357
- **CP-3**: Integration tests pass, no unresolved findings.
349
+ **CP-3**: Integration tests pass, review complete.
358
350
 
359
351
  {{IF_BROWSER_INTERACTION}}
360
- ### Phase 5.5: Browser Verification (playwright-cli) — MANDATORY
352
+ ### Phase 5.5: Browser Verification — MANDATORY
353
+
354
+ You MUST execute this phase. Do NOT skip it.
361
355
 
362
- You MUST execute this phase. Do NOT skip it. Do NOT mark it as completed without actually running playwright-cli.
356
+ **Browser Tool**: {{BROWSER_TOOL}}
357
+
358
+ {{IF_BROWSER_TOOL_PLAYWRIGHT}}
359
+ **Using: playwright-cli**
363
360
 
364
361
  **CRITICAL CONSTRAINT — playwright-cli ONLY, NO Playwright MCP**:
365
362
  - You MUST use `playwright-cli` (the CLI tool) for ALL browser interactions in this phase
@@ -446,16 +443,81 @@ Construct your verification workflow based on: (1) the playwright-cli skill docu
446
443
  1. Close the playwright-cli browser: `playwright-cli close`
447
444
  2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
448
445
  3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
446
+ {{END_IF_BROWSER_TOOL_PLAYWRIGHT}}
447
+ {{IF_BROWSER_TOOL_OPENCLI}}
448
+ **Using: opencli** (reuses Chrome logged-in sessions)
449
+
450
+ **CRITICAL CONSTRAINT — opencli browser ONLY**:
451
+ - You MUST use `opencli browser` for ALL browser interactions in this phase
452
+ - All browser actions go through `opencli browser <command>` in the Bash tool
453
+
454
+ **Step 0 — OpenCLI Readiness Check (BLOCKING)**:
455
+
456
+ 0a. Check if `opencli` is installed:
457
+ ```bash
458
+ which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
459
+ ```
460
+ If `NOT_INSTALLED`: `npm install -g @jackwener/opencli@latest`. If installation fails, log `## Browser Verification: SKIPPED — opencli installation failed` and proceed.
461
+
462
+ 0b. Verify Browser Bridge: `opencli doctor`. If fails, log skip and proceed.
463
+
464
+ 0c. Learn usage: `opencli browser --help 2>/dev/null || opencli --help`
465
+
466
+ **Step 1 — Start Dev Server**: (same port detection as playwright path)
467
+ ```bash
468
+ DEV_PORT={{DEV_PORT}}
469
+ if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
470
+ DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')" 2>/dev/null)
471
+ DEV_PORT=${DEV_PORT:-3000}
472
+ fi
473
+ ```
474
+ Start server, wait for ready, then: `opencli browser open http://localhost:$DEV_PORT && opencli browser state`
475
+
476
+ **Step 2 — Verification**:
477
+
478
+ Use `opencli browser state` to discover elements with `[N]` indices, then verify:
479
+ {{BROWSER_VERIFY_STEPS}}
480
+
481
+ Chain commands: `opencli browser click <N> && opencli browser wait time 1 && opencli browser state`
482
+
483
+ **Step 3 — Cleanup**:
484
+ 1. `opencli browser close`
485
+ 2. `kill $DEV_SERVER_PID 2>/dev/null || true`
486
+ 3. `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
487
+ {{END_IF_BROWSER_TOOL_OPENCLI}}
488
+ {{IF_BROWSER_TOOL_AUTO}}
489
+ **Tool Selection**: Choose the best browser tool at runtime.
490
+
491
+ **Step 0 — Detect available tools**:
492
+ ```bash
493
+ echo "=== playwright-cli ===" && which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
494
+ echo "=== opencli ===" && which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
495
+ ```
496
+ If opencli installed: `opencli doctor 2>/dev/null || echo "OPENCLI_BRIDGE_FAILED"`
497
+
498
+ **Decision table**:
499
+ | Condition | Tool |
500
+ |-----------|------|
501
+ | Only playwright-cli available | playwright-cli |
502
+ | Only opencli available (doctor passes) | opencli |
503
+ | Both — local dev server, forms, components | playwright-cli |
504
+ | Both — needs real login state (OAuth/SSO) | opencli |
505
+ | Both — third-party integration verification | opencli |
506
+ | Neither available | Install playwright-cli as default |
507
+
508
+ Then follow the corresponding tool's workflow above (Steps 1-3).
509
+ {{END_IF_BROWSER_TOOL_AUTO}}
449
510
 
450
511
  **Step 4 — Reporting**:
451
512
 
452
513
  Append results to `context-snapshot.md`:
453
514
  ```
454
515
  ## Browser Verification
516
+ Tool: <playwright-cli or opencli>
455
517
  URL: http://localhost:$DEV_PORT
456
518
  Dev Server Command: <actual command used>
457
- playwright-cli version: <version>
458
- Steps executed: [list of playwright-cli commands used]
519
+ Tool version: <version>
520
+ Steps executed: [list of commands used]
459
521
  Screenshot: [path]
460
522
  Result: PASS / FAIL (reason)
461
523
  Server cleanup: confirmed
@@ -154,11 +154,11 @@ After implement completes, verify:
154
154
  If `FAST_PATH=true` (≤ 2 tasks, obvious root cause), skip this phase entirely.
155
155
 
156
156
  Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/bugfix/{{BUG_ID}}/`:
157
- - Reviews changes against spec.md
158
- - If NEEDS_FIXES: fix the issues and re-run review (max 3 review rounds)
159
- - If PASS or PASS_WITH_WARNINGS: proceed
157
+ - The skill runs an internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and writes review-report.md
158
+ - If PASS: proceed
159
+ - If NEEDS_FIXES: the skill exhausted its max rounds; log remaining findings and proceed
160
160
 
161
- **CP-3**: Code review passes, all tests green.
161
+ **CP-3**: Code review complete, all tests green.
162
162
 
163
163
  **Checkpoint update**: Set step `prizmkit-code-review` to `"completed"`.
164
164
 
@@ -172,11 +172,17 @@
172
172
  },
173
173
  "browser_interaction": {
174
174
  "type": "object",
175
- "description": "Browser verification config for features with UI. Requires playwright-cli. AI auto-detects dev server command, URL, and port from project config at runtime.",
175
+ "description": "Browser verification config for features with UI. Supports playwright-cli and opencli. AI auto-detects dev server command, URL, and port from project config at runtime.",
176
176
  "properties": {
177
+ "tool": {
178
+ "type": "string",
179
+ "enum": ["playwright-cli", "opencli", "auto"],
180
+ "default": "auto",
181
+ "description": "Browser tool to use. 'auto' (default) = AI chooses at runtime. 'playwright-cli' = local dev server verification in isolated browser. 'opencli' = reuses Chrome logged-in session, ideal for verifying third-party integrations or OAuth flows."
182
+ },
177
183
  "verify_steps": {
178
184
  "type": "array",
179
- "description": "Verification goals describing WHAT to verify (not HOW). AI decides concrete playwright-cli actions at runtime based on actual code and snapshot. If omitted, AI explores the app and verifies the feature works.",
185
+ "description": "Verification goals describing WHAT to verify (not HOW). AI decides concrete browser tool actions at runtime based on actual code and snapshot. If omitted, AI explores the app and verifies the feature works.",
180
186
  "items": {
181
187
  "type": "string"
182
188
  }