prizmkit 1.1.156 → 1.1.160
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/adapters/codebuddy/settings-adapter.js +76 -25
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +9 -2
- package/bundled/dev-pipeline/prizmkit_runtime/reset.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +20 -11
- package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +42 -15
- package/bundled/dev-pipeline/scripts/update-feature-status.py +7 -0
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +1 -1
- package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +6 -6
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +4 -3
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +2 -2
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +2 -2
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +115 -4
- package/bundled/dev-pipeline/tests/test_reset_modes.py +137 -0
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +68 -13
- package/bundled/dev-pipeline/tests/test_unified_cli.py +12 -7
- package/bundled/rules/prizm/prizm-commit-workflow.md +7 -7
- package/bundled/rules/prizm/prizm-documentation.md +24 -65
- package/bundled/rules/prizm/prizm-progressive-loading.md +9 -8
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/prizmkit/SKILL.md +1 -13
- package/bundled/skills/prizmkit-code-review/SKILL.md +29 -10
- package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +5 -4
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +15 -0
- package/bundled/skills/prizmkit-code-review/scripts/render_review_report.py +61 -0
- package/bundled/skills/prizmkit-committer/SKILL.md +50 -38
- package/bundled/skills/prizmkit-deploy/SKILL.md +172 -198
- package/bundled/skills/prizmkit-deploy/references/capability-contract.md +137 -0
- package/bundled/skills/prizmkit-deploy/references/deploy-record-schema.json +1053 -0
- package/bundled/skills/prizmkit-deploy/references/deployment-declaration-schema.json +291 -0
- package/bundled/skills/prizmkit-deploy/references/legacy-migration.md +90 -0
- package/bundled/skills/prizmkit-deploy/references/policy-and-execution.md +170 -0
- package/bundled/skills/prizmkit-deploy/references/real-resource-test-policy.md +73 -0
- package/bundled/skills/prizmkit-deploy/references/verification-and-recovery.md +164 -0
- package/bundled/skills/prizmkit-deploy/scripts/validate-deploy-artifact.py +371 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +2 -2
- package/bundled/skills/prizmkit-init/SKILL.md +38 -42
- package/bundled/skills/prizmkit-init/references/config-schema.md +11 -7
- package/bundled/skills/prizmkit-init/references/rules/layer-detection.md +3 -3
- package/bundled/skills/prizmkit-init/references/update-supplement.md +5 -5
- package/bundled/skills/prizmkit-plan/SKILL.md +5 -4
- package/bundled/skills/prizmkit-plan/assets/plan-template.md +4 -1
- package/bundled/skills/prizmkit-plan/references/verification-checklist.md +3 -2
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +17 -11
- package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +95 -155
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +6 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +4 -2
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +9 -10
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +6 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -12
- package/bundled/skills/prizmkit-retrospective/SKILL.md +3 -3
- package/bundled/skills/prizmkit-test/SKILL.md +26 -13
- package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +8 -4
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +7 -3
- package/bundled/skills/prizmkit-test/references/test-coverage-model.md +33 -10
- package/bundled/skills/prizmkit-test/references/test-report-template.md +33 -11
- package/bundled/skills/prizmkit-workflow/SKILL.md +33 -3
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +23 -5
- package/bundled/templates/hooks/commit-intent-status.py +9 -41
- package/bundled/templates/hooks/commit-intent.json +3 -3
- package/bundled/templates/hooks/diff-prizm-docs.py +3 -1
- package/bundled/templates/hooks/prizm-pre-commit.py +32 -6
- package/bundled/templates/hooks/run-python-hook.cjs +44 -0
- package/bundled/templates/hooks/validate-prizm-docs.py +399 -173
- package/bundled/templates/project-memory-template.md +19 -19
- package/package.json +1 -1
- package/src/clean.js +6 -7
- package/src/gitignore-template.js +8 -12
- package/src/scaffold.js +125 -71
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +0 -178
- package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +0 -89
- package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +0 -145
- package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +0 -109
- package/bundled/skills/prizmkit-deploy/references/data-safety-examples.md +0 -120
- package/bundled/skills/prizmkit-deploy/references/database-setup.md +0 -65
- package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +0 -150
- package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +0 -78
- package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +0 -49
- package/bundled/skills/prizmkit-deploy/references/deployment-modes.md +0 -50
- package/bundled/skills/prizmkit-deploy/references/direct-upload.md +0 -26
- package/bundled/skills/prizmkit-deploy/references/dns-setup.md +0 -42
- package/bundled/skills/prizmkit-deploy/references/docker-deploy.md +0 -31
- package/bundled/skills/prizmkit-deploy/references/firewall-setup.md +0 -37
- package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +0 -21
- package/bundled/skills/prizmkit-deploy/references/nginx-blue-green.md +0 -59
- package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +0 -164
- package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +0 -221
- package/bundled/skills/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
- package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
- package/bundled/skills/prizmkit-deploy/references/ssh-takeover.md +0 -20
- package/bundled/skills/prizmkit-deploy/references/ssl-setup.md +0 -56
|
@@ -670,6 +670,143 @@ def test_fresh_checkout_and_clean_keep_id_range_and_filter_selection(
|
|
|
670
670
|
assert all(entry[3] is (mode == "--clean") for entry in captured)
|
|
671
671
|
|
|
672
672
|
|
|
673
|
+
@pytest.mark.parametrize("kind", ("feature", "bugfix", "refactor"))
|
|
674
|
+
def test_clean_uses_item_state_without_pipeline_state_but_fresh_checkout_still_requires_it(
|
|
675
|
+
monkeypatch,
|
|
676
|
+
tmp_path,
|
|
677
|
+
kind,
|
|
678
|
+
):
|
|
679
|
+
from prizmkit_runtime import reset as reset_runtime
|
|
680
|
+
from prizmkit_runtime.reset import run_reset_command
|
|
681
|
+
from prizmkit_runtime.task_checkout import TaskCheckout, persist_task_checkout
|
|
682
|
+
|
|
683
|
+
paths = _make_paths(tmp_path / kind)
|
|
684
|
+
contract = FAMILY_CONTRACTS[kind]
|
|
685
|
+
item_id = f"{contract['prefix']}001"
|
|
686
|
+
family, plan_path = _family_and_plan(paths, kind, [_item(item_id, "in_progress")])
|
|
687
|
+
status_path, _ = _write_runtime_status(
|
|
688
|
+
family,
|
|
689
|
+
item_id,
|
|
690
|
+
active_dev_branch=f"{contract['branch_prefix']}/{item_id}-clean",
|
|
691
|
+
base_branch="main",
|
|
692
|
+
)
|
|
693
|
+
checkout_path = persist_task_checkout(
|
|
694
|
+
family.state_dir,
|
|
695
|
+
TaskCheckout.active(
|
|
696
|
+
family.task_type,
|
|
697
|
+
item_id,
|
|
698
|
+
f"{contract['branch_prefix']}/{item_id}-clean",
|
|
699
|
+
"main",
|
|
700
|
+
),
|
|
701
|
+
)
|
|
702
|
+
captured = []
|
|
703
|
+
|
|
704
|
+
def fake_reset_one(received_family, item, options, project_root, return_branch, lines):
|
|
705
|
+
captured.append((received_family.kind, item.item_id, options.clean))
|
|
706
|
+
return True
|
|
707
|
+
|
|
708
|
+
monkeypatch.setattr(reset_runtime, "_reset_one", fake_reset_one)
|
|
709
|
+
monkeypatch.setattr(reset_runtime, "default_branch", lambda _root: "main")
|
|
710
|
+
|
|
711
|
+
fresh_result = run_reset_command(
|
|
712
|
+
kind,
|
|
713
|
+
(item_id, "--fresh-checkout", str(plan_path)),
|
|
714
|
+
paths,
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
assert fresh_result.exit_code != 0
|
|
718
|
+
assert "No pipeline state found" in fresh_result.render()
|
|
719
|
+
assert captured == []
|
|
720
|
+
assert status_path.is_file()
|
|
721
|
+
assert checkout_path.is_file()
|
|
722
|
+
assert not (family.state_dir / "pipeline.json").exists()
|
|
723
|
+
|
|
724
|
+
clean_result = run_reset_command(
|
|
725
|
+
kind,
|
|
726
|
+
(item_id, "--clean", str(plan_path)),
|
|
727
|
+
paths,
|
|
728
|
+
)
|
|
729
|
+
|
|
730
|
+
assert clean_result.exit_code == 0, clean_result.render()
|
|
731
|
+
assert captured == [(kind, item_id, True)]
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def test_feature_clean_removes_stale_workflow_fields_and_preserves_diagnostics(tmp_path):
|
|
735
|
+
paths = _make_paths(tmp_path)
|
|
736
|
+
family, plan_path = _family_and_plan(
|
|
737
|
+
paths,
|
|
738
|
+
"feature",
|
|
739
|
+
[_item("F-001", "failed")],
|
|
740
|
+
)
|
|
741
|
+
status_path, _ = _write_runtime_status(
|
|
742
|
+
family,
|
|
743
|
+
"F-001",
|
|
744
|
+
repair_scope="production",
|
|
745
|
+
repair_round=2,
|
|
746
|
+
blocked_reason="test_blocked",
|
|
747
|
+
terminal_status="WORKFLOW_BLOCKED",
|
|
748
|
+
)
|
|
749
|
+
session_dir = family.state_dir / "F-001" / "sessions" / "old-session"
|
|
750
|
+
session_dir.mkdir(parents=True)
|
|
751
|
+
(session_dir / "session.log").write_text("old session\n", encoding="utf-8")
|
|
752
|
+
feature_slug = "001-f-001"
|
|
753
|
+
specs_dir = paths.project_root / ".prizmkit" / "specs" / feature_slug
|
|
754
|
+
specs_dir.mkdir(parents=True)
|
|
755
|
+
(specs_dir / "spec.md").write_text("old spec\n", encoding="utf-8")
|
|
756
|
+
(specs_dir / "continuation-summary.md").write_text(
|
|
757
|
+
"old continuation\n",
|
|
758
|
+
encoding="utf-8",
|
|
759
|
+
)
|
|
760
|
+
|
|
761
|
+
result = subprocess.run(
|
|
762
|
+
[
|
|
763
|
+
sys.executable,
|
|
764
|
+
str(PIPELINE_ROOT / "scripts" / "update-feature-status.py"),
|
|
765
|
+
"--feature-list",
|
|
766
|
+
str(plan_path),
|
|
767
|
+
"--state-dir",
|
|
768
|
+
str(family.state_dir),
|
|
769
|
+
"--feature-id",
|
|
770
|
+
"F-001",
|
|
771
|
+
"--feature-slug",
|
|
772
|
+
feature_slug,
|
|
773
|
+
"--project-root",
|
|
774
|
+
str(paths.project_root),
|
|
775
|
+
"--action",
|
|
776
|
+
"clean",
|
|
777
|
+
],
|
|
778
|
+
cwd=paths.project_root,
|
|
779
|
+
text=True,
|
|
780
|
+
stdout=subprocess.PIPE,
|
|
781
|
+
stderr=subprocess.PIPE,
|
|
782
|
+
check=False,
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
assert result.returncode == 0, (result.stdout, result.stderr)
|
|
786
|
+
payload = json.loads(result.stdout)
|
|
787
|
+
assert payload["action"] == "clean"
|
|
788
|
+
assert payload["new_status"] == "pending"
|
|
789
|
+
updated_list = json.loads(plan_path.read_text(encoding="utf-8"))
|
|
790
|
+
assert updated_list["features"][0]["status"] == "pending"
|
|
791
|
+
updated_status = json.loads(status_path.read_text(encoding="utf-8"))
|
|
792
|
+
for stale_field in (
|
|
793
|
+
"repair_scope",
|
|
794
|
+
"repair_round",
|
|
795
|
+
"blocked_reason",
|
|
796
|
+
"terminal_status",
|
|
797
|
+
):
|
|
798
|
+
assert stale_field not in updated_status
|
|
799
|
+
assert updated_status["retry_count"] == 0
|
|
800
|
+
assert updated_status["infra_error_count"] == 0
|
|
801
|
+
assert updated_status["sessions"] == []
|
|
802
|
+
assert updated_status["last_session_id"] is None
|
|
803
|
+
assert updated_status["resume_from_phase"] is None
|
|
804
|
+
assert updated_status["custom_diagnostic"] == {"keep": True}
|
|
805
|
+
assert "continuation_pending" not in updated_status
|
|
806
|
+
assert not session_dir.exists()
|
|
807
|
+
assert not specs_dir.exists()
|
|
808
|
+
|
|
809
|
+
|
|
673
810
|
def _valid_bug(bug_id, status="pending", dependencies=None):
|
|
674
811
|
return {
|
|
675
812
|
"id": bug_id,
|
|
@@ -229,18 +229,18 @@ def test_runtime_commit_executes_exact_request_and_finalizes_only_checkpoint(tmp
|
|
|
229
229
|
".prizmkit/prizm-docs/src/counter.prizm",
|
|
230
230
|
],
|
|
231
231
|
)
|
|
232
|
-
def
|
|
232
|
+
def test_runtime_commit_admits_tracked_prizmkit_path_in_exact_request(tmp_path, durable_path):
|
|
233
233
|
_init_repo(tmp_path)
|
|
234
234
|
durable = tmp_path / durable_path
|
|
235
235
|
durable.parent.mkdir(parents=True, exist_ok=True)
|
|
236
236
|
durable.write_text("before\n", encoding="utf-8")
|
|
237
237
|
_git(tmp_path, "add", "-f", durable_path)
|
|
238
|
-
_git(tmp_path, "commit", "-m", "track
|
|
238
|
+
_git(tmp_path, "commit", "-m", "track project-selected PrizmKit data")
|
|
239
239
|
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
240
240
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
241
241
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
242
242
|
durable.write_text("after\n", encoding="utf-8")
|
|
243
|
-
_write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
|
|
243
|
+
_write_request(tmp_path, artifact_dir, base_head, ["tracked.txt", durable_path])
|
|
244
244
|
|
|
245
245
|
result = finalize_runtime_commit(
|
|
246
246
|
tmp_path,
|
|
@@ -249,21 +249,16 @@ def test_runtime_commit_excludes_tracked_prizmkit_internal_paths(tmp_path, durab
|
|
|
249
249
|
)
|
|
250
250
|
|
|
251
251
|
assert result.status == "committed", result
|
|
252
|
-
|
|
252
|
+
changed = set(_git(
|
|
253
253
|
tmp_path,
|
|
254
254
|
"diff-tree",
|
|
255
255
|
"--no-commit-id",
|
|
256
256
|
"--name-only",
|
|
257
257
|
"-r",
|
|
258
258
|
"HEAD",
|
|
259
|
-
)
|
|
259
|
+
).splitlines())
|
|
260
|
+
assert changed == {"tracked.txt", durable_path}
|
|
260
261
|
assert durable.read_text(encoding="utf-8") == "after\n"
|
|
261
|
-
assert durable_path in _git(
|
|
262
|
-
tmp_path,
|
|
263
|
-
"status",
|
|
264
|
-
"--short",
|
|
265
|
-
"--untracked-files=all",
|
|
266
|
-
)
|
|
267
262
|
|
|
268
263
|
|
|
269
264
|
def test_runtime_commit_ignores_runner_support_paths_but_leaves_them_unmodified(tmp_path):
|
|
@@ -520,8 +515,7 @@ def test_runtime_commit_handles_rename_as_exact_delete_and_add(tmp_path):
|
|
|
520
515
|
"skills-lock.json",
|
|
521
516
|
".codex/config.toml",
|
|
522
517
|
".CLAUDE/settings.local.json",
|
|
523
|
-
".prizmkit/
|
|
524
|
-
".prizmkit/prizm-docs/src/counter.prizm",
|
|
518
|
+
".prizmkit/prizm-docs/.env",
|
|
525
519
|
".prizmkit/state/runtime.json",
|
|
526
520
|
".prizmkit/dev-pipeline/cli.py",
|
|
527
521
|
".prizmkit/scripts/helper.py",
|
|
@@ -547,6 +541,67 @@ def test_runtime_commit_rejects_unsafe_intended_paths(tmp_path, unsafe_path):
|
|
|
547
541
|
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
548
542
|
|
|
549
543
|
|
|
544
|
+
def test_runtime_commit_verifies_staged_set_before_commit(tmp_path):
|
|
545
|
+
_init_repo(tmp_path)
|
|
546
|
+
support = tmp_path / "AGENTS.md"
|
|
547
|
+
support.write_text("before\n", encoding="utf-8")
|
|
548
|
+
_git(tmp_path, "add", "AGENTS.md")
|
|
549
|
+
_git(tmp_path, "commit", "-m", "track support")
|
|
550
|
+
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
551
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
552
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
553
|
+
support.write_text("after\n", encoding="utf-8")
|
|
554
|
+
_git(tmp_path, "add", "AGENTS.md")
|
|
555
|
+
_write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
|
|
556
|
+
|
|
557
|
+
result = finalize_runtime_commit(
|
|
558
|
+
tmp_path,
|
|
559
|
+
artifact_dir=artifact_dir,
|
|
560
|
+
checkpoint_path=checkpoint_path,
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
assert result.status == "failed"
|
|
564
|
+
assert result.reason == "staged_paths_mismatch"
|
|
565
|
+
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
def test_runtime_commit_keeps_tracked_post_commit_bookkeeping_out_of_snapshot(tmp_path):
|
|
569
|
+
from prizmkit_runtime.gitops import HIDDEN_TOOL_WORKTREE_EXCLUDES
|
|
570
|
+
|
|
571
|
+
initial_head = _init_repo(tmp_path)
|
|
572
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
573
|
+
request_path = _write_request(tmp_path, artifact_dir, initial_head, ["tracked.txt"])
|
|
574
|
+
checkpoint_rel = checkpoint_path.relative_to(tmp_path).as_posix()
|
|
575
|
+
request_rel = request_path.relative_to(tmp_path).as_posix()
|
|
576
|
+
_git(tmp_path, "add", "-f", checkpoint_rel, request_rel)
|
|
577
|
+
_git(tmp_path, "commit", "-m", "track runtime bookkeeping by project policy")
|
|
578
|
+
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
579
|
+
_write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
|
|
580
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
581
|
+
|
|
582
|
+
result = finalize_runtime_commit(
|
|
583
|
+
tmp_path,
|
|
584
|
+
artifact_dir=artifact_dir,
|
|
585
|
+
checkpoint_path=checkpoint_path,
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
assert result.status == "committed", result
|
|
589
|
+
assert _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD") == "tracked.txt"
|
|
590
|
+
assert checkpoint_rel not in _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD")
|
|
591
|
+
visible = _git(
|
|
592
|
+
tmp_path,
|
|
593
|
+
"status",
|
|
594
|
+
"--porcelain",
|
|
595
|
+
"--",
|
|
596
|
+
".",
|
|
597
|
+
*HIDDEN_TOOL_WORKTREE_EXCLUDES,
|
|
598
|
+
)
|
|
599
|
+
assert visible == ""
|
|
600
|
+
raw_status = _git(tmp_path, "status", "--porcelain", "--", checkpoint_rel, request_rel)
|
|
601
|
+
assert checkpoint_rel in raw_status
|
|
602
|
+
assert request_rel in raw_status
|
|
603
|
+
|
|
604
|
+
|
|
550
605
|
def test_runtime_commit_rejects_caller_orchestration_fields(tmp_path):
|
|
551
606
|
base_head = _init_repo(tmp_path)
|
|
552
607
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
@@ -1313,7 +1313,8 @@ def test_headless_review_guidance_maps_stage_local_skill_result():
|
|
|
1313
1313
|
|
|
1314
1314
|
skill_text = skill_path.read_text(encoding="utf-8")
|
|
1315
1315
|
assert "the staged diff, and the unstaged diff" in skill_text
|
|
1316
|
-
assert "untracked, deleted, and renamed
|
|
1316
|
+
assert "untracked, deleted, and renamed paths" in skill_text
|
|
1317
|
+
assert "default-excluded changed paths" in skill_text
|
|
1317
1318
|
assert "accepted = 0" in skill_text
|
|
1318
1319
|
assert "ten completed review rounds" in skill_text
|
|
1319
1320
|
assert "## Phase 3: Independent Code Review" in skill_text
|
|
@@ -3620,8 +3621,11 @@ def test_git_status_safe_ignores_worktree_support_assets(monkeypatch, tmp_path):
|
|
|
3620
3621
|
joined = " ".join(status_args)
|
|
3621
3622
|
assert ":(top,exclude).prizmkit-worktree" in status_args
|
|
3622
3623
|
assert ":(top,exclude).claude" in status_args
|
|
3623
|
-
assert ":(top,exclude).prizmkit" in status_args
|
|
3624
|
-
assert ":(top,exclude,glob).prizmkit/**" in status_args
|
|
3624
|
+
assert ":(top,exclude).prizmkit" not in status_args
|
|
3625
|
+
assert ":(top,exclude,glob).prizmkit/**" not in status_args
|
|
3626
|
+
assert ":(top,exclude,glob).prizmkit/dev-pipeline/**" in status_args
|
|
3627
|
+
assert ":(top,exclude,glob).prizmkit/state/**" in status_args
|
|
3628
|
+
assert ":(top,exclude,glob).prizmkit/specs/**/workflow-checkpoint.json" in status_args
|
|
3625
3629
|
assert all(exclude in status_args for exclude in HIDDEN_TOOL_WORKTREE_EXCLUDES)
|
|
3626
3630
|
assert ".prizmkit-worktree" in joined
|
|
3627
3631
|
|
|
@@ -3882,7 +3886,7 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
|
|
|
3882
3886
|
assert guarded_worktree_remove(runtime, delete_branch=False).ok
|
|
3883
3887
|
|
|
3884
3888
|
|
|
3885
|
-
def
|
|
3889
|
+
def test_linked_worktree_rejects_dirty_tracked_prizmkit_config(tmp_path):
|
|
3886
3890
|
from prizmkit_runtime.gitops import (
|
|
3887
3891
|
BranchContext,
|
|
3888
3892
|
WorktreePolicy,
|
|
@@ -3929,10 +3933,11 @@ def test_linked_worktree_fast_forwards_with_dirty_prizmkit_internal_state(tmp_pa
|
|
|
3929
3933
|
assert branch_fast_forward_possible(repo, runtime.context) is True
|
|
3930
3934
|
result = merge_linked_worktree(runtime)
|
|
3931
3935
|
|
|
3932
|
-
assert result.ok is
|
|
3933
|
-
assert
|
|
3934
|
-
assert (repo / "feature.txt").
|
|
3936
|
+
assert result.ok is False
|
|
3937
|
+
assert result.reason == "dirty_task_checkout"
|
|
3938
|
+
assert not (repo / "feature.txt").exists()
|
|
3935
3939
|
assert json.loads(worktree_config.read_text(encoding="utf-8"))["mode"] == "session-local"
|
|
3940
|
+
worktree_config.write_text('{"mode":"base"}\n', encoding="utf-8")
|
|
3936
3941
|
assert guarded_worktree_remove(runtime, delete_branch=True).ok
|
|
3937
3942
|
|
|
3938
3943
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
description: "PrizmKit commit workflow rules"
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
1.
|
|
7
|
-
2. Use
|
|
8
|
-
3.
|
|
9
|
-
4.
|
|
10
|
-
5.
|
|
11
|
-
6.
|
|
5
|
+
For a formal requirement:
|
|
6
|
+
1. Complete `/prizmkit-retrospective` after Test and before Committer; it synchronizes durable documentation or records `NO_DOC_CHANGE` but never stages or commits.
|
|
7
|
+
2. Use `/prizmkit-committer` for one exact local commit operation and Conventional Commit message.
|
|
8
|
+
3. Interactive Committer stages only the user-confirmed exact manifest and verifies staged-set/receipt equality; broad staging and force-add are prohibited.
|
|
9
|
+
4. A Git-visible `.prizmkit/**` requirement path is handled like any other exact intended path and requires no documentation-specific commit evidence. Ignored paths remain absent; project tracking policy is unchanged.
|
|
10
|
+
5. Exact Runtime bookkeeping/support and Secrets remain excluded by semantic role. Secret checks apply globally and no framework-directory exception exists.
|
|
11
|
+
6. Remote publication and deployment remain separate.
|
|
@@ -11,68 +11,27 @@ globs:
|
|
|
11
11
|
- "**/*.java"
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
WHEN TO UPDATE
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
- L1
|
|
31
|
-
- L2
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
REQUIRED FIELDS PER LEVEL:
|
|
40
|
-
|
|
41
|
-
L0 root.prizm:
|
|
42
|
-
- PRIZM_VERSION
|
|
43
|
-
- PROJECT
|
|
44
|
-
- LANG
|
|
45
|
-
- MODULE_INDEX or MODULE_GROUPS (with -> pointers to L1 files)
|
|
46
|
-
- RULES (top-level project rules)
|
|
47
|
-
|
|
48
|
-
L1 module.prizm (structural index only):
|
|
49
|
-
- MODULE
|
|
50
|
-
- FILES
|
|
51
|
-
- RESPONSIBILITY
|
|
52
|
-
- DEPENDENCIES
|
|
53
|
-
- L1 does NOT contain: INTERFACES, DATA_FLOW, TRAPS, DECISIONS (those belong in L2)
|
|
54
|
-
|
|
55
|
-
L2 detail.prizm:
|
|
56
|
-
- MODULE
|
|
57
|
-
- FILES
|
|
58
|
-
- KEY_FILES
|
|
59
|
-
- DEPENDENCIES
|
|
60
|
-
- INTERFACES
|
|
61
|
-
- TRAPS (with severity prefix: [CRITICAL], [HIGH], or [LOW])
|
|
62
|
-
|
|
63
|
-
L2 GENERATION TEMPLATE (use when AI first touches a sub-module with no L2 doc):
|
|
64
|
-
|
|
65
|
-
MODULE: <path>
|
|
66
|
-
FILES: <comma-separated file list>
|
|
67
|
-
RESPONSIBILITY: <one-line>
|
|
68
|
-
KEY_FILES:
|
|
69
|
-
- <file>: <role, line count, complexity note>
|
|
70
|
-
DEPENDENCIES:
|
|
71
|
-
- uses: <lib>: <why>
|
|
72
|
-
- imports: <module>: <what>
|
|
73
|
-
INTERFACES:
|
|
74
|
-
- <exported function/class>: <signature and purpose>
|
|
75
|
-
TRAPS:
|
|
76
|
-
- [LOW] <gotcha, race condition, or non-obvious coupling> | FIX: <approach>
|
|
77
|
-
|
|
78
|
-
TRAPS is critical — always record gotchas, race conditions, non-obvious behavior, and surprising coupling between modules. Every TRAP must have a severity prefix ([CRITICAL], [HIGH], or [LOW]).
|
|
14
|
+
WHEN TO UPDATE `.prizmkit/prizm-docs/`:
|
|
15
|
+
- Use `/prizmkit-retrospective` after a validated change affects structure, interfaces, dependencies, behavior, or durable TRAPS/RULES/DECISIONS.
|
|
16
|
+
- Skip documentation writes when no current durable non-obvious fact passes the Value Gate.
|
|
17
|
+
- Before source modification, read exact root, the relevant direct-child L1, the complete relevant nested L2, and complete resolving pointer documents.
|
|
18
|
+
- If relevant L2 is absent, inspect bounded relevant source without creating a placeholder.
|
|
19
|
+
|
|
20
|
+
FRAMEWORK DIRECTORY AND GIT POLICY:
|
|
21
|
+
- `.prizmkit/**` is framework-owned capability/artifact space; an owner may read/write only its managed paths.
|
|
22
|
+
- The project decides whether framework paths are ignored, untracked, or tracked. Do not add, remove, force-add, stage, commit, or interpret `.gitignore` entries as part of documentation maintenance.
|
|
23
|
+
- Validation/generation/reconciliation behavior is identical across tracking states apart from ordinary Git visibility; Git history is not required.
|
|
24
|
+
|
|
25
|
+
FORMAT RULES:
|
|
26
|
+
- New roots use `PRIZM_VERSION: 4`.
|
|
27
|
+
- Only exact `.prizmkit/prizm-docs/root.prizm` is L0; direct `.prizm` children other than root are L1; every nested `.prizm` document is L2.
|
|
28
|
+
- ALL CAPS section headers, KEY: value pairs, and dash-prefixed lists only.
|
|
29
|
+
- PROHIBITED: CHANGELOG sections/files, prose paragraphs, markdown headers, code blocks, horizontal rules, UPDATED/date metadata, feature/bug/refactor/task/session/run/pipeline/workflow IDs, branch names, absolute worktree paths, and `.prizmkit/specs` / `.prizmkit/dev-pipeline` artifact paths.
|
|
30
|
+
- L1 is structural and must not contain INTERFACES, DATA_FLOW, TRAPS, DECISIONS, CONCERN, or full RULES.
|
|
31
|
+
- Mirrored L2 requires MODULE, FILES, RESPONSIBILITY, INTERFACES, KEY_FILES, DEPENDENCIES, and TRAPS. Semantic L2 also requires deterministic CONCERN/SLUG, DATA_FLOW, RULES, DECISIONS, exact parent DETAILS pointer, and non-overlapping FILES ownership.
|
|
32
|
+
|
|
33
|
+
CAPACITY AND WRITES:
|
|
34
|
+
- Raw UTF-8 hard limits: L0 4096B, L1 4096B, L2 5120B. Existing warning bands remain advisory; hard-limit violations fail.
|
|
35
|
+
- Apply Value/Cleanup gates and protect still-valid contracts, constraints, dependencies, traps, decisions, side effects, and safety/integrity rules.
|
|
36
|
+
- Build complete candidates and write bottom-up. Skip byte-identical replacements, re-read actual bytes/pointers, and restore exact prior bytes or remove invalid new targets after any failed post-write check.
|
|
37
|
+
- Never add L3, a documentation state machine, task-named shards, or placeholder L2 documents.
|
|
@@ -3,11 +3,12 @@ description: "PrizmKit progressive context loading protocol"
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
This project uses PrizmKit's progressive loading protocol:
|
|
6
|
-
- ON SESSION START: Read `.prizmkit/prizm-docs/root.prizm` (L0
|
|
7
|
-
- ON
|
|
8
|
-
- ON
|
|
9
|
-
-
|
|
10
|
-
- NEVER load all
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
6
|
+
- ON SESSION START: Read exact `.prizmkit/prizm-docs/root.prizm` (L0 project map) when it exists.
|
|
7
|
+
- ON TASK: Read only relevant direct-child L1 documents (`.prizmkit/prizm-docs/<module>.prizm`) selected through root MODULE_INDEX/MODULE_GROUPS pointers.
|
|
8
|
+
- ON FILE EDIT: Read the complete relevant nested L2 document and complete parent/child documents needed to resolve its SUBDIRS or DETAILS pointer before modification. Grep-only fragments are insufficient modification context.
|
|
9
|
+
- IF L2 IS ABSENT: Inspect only bounded target source and narrowly implicated contracts; proceed without creating a placeholder. Documentation creation belongs to Retrospective or explicit documentation repair and requires complete Value-Gate-qualified content.
|
|
10
|
+
- NEVER load all L1/L2 documents at session start, create L3, or load unrelated modules.
|
|
11
|
+
- PATH LEVELS: only exact `root.prizm` is L0; every other direct `.prizm` child is L1; every nested `.prizm` document is L2.
|
|
12
|
+
- Arrow notation (`->`) identifies resolving documentation pointers.
|
|
13
|
+
- Memory files do not contain CHANGELOG sections/files, UPDATED/date metadata, feature/bug/refactor/task/session/run/pipeline/workflow IDs, branch names, absolute worktree paths, or `.prizmkit/specs` / `.prizmkit/dev-pipeline` artifact paths.
|
|
14
|
+
- `.prizmkit/**` is the framework directory. Its owning capabilities may read/write managed artifacts, but project Git tracking/ignore policy is independent and must not alter documentation behavior.
|
|
@@ -18,7 +18,7 @@ description: "PrizmKit framework introduction and lifecycle navigator. Explains
|
|
|
18
18
|
## When NOT to Use
|
|
19
19
|
|
|
20
20
|
- User already knows the required skill; invoke that skill directly.
|
|
21
|
-
- A formal requirement is already in progress; continue
|
|
21
|
+
- A formal requirement is already in progress; continue through its owning coordinator or current atomic stage.
|
|
22
22
|
- User wants an immediate low-risk direct edit; perform the edit and its specific verification.
|
|
23
23
|
|
|
24
24
|
## Responsibility Map
|
|
@@ -125,18 +125,6 @@ The active coordinator validates all required evidence before invoking `prizmkit
|
|
|
125
125
|
|
|
126
126
|
Pushing to a remote is a separate explicit action. Deployment is always a separate invocation of `/prizmkit-deploy`.
|
|
127
127
|
|
|
128
|
-
## Workflow State
|
|
129
|
-
|
|
130
|
-
An active requirement may use:
|
|
131
|
-
|
|
132
|
-
```text
|
|
133
|
-
.prizmkit/state/workflows/<requirement-identity>.json
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
`<requirement-identity>` is the validated exact basename of the active artifact directory. An existing state file that records a different artifact directory is a blocking collision and is never silently overwritten or suffixed. This coordinator-owned state records current stage, terminal status, repair scope, repair round, and resume entry. Atomic Skills do not read or write it. The target project controls whether the file is committed, ignored, or shared.
|
|
137
|
-
|
|
138
|
-
Read `${SKILL_DIR}/references/workflow-state-protocol.md` for the state protocol. If the state file is missing or stale, use `spec.md`, `plan.md`, the review report, `test-report.md`, and `test-result.json` to reconstruct the safest recoverable stage and report that reconstruction.
|
|
139
|
-
|
|
140
128
|
## Quick Start
|
|
141
129
|
|
|
142
130
|
Install the skills through the host's skills installer, for example:
|
|
@@ -18,6 +18,18 @@ description: "Review one supplied complete change with a bounded Main-Agent revi
|
|
|
18
18
|
- Review repairs use targeted verification appropriate to each accepted finding.
|
|
19
19
|
- `{artifact_dir}/review-report.md` is the only persisted review artifact for this execution.
|
|
20
20
|
|
|
21
|
+
## Report Renderer Contract
|
|
22
|
+
|
|
23
|
+
Use `${SKILL_DIR}/scripts/render_review_report.py` as the canonical executable writer for report initialization, validated progress append, and finalization:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
resolved Python 3 interpreter + render_review_report.py init <report>
|
|
27
|
+
resolved Python 3 interpreter + render_review_report.py append <report> ← validated event JSON on standard input
|
|
28
|
+
resolved Python 3 interpreter + render_review_report.py finalize <report> ← validated final JSON on standard input
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Resolve a compatible Python 3 interpreter through the current Host's executable capability; do not require one operating-system-specific command name. If no compatible interpreter is available, follow `${SKILL_DIR}/references/review-report-template.md` directly, record the renderer fallback in Final Verification evidence, and apply every equivalent count, ordering, field, and terminal-shape check before returning a verdict. Never silently omit renderer-owned fields or claim executable validation occurred during fallback.
|
|
32
|
+
|
|
21
33
|
## Atomic Stage Boundary
|
|
22
34
|
|
|
23
35
|
`prizmkit-code-review` owns the complete review, accepted-correction repairs, targeted verification, and `review-report.md` for one supplied change. It returns `PASS` or `NEEDS_FIXES` and stops.
|
|
@@ -43,16 +55,23 @@ description: "Review one supplied complete change with a bounded Main-Agent revi
|
|
|
43
55
|
|
|
44
56
|
Review only the caller-supplied `artifact_dir`; never discover a different recent artifact. Missing or inconsistent stage input produces `NEEDS_FIXES` with the exact input blocker.
|
|
45
57
|
|
|
58
|
+
## Default Correctness Scope
|
|
59
|
+
|
|
60
|
+
The current requirement change outside `.prizmkit/**` is the ordinary correctness scope. Every `.prizmkit/**` path is excluded by default from correctness review, including correctness diffs, candidate findings, repairs, and verification scope. The Skill may read only exact caller-supplied `.prizmkit` artifacts such as `spec.md` and `plan.md` as evidence for the outside-framework requirement and may write its own `review-report.md`; it must not assess, report findings against, or repair their content. Neither action makes `.prizmkit` content reviewable production change. Correctness review of any framework/support artifact requires a separate explicit support-artifact review contract naming the exact artifacts and validator.
|
|
61
|
+
|
|
62
|
+
Generated host-support paths are also excluded by default, including `AGENTS.md`, `skills-lock.json`, installed platform directories, and local platform settings. An explicitly owned support change requires a separate explicit support-artifact validation contract; do not pull it into ordinary Code Review through workspace expansion. Record excluded changed paths in the report so exclusion is visible rather than mistaken for reviewed content.
|
|
63
|
+
|
|
46
64
|
## Phase 0: Initialize Report and Reuse Current Context
|
|
47
65
|
|
|
48
66
|
1. Resolve `{artifact_dir}` and `{artifact_dir}/review-report.md` from the active requirement context.
|
|
49
|
-
2. At the start of each execution,
|
|
50
|
-
3. Within that execution, append
|
|
51
|
-
4. Start from the Main Agent's current requirement context and inspect the complete workspace
|
|
52
|
-
5.
|
|
53
|
-
6.
|
|
54
|
-
7.
|
|
55
|
-
8.
|
|
67
|
+
2. At the start of each execution, initialize a replacement report through the Report Renderer Contract and `${SKILL_DIR}/references/review-report-template.md`.
|
|
68
|
+
3. Within that execution, append every review round, repair batch, independent-review event, final verification, and exactly one `## Final Result` through the renderer or its visible equivalent fallback.
|
|
69
|
+
4. Start from the Main Agent's current requirement context and inspect the complete workspace inventory first: `git status --short`, the staged diff, and the unstaged diff. Include untracked, deleted, and renamed paths in classification, then remove default-excluded `.prizmkit/**` and host-support paths from the correctness scope before producing findings.
|
|
70
|
+
5. Append one validated `scope-classification` renderer event containing exact in-scope paths and exact default-excluded changed paths; do not describe exclusions as reviewed or silently repair them.
|
|
71
|
+
6. Reuse current context and load only missing or potentially stale material required to resolve a concrete ambiguity, verify an acceptance criterion, or understand a changed contract.
|
|
72
|
+
7. Inspect unchanged callers, dependents, contracts, or tests only when the in-scope diff changes or may violate an interface, shared behavior, or regression boundary. Do not perform an unconditional repository-wide dependency sweep.
|
|
73
|
+
8. For `review_scope=delta`, focus on in-scope files and behavior affected since the prior review pass and expand only across contracts implicated by that delta.
|
|
74
|
+
9. If no in-scope changes exist, record final verification and `PASS` only when the current requirement context and prior implementation state prove there is nothing left to review.
|
|
56
75
|
|
|
57
76
|
## Phase 1: Main-Agent Review Loop
|
|
58
77
|
|
|
@@ -77,7 +96,7 @@ For every candidate finding:
|
|
|
77
96
|
- `unresolved`: correctness or safe repair cannot be established.
|
|
78
97
|
3. Treat Missing tools, permissions, environment, or required evidence as an unresolved finding when they prevent review verification.
|
|
79
98
|
4. If a repair cannot be completed safely, record an unresolved finding and return `NEEDS_FIXES`.
|
|
80
|
-
5. Append the review
|
|
99
|
+
5. Append the validated review-round event through the Report Renderer Contract.
|
|
81
100
|
|
|
82
101
|
Round behavior:
|
|
83
102
|
|
|
@@ -105,7 +124,7 @@ For accepted findings while the round limit remains:
|
|
|
105
124
|
1. Repair directly in the active workspace.
|
|
106
125
|
2. Run targeted tests, static checks, or other verification appropriate to each repair.
|
|
107
126
|
3. Inspect the complete resulting diff for unrelated changes and regressions.
|
|
108
|
-
4. Append repair
|
|
127
|
+
4. Append validated repair-verification evidence through the Report Renderer Contract and continue the review loop.
|
|
109
128
|
|
|
110
129
|
Do not turn review verification into a broad unrelated test campaign; use targeted checks that establish each repair.
|
|
111
130
|
|
|
@@ -131,7 +150,7 @@ Before completing:
|
|
|
131
150
|
|
|
132
151
|
1. Confirm the final workspace is the complete reviewed change.
|
|
133
152
|
2. Confirm all accepted findings are fixed and no unresolved finding remains for `PASS`.
|
|
134
|
-
3. Append final verification and exactly one final result.
|
|
153
|
+
3. Append final verification and exactly one final result through the Report Renderer Contract or its visibly recorded equivalent fallback.
|
|
135
154
|
|
|
136
155
|
Valid results:
|
|
137
156
|
|
|
@@ -62,14 +62,15 @@ The Main Agent supplies:
|
|
|
62
62
|
|
|
63
63
|
- original requirement and confirmed clarifications;
|
|
64
64
|
- exact artifact, spec, and plan paths plus current contents;
|
|
65
|
-
- current workspace status;
|
|
66
|
-
- staged and unstaged tracked changes;
|
|
67
|
-
- relevant untracked, deleted, and renamed content;
|
|
65
|
+
- current workspace status after the Main Agent classifies default exclusions;
|
|
66
|
+
- staged and unstaged tracked changes in the ordinary correctness scope;
|
|
67
|
+
- relevant in-scope untracked, deleted, and renamed content;
|
|
68
|
+
- exact default-excluded changed paths as visible exclusion metadata, never as reviewed content;
|
|
68
69
|
- implementation task completion and targeted verification results;
|
|
69
70
|
- response number and total budget;
|
|
70
71
|
- prior adjudication, actual repairs, and repair verification on continuation or replacement.
|
|
71
72
|
|
|
72
|
-
The Main Agent runs Git and captures authoritative current-change state. The Reviewer may use structurally read-only checkout access to inspect unchanged callers, consumers, contracts, schemas, types, configurations, fixtures, or tests only when concrete coupling to this requirement justifies it. It must not run commands or perform an unconditional repository-wide scan. Missing or inconsistent required input produces `REVIEW_BLOCKED`, never partial success.
|
|
73
|
+
The Main Agent runs Git and captures authoritative current-change state, then applies the Skill's default `.prizmkit/**` and generated host-support exclusions before supplying the correctness change. The Reviewer may read the exact supplied spec/plan artifacts but must not inspect other `.prizmkit` content. It may use structurally read-only checkout access to inspect unchanged callers, consumers, contracts, schemas, types, configurations, fixtures, or tests only when concrete coupling to this requirement justifies it. It must not run commands or perform an unconditional repository-wide scan. Missing or inconsistent required input produces `REVIEW_BLOCKED`, never partial success.
|
|
73
74
|
|
|
74
75
|
## Initial Reviewer Prompt
|
|
75
76
|
|
|
@@ -16,6 +16,21 @@ Within that execution, append sections only. Never edit or replace an earlier pr
|
|
|
16
16
|
|
|
17
17
|
## Progress Sections
|
|
18
18
|
|
|
19
|
+
### Review Scope
|
|
20
|
+
|
|
21
|
+
Append once after workspace inventory classification and before the first review round:
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
## Review Scope
|
|
25
|
+
|
|
26
|
+
- In-Scope Paths:
|
|
27
|
+
- <exact requirement-owned path or None.>
|
|
28
|
+
- Default-Excluded Changed Paths:
|
|
29
|
+
- <exact .prizmkit/support path or None.>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Paths under `.prizmkit/**` and generated host-support paths are visible exclusions, not reviewed content.
|
|
33
|
+
|
|
19
34
|
### Main-Agent Review Round
|
|
20
35
|
|
|
21
36
|
```markdown
|