prizmkit 1.1.129 → 1.1.130
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +2 -2
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -2
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +10 -3
- package/bundled/dev-pipeline/scripts/prompt_framework.py +4 -6
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +94 -2
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
package/bundled/VERSION.json
CHANGED
|
@@ -1637,8 +1637,8 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1637
1637
|
effective_resume = "6"
|
|
1638
1638
|
|
|
1639
1639
|
|
|
1640
|
-
# Browser verification
|
|
1641
|
-
#
|
|
1640
|
+
# Browser verification is opt-in through a browser_interaction object and
|
|
1641
|
+
# can always be disabled globally with BROWSER_VERIFY=false.
|
|
1642
1642
|
browser_enabled, browser_tool, browser_verify_steps, browser_blocking = browser_enabled_from_item(feature)
|
|
1643
1643
|
|
|
1644
1644
|
if browser_tool not in ("playwright-cli", "opencli", "auto"):
|
|
@@ -362,7 +362,7 @@ def _bugfix_header(pipeline_mode):
|
|
|
362
362
|
return title + "\n" + desc + "\n"
|
|
363
363
|
|
|
364
364
|
|
|
365
|
-
def assemble_bugfix_sections(pipeline_mode, sections_dir, browser_enabled, manual_gate):
|
|
365
|
+
def assemble_bugfix_sections(pipeline_mode, sections_dir, browser_enabled, manual_gate, browser_tool="auto"):
|
|
366
366
|
sections = [
|
|
367
367
|
("header", _bugfix_header(pipeline_mode)),
|
|
368
368
|
("bugfix-session-context", load_section(sections_dir, "bugfix-session-context.md")),
|
|
@@ -380,7 +380,11 @@ def assemble_bugfix_sections(pipeline_mode, sections_dir, browser_enabled, manua
|
|
|
380
380
|
("bugfix-phase-review", load_section(sections_dir, "bugfix-phase-review.md")),
|
|
381
381
|
])
|
|
382
382
|
if browser_enabled:
|
|
383
|
-
|
|
383
|
+
browser_section_file = {
|
|
384
|
+
"playwright-cli": "phase-browser-verification.md",
|
|
385
|
+
"opencli": "phase-browser-verification-opencli.md",
|
|
386
|
+
}.get(browser_tool, "phase-browser-verification-auto.md")
|
|
387
|
+
sections.append(("phase-browser", load_section(sections_dir, browser_section_file)))
|
|
384
388
|
if manual_gate:
|
|
385
389
|
sections.append(("bugfix-manual-gate", load_section(sections_dir, "bugfix-phase-manual-verification.md")))
|
|
386
390
|
sections.extend([
|
|
@@ -463,6 +467,7 @@ def main():
|
|
|
463
467
|
try:
|
|
464
468
|
sections = assemble_bugfix_sections(
|
|
465
469
|
pipeline_mode, sections_dir, browser_enabled, manual_gate,
|
|
470
|
+
browser_tool=replacements["{{BROWSER_TOOL}}"],
|
|
466
471
|
)
|
|
467
472
|
rendered = render_from_sections(sections, replacements)
|
|
468
473
|
except FileNotFoundError as exc:
|
|
@@ -383,7 +383,7 @@ def _refactor_header(pipeline_mode):
|
|
|
383
383
|
return title + "\n" + desc + "\n"
|
|
384
384
|
|
|
385
385
|
|
|
386
|
-
def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled):
|
|
386
|
+
def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled, browser_tool="auto"):
|
|
387
387
|
sections = [
|
|
388
388
|
("header", _refactor_header(pipeline_mode)),
|
|
389
389
|
("refactor-session-context", load_section(sections_dir, "refactor-session-context.md")),
|
|
@@ -401,7 +401,11 @@ def assemble_refactor_sections(pipeline_mode, sections_dir, browser_enabled):
|
|
|
401
401
|
("refactor-phase-review", load_section(sections_dir, "refactor-phase-review.md")),
|
|
402
402
|
])
|
|
403
403
|
if browser_enabled:
|
|
404
|
-
|
|
404
|
+
browser_section_file = {
|
|
405
|
+
"playwright-cli": "phase-browser-verification.md",
|
|
406
|
+
"opencli": "phase-browser-verification-opencli.md",
|
|
407
|
+
}.get(browser_tool, "phase-browser-verification-auto.md")
|
|
408
|
+
sections.append(("phase-browser", load_section(sections_dir, browser_section_file)))
|
|
405
409
|
sections.extend([
|
|
406
410
|
("refactor-phase-commit-report", load_section(sections_dir, "refactor-phase-commit-report.md")),
|
|
407
411
|
("refactor-session-status", load_section(sections_dir, "refactor-session-status.md")),
|
|
@@ -469,7 +473,10 @@ def main():
|
|
|
469
473
|
sections = []
|
|
470
474
|
if use_sections:
|
|
471
475
|
try:
|
|
472
|
-
sections = assemble_refactor_sections(
|
|
476
|
+
sections = assemble_refactor_sections(
|
|
477
|
+
pipeline_mode, sections_dir, browser_enabled,
|
|
478
|
+
browser_tool=replacements["{{BROWSER_TOOL}}"],
|
|
479
|
+
)
|
|
473
480
|
rendered = render_from_sections(sections, replacements)
|
|
474
481
|
except FileNotFoundError as exc:
|
|
475
482
|
LOGGER.warning("Refactor section assembly failed (%s), falling back to legacy template", exc)
|
|
@@ -327,21 +327,19 @@ def detect_dev_server_port(project_root):
|
|
|
327
327
|
|
|
328
328
|
|
|
329
329
|
def browser_enabled_from_item(item):
|
|
330
|
-
"""Return browser enabled/tool/steps with
|
|
330
|
+
"""Return browser enabled/tool/steps with explicit opt-in semantics."""
|
|
331
331
|
browser_interaction = item.get("browser_interaction") if isinstance(item, dict) else None
|
|
332
332
|
env_value = os.environ.get("BROWSER_VERIFY", "").lower()
|
|
333
333
|
if env_value == "false":
|
|
334
334
|
return False, "auto", "", False
|
|
335
335
|
|
|
336
|
-
enabled =
|
|
336
|
+
enabled = False
|
|
337
337
|
tool = "auto"
|
|
338
338
|
blocking = False
|
|
339
339
|
steps = []
|
|
340
340
|
|
|
341
|
-
if isinstance(browser_interaction,
|
|
342
|
-
enabled =
|
|
343
|
-
elif isinstance(browser_interaction, dict):
|
|
344
|
-
enabled = browser_interaction.get("enabled", True)
|
|
341
|
+
if isinstance(browser_interaction, dict):
|
|
342
|
+
enabled = True
|
|
345
343
|
tool = browser_interaction.get("tool", "auto")
|
|
346
344
|
blocking = bool(browser_interaction.get("blocking", False))
|
|
347
345
|
steps = browser_interaction.get("verify_steps", []) or []
|
|
@@ -1310,7 +1310,7 @@ class TestFeaturePromptUnifiedFullGuidance:
|
|
|
1310
1310
|
assert "### Scoped Feature Test Gate — PrizmKit Test" in prompt
|
|
1311
1311
|
assert "## Test Failure Recovery Protocol" in prompt
|
|
1312
1312
|
assert "Boundary Matrix" in prompt
|
|
1313
|
-
assert "### Browser Verification — MANDATORY" in prompt
|
|
1313
|
+
assert "### Browser Verification — MANDATORY" not in prompt
|
|
1314
1314
|
assert "### TERMINAL STOP — Commit Completed" in prompt
|
|
1315
1315
|
assert "# Dev-Pipeline Session Bootstrap — Tier 1" not in prompt
|
|
1316
1316
|
assert "# Dev-Pipeline Session Bootstrap — Tier 2" not in prompt
|
|
@@ -1420,7 +1420,99 @@ class TestBrowserBlockingPromptPolicy:
|
|
|
1420
1420
|
assert "Failures do NOT block the commit" not in prompt
|
|
1421
1421
|
|
|
1422
1422
|
|
|
1423
|
-
class
|
|
1423
|
+
class TestBrowserOptInPromptPolicy:
|
|
1424
|
+
@staticmethod
|
|
1425
|
+
def _rendered_outputs(tmp_path, browser_interaction=None, env_value=None):
|
|
1426
|
+
previous_env = os.environ.get("BROWSER_VERIFY")
|
|
1427
|
+
if env_value is None:
|
|
1428
|
+
os.environ.pop("BROWSER_VERIFY", None)
|
|
1429
|
+
else:
|
|
1430
|
+
os.environ["BROWSER_VERIFY"] = env_value
|
|
1431
|
+
try:
|
|
1432
|
+
feature_prompt = _render_feature_prompt(
|
|
1433
|
+
tmp_path / "feature", browser_interaction=browser_interaction,
|
|
1434
|
+
)
|
|
1435
|
+
bugfix_prompt = _render_bugfix_prompt(
|
|
1436
|
+
tmp_path / "bugfix",
|
|
1437
|
+
bug_overrides=(
|
|
1438
|
+
{"browser_interaction": browser_interaction}
|
|
1439
|
+
if browser_interaction is not None else None
|
|
1440
|
+
),
|
|
1441
|
+
)
|
|
1442
|
+
refactor_prompt = _render_refactor_prompt(
|
|
1443
|
+
tmp_path / "refactor",
|
|
1444
|
+
refactor_overrides=(
|
|
1445
|
+
{"browser_interaction": browser_interaction}
|
|
1446
|
+
if browser_interaction is not None else None
|
|
1447
|
+
),
|
|
1448
|
+
)
|
|
1449
|
+
return feature_prompt, bugfix_prompt, refactor_prompt
|
|
1450
|
+
finally:
|
|
1451
|
+
if previous_env is None:
|
|
1452
|
+
os.environ.pop("BROWSER_VERIFY", None)
|
|
1453
|
+
else:
|
|
1454
|
+
os.environ["BROWSER_VERIFY"] = previous_env
|
|
1455
|
+
|
|
1456
|
+
@staticmethod
|
|
1457
|
+
def _checkpoint_skills(project_root, family):
|
|
1458
|
+
if family == "feature":
|
|
1459
|
+
pattern = "**/workflow-checkpoint.json"
|
|
1460
|
+
elif family == "bugfix":
|
|
1461
|
+
pattern = "**/bugfix/B-001/workflow-checkpoint.json"
|
|
1462
|
+
else:
|
|
1463
|
+
pattern = "**/refactor/R-001/workflow-checkpoint.json"
|
|
1464
|
+
path = next(project_root.glob(pattern))
|
|
1465
|
+
return [step["skill"] for step in json.loads(path.read_text(encoding="utf-8"))["steps"]]
|
|
1466
|
+
|
|
1467
|
+
def test_omitted_browser_interaction_disables_browser_for_all_families(self, tmp_path):
|
|
1468
|
+
prompts = self._rendered_outputs(tmp_path / "omitted")
|
|
1469
|
+
|
|
1470
|
+
for prompt in prompts:
|
|
1471
|
+
assert "Browser Verification" not in prompt
|
|
1472
|
+
assert "playwright-cli" not in prompt
|
|
1473
|
+
assert "opencli" not in prompt
|
|
1474
|
+
assert "development-server" not in prompt
|
|
1475
|
+
assert "browser-dev-server.pid" not in prompt
|
|
1476
|
+
|
|
1477
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "omitted" / "feature", "feature")
|
|
1478
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "omitted" / "bugfix", "bugfix")
|
|
1479
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "omitted" / "refactor", "refactor")
|
|
1480
|
+
|
|
1481
|
+
def test_explicit_browser_interaction_preserves_configuration_for_all_families(self, tmp_path):
|
|
1482
|
+
browser_interaction = {
|
|
1483
|
+
"tool": "playwright-cli",
|
|
1484
|
+
"verify_steps": ["Open the page", "Submit the form"],
|
|
1485
|
+
}
|
|
1486
|
+
prompts = self._rendered_outputs(tmp_path / "explicit", browser_interaction)
|
|
1487
|
+
|
|
1488
|
+
for prompt in prompts:
|
|
1489
|
+
assert "Browser Verification" in prompt
|
|
1490
|
+
assert "Browser Verification (playwright-cli)" in prompt
|
|
1491
|
+
assert "playwright-cli" in prompt
|
|
1492
|
+
assert "opencli" not in prompt
|
|
1493
|
+
assert "Goal 1: Open the page" in prompt
|
|
1494
|
+
assert "Goal 2: Submit the form" in prompt
|
|
1495
|
+
|
|
1496
|
+
assert "browser-verification" in self._checkpoint_skills(tmp_path / "explicit" / "feature", "feature")
|
|
1497
|
+
assert "browser-verification" in self._checkpoint_skills(tmp_path / "explicit" / "bugfix", "bugfix")
|
|
1498
|
+
assert "browser-verification" in self._checkpoint_skills(tmp_path / "explicit" / "refactor", "refactor")
|
|
1499
|
+
|
|
1500
|
+
def test_global_disable_suppresses_explicit_browser_for_all_families(self, tmp_path):
|
|
1501
|
+
prompts = self._rendered_outputs(
|
|
1502
|
+
tmp_path / "global-disable",
|
|
1503
|
+
{"tool": "opencli", "verify_steps": ["Open the page"]},
|
|
1504
|
+
env_value="false",
|
|
1505
|
+
)
|
|
1506
|
+
|
|
1507
|
+
for prompt in prompts:
|
|
1508
|
+
assert "Browser Verification" not in prompt
|
|
1509
|
+
assert "opencli" not in prompt
|
|
1510
|
+
assert "browser-dev-server.pid" not in prompt
|
|
1511
|
+
|
|
1512
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "global-disable" / "feature", "feature")
|
|
1513
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "global-disable" / "bugfix", "bugfix")
|
|
1514
|
+
assert "browser-verification" not in self._checkpoint_skills(tmp_path / "global-disable" / "refactor", "refactor")
|
|
1515
|
+
|
|
1424
1516
|
def test_fresh_manual_bugfix_prompt_stops_before_commit_phase(self, tmp_path):
|
|
1425
1517
|
prompt = _render_bugfix_prompt(
|
|
1426
1518
|
tmp_path / "fresh-manual-bugfix",
|