prizmkit 1.1.127 → 1.1.129

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 (50) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/claude/command-adapter.js +2 -75
  3. package/bundled/dev-pipeline/assets/skill-subagent-integration.md +14 -11
  4. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +88 -58
  5. package/bundled/dev-pipeline/prizmkit_runtime/reset.py +4 -3
  6. package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +53 -1
  7. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +33 -17
  8. package/bundled/dev-pipeline/prizmkit_runtime/runtime_helper.py +0 -1
  9. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +28 -26
  10. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +1 -1
  11. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +4 -3
  12. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +1 -1
  13. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +3 -3
  14. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
  15. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +22 -21
  16. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +4 -4
  17. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +5 -5
  18. package/bundled/dev-pipeline/templates/sections/bugfix-mission.md +1 -1
  19. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +11 -4
  20. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
  21. package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +3 -2
  22. package/bundled/dev-pipeline/templates/sections/directory-convention-full.md +3 -2
  23. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +1 -1
  24. package/bundled/dev-pipeline/templates/sections/phase-commit.md +1 -1
  25. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +1 -1
  26. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +1 -1
  27. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +12 -5
  28. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +12 -5
  29. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +1 -1
  30. package/bundled/dev-pipeline/templates/sections/phase0-init.md +1 -1
  31. package/bundled/dev-pipeline/templates/sections/refactor-mission.md +1 -1
  32. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +13 -6
  33. package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +1 -1
  34. package/bundled/dev-pipeline/templates/sections/subagent-timeout-recovery.md +6 -4
  35. package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +1 -1
  36. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +106 -7
  37. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +139 -11
  38. package/bundled/dev-pipeline/tests/test_runtime_helper.py +9 -3
  39. package/bundled/dev-pipeline/tests/test_unified_cli.py +225 -24
  40. package/bundled/skills/_metadata.json +3 -3
  41. package/bundled/skills/feature-planner/SKILL.md +2 -2
  42. package/bundled/skills/prizmkit/SKILL.md +1 -1
  43. package/bundled/skills/prizmkit-code-review/SKILL.md +63 -122
  44. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +9 -36
  45. package/bundled/skills/prizmkit-code-review/scripts/render_review_report.py +21 -111
  46. package/package.json +1 -1
  47. package/src/manifest.js +8 -3
  48. package/src/scaffold.js +5 -16
  49. package/bundled/skills/prizmkit-code-review/assets/reviewer-role.json +0 -19
  50. package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -120
@@ -2,6 +2,7 @@
2
2
 
3
3
  import json
4
4
  import os
5
+ import re
5
6
  import shutil
6
7
  import subprocess
7
8
  import sys
@@ -811,7 +812,7 @@ def test_session_preamble_writes_redacted_start_command_for_all_launch_profiles(
811
812
  assert str(prompt) not in "\n".join(lines[:6])
812
813
 
813
814
 
814
- def test_headless_review_guidance_uses_risk_routed_dual_layer_loop():
815
+ def test_headless_review_guidance_uses_main_agent_review_loop():
815
816
  headless_guidance_files = [
816
817
  REPO_ROOT / "dev-pipeline" / "templates" / "sections" / "phase-review-full.md",
817
818
  REPO_ROOT / "dev-pipeline" / "templates" / "bootstrap-tier3.md",
@@ -827,32 +828,28 @@ def test_headless_review_guidance_uses_risk_routed_dual_layer_loop():
827
828
 
828
829
  for path in headless_guidance_files:
829
830
  text = path.read_text(encoding="utf-8")
830
- assert "Main-Agent self-review" in text, path
831
- assert "low=0" in text and "medium=1" in text and "high=2" in text, path
832
- assert "Reviewer 3 is forbidden" in text, path
831
+ assert "Main-Agent review loop" in text, path
832
+ assert "up to ten completed rounds" in text, path
833
833
  assert "text final-verdict" in text, path
834
- assert "workspace-equivalent" not in text, path
835
- assert "workspace protocol" not in text, path
836
- assert "current-workspace / active-checkout / no-worktree" not in text, path
837
- assert ".claude/worktrees/..." not in text, path
838
- assert ".prizmkit/state/worktrees/..." not in text, path
839
- assert "USE_WORKTREE" not in text, path
834
+ assert "The current Main Agent is the only Code Review executor" in text, path
835
+ assert "Do not invoke another review skill or review workflow" in text, path
836
+ assert "low=0" not in text and "Reviewer 3" not in text, path
837
+ assert "REVIEW_BLOCKED" not in text, path
838
+ assert "forced-worktree changed-content fallback" not in text, path
840
839
  assert "isolation:" not in text, path
841
840
 
842
841
  skill_text = skill_path.read_text(encoding="utf-8")
843
842
  assert "staged and unstaged tracked changes" in skill_text
844
843
  assert "untracked files" in skill_text
845
844
  assert "accepted = 0" in skill_text
846
- assert "low: 0" in skill_text and "medium: 1" in skill_text and "high: 2" in skill_text
847
- assert "accepted high-severity finding" in skill_text
848
- assert "Do not launch Reviewer 3" in skill_text
845
+ assert "ten completed review rounds" in skill_text
849
846
  assert "## Final Result" in skill_text
850
- assert "BLOCKED" in skill_text
851
- assert "Do not substitute Main-Agent self-review" in skill_text
847
+ assert "PASS | NEEDS_FIXES" in skill_text
848
+ assert "BLOCKED" not in skill_text
849
+ assert "Reviewer 2" not in skill_text
852
850
  assert "reviewer-workspace-protocol.md" not in skill_text
853
851
  assert "reviewer-execution-protocol.md" not in skill_text
854
852
  assert "WORKSPACE_MISMATCH" not in skill_text
855
- assert "REVIEW_INFRASTRUCTURE_BLOCKED" not in skill_text
856
853
 
857
854
 
858
855
  def test_progress_parser_adds_required_metadata(tmp_path):
@@ -952,10 +949,11 @@ def test_progress_parser_normalizes_codebuddy_agent_tools_with_deduplication():
952
949
 
953
950
  assert data["cb_session_id"] == "cb-session"
954
951
  assert data["subagent_provider"] == "codebuddy"
955
- assert data["subagent_spawn_count"] == 2
956
- assert data["active_subagent_count"] == 2
952
+ assert data["subagent_spawn_count"] == 1
953
+ assert data["active_subagent_count"] == 1
957
954
  assert {item["status"] for item in data["subagent_states"]} == {"running"}
958
- assert len(data["subagent_statistics"]["records"]) == 2
955
+ assert len(data["subagent_statistics"]["records"]) == 1
956
+ assert data["subagent_statistics"]["records"][0]["metadata"]["tool"] == "Agent"
959
957
 
960
958
 
961
959
  def test_progress_parser_normalizes_codex_collab_metadata_with_missing_fields():
@@ -1832,14 +1830,18 @@ def test_git_branch_worktree_plans_preserve_shell_invariants(tmp_path):
1832
1830
 
1833
1831
  assert create.name == "branch_create"
1834
1832
  assert any(command.args[:2] == ("checkout", "-b") for command in create.commands)
1835
- assert any(command.args[:2] == ("stash", "push") for command in merge.commands)
1833
+ assert not any(command.args and command.args[0] == "stash" for command in merge.commands)
1834
+ assert any(command.args[:2] == ("status", "--porcelain") for command in merge.commands)
1836
1835
  assert any(command.args[:2] == ("merge", "--ff-only") for command in merge.commands)
1837
- assert any(command.args == ("push",) for command in merge.commands)
1838
- assert save_wip.never_fails is True
1839
- assert ensure.never_fails is True
1836
+ push_index = next(index for index, command in enumerate(merge.commands) if command.args == ("push",))
1837
+ merge_index = next(index for index, command in enumerate(merge.commands) if command.args[:2] == ("merge", "--ff-only"))
1838
+ assert merge_index < push_index
1839
+ assert save_wip.never_fails is False
1840
+ assert ensure.never_fails is False
1840
1841
  assert any(command.args[:2] == ("rebase", "--abort") for command in ensure.commands)
1841
1842
  assert any(command.args[:2] == ("add", "-A") for command in ensure.commands)
1842
- assert not any(command.args[:2] == ("stash", "pop") for command in ensure.commands)
1843
+ assert not any(command.args and command.args[0] == "stash" for command in ensure.commands)
1844
+ assert ensure.never_fails is False
1843
1845
  assert any(".*/worktrees/**" in " ".join(command.args) for command in save_wip.commands)
1844
1846
  assert worktree.commands[0].args[:2] == ("worktree", "add")
1845
1847
 
@@ -1867,6 +1869,205 @@ def test_git_branch_worktree_plans_preserve_shell_invariants(tmp_path):
1867
1869
  assert skipped_wip.results == ()
1868
1870
 
1869
1871
 
1872
+ def test_runtime_source_constructs_no_git_stash_commands():
1873
+ runtime = Path("dev-pipeline/prizmkit_runtime")
1874
+ matches = []
1875
+ for path in runtime.glob("*.py"):
1876
+ text = path.read_text(encoding="utf-8")
1877
+ if re.search(r'["\']stash["\']', text):
1878
+ matches.append(path.as_posix())
1879
+
1880
+ assert matches == []
1881
+
1882
+
1883
+ def _init_merge_repo(project_root):
1884
+ subprocess.run(["git", "init", "-b", "main"], cwd=project_root, check=True, stdout=subprocess.DEVNULL)
1885
+ subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=project_root, check=True)
1886
+ subprocess.run(["git", "config", "user.name", "Test"], cwd=project_root, check=True)
1887
+ manifest = project_root / ".prizmkit" / "manifest.json"
1888
+ manifest.parent.mkdir(parents=True)
1889
+ manifest.write_text('{"version":"current"}\n', encoding="utf-8")
1890
+ (project_root / "app.txt").write_text("base\n", encoding="utf-8")
1891
+ subprocess.run(["git", "add", "."], cwd=project_root, check=True)
1892
+ subprocess.run(["git", "commit", "-m", "base"], cwd=project_root, check=True, stdout=subprocess.DEVNULL)
1893
+
1894
+
1895
+ def _stash_oids(project_root):
1896
+ output = subprocess.run(
1897
+ ["git", "stash", "list", "--format=%H"],
1898
+ cwd=project_root,
1899
+ check=True,
1900
+ stdout=subprocess.PIPE,
1901
+ text=True,
1902
+ ).stdout
1903
+ return tuple(line for line in output.splitlines() if line)
1904
+
1905
+
1906
+ def test_branch_merge_preserves_preexisting_stash_when_workspace_is_clean(tmp_path):
1907
+ from prizmkit_runtime.gitops import BranchContext, branch_merge_plan, run_git_plan
1908
+
1909
+ _init_merge_repo(tmp_path)
1910
+ manifest = tmp_path / ".prizmkit" / "manifest.json"
1911
+ manifest.write_text('{"version":"stale"}\n', encoding="utf-8")
1912
+ subprocess.run(["git", "stash", "push", "-m", "stale-install", "--", ".prizmkit/manifest.json"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1913
+ stale_stashes = _stash_oids(tmp_path)
1914
+ subprocess.run(["git", "checkout", "-b", "dev/example"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1915
+ (tmp_path / "feature.txt").write_text("done\n", encoding="utf-8")
1916
+ subprocess.run(["git", "add", "feature.txt"], cwd=tmp_path, check=True)
1917
+ subprocess.run(["git", "commit", "-m", "feature"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1918
+
1919
+ result = run_git_plan(
1920
+ tmp_path,
1921
+ branch_merge_plan(BranchContext("main", "dev/example", tmp_path)),
1922
+ )
1923
+
1924
+ assert result.ok is True
1925
+ assert _stash_oids(tmp_path) == stale_stashes
1926
+ assert json.loads(manifest.read_text(encoding="utf-8"))["version"] == "current"
1927
+ assert (tmp_path / "feature.txt").read_text(encoding="utf-8") == "done\n"
1928
+
1929
+
1930
+ def test_branch_merge_rejects_dirty_task_checkout_without_touching_stashes(tmp_path):
1931
+ from prizmkit_runtime.gitops import BranchContext, branch_merge_plan, run_git_plan
1932
+
1933
+ _init_merge_repo(tmp_path)
1934
+ manifest = tmp_path / ".prizmkit" / "manifest.json"
1935
+ manifest.write_text('{"version":"stale"}\n', encoding="utf-8")
1936
+ subprocess.run(["git", "stash", "push", "-m", "user-stash", "--", ".prizmkit/manifest.json"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1937
+ stale_stashes = _stash_oids(tmp_path)
1938
+ subprocess.run(["git", "checkout", "-b", "dev/example"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1939
+ (tmp_path / "feature.txt").write_text("done\n", encoding="utf-8")
1940
+ subprocess.run(["git", "add", "feature.txt"], cwd=tmp_path, check=True)
1941
+ subprocess.run(["git", "commit", "-m", "feature"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1942
+ (tmp_path / "app.txt").write_text("local visible change\n", encoding="utf-8")
1943
+
1944
+ result = run_git_plan(
1945
+ tmp_path,
1946
+ branch_merge_plan(BranchContext("main", "dev/example", tmp_path)),
1947
+ )
1948
+
1949
+ assert result.ok is False
1950
+ assert _stash_oids(tmp_path) == stale_stashes
1951
+ assert (tmp_path / "app.txt").read_text(encoding="utf-8") == "local visible change\n"
1952
+ assert json.loads(manifest.read_text(encoding="utf-8"))["version"] == "current"
1953
+ assert subprocess.run(
1954
+ ["git", "branch", "--show-current"],
1955
+ cwd=tmp_path,
1956
+ check=True,
1957
+ stdout=subprocess.PIPE,
1958
+ text=True,
1959
+ ).stdout.strip() == "dev/example"
1960
+
1961
+
1962
+ def test_branch_merge_rebases_committed_task_without_stash_restore_conflict(tmp_path):
1963
+ from prizmkit_runtime.gitops import BranchContext, branch_merge_plan, run_git_plan
1964
+
1965
+ _init_merge_repo(tmp_path)
1966
+ subprocess.run(["git", "checkout", "-b", "dev/example"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1967
+ (tmp_path / "feature.txt").write_text("done\n", encoding="utf-8")
1968
+ subprocess.run(["git", "add", "feature.txt"], cwd=tmp_path, check=True)
1969
+ subprocess.run(["git", "commit", "-m", "feature"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1970
+ subprocess.run(["git", "checkout", "main"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1971
+ (tmp_path / "app.txt").write_text("main changed\n", encoding="utf-8")
1972
+ subprocess.run(["git", "commit", "-am", "advance main"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1973
+ subprocess.run(["git", "checkout", "dev/example"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1974
+
1975
+ result = run_git_plan(
1976
+ tmp_path,
1977
+ branch_merge_plan(BranchContext("main", "dev/example", tmp_path)),
1978
+ )
1979
+
1980
+ assert result.ok is True
1981
+ assert _stash_oids(tmp_path) == ()
1982
+ assert (tmp_path / "app.txt").read_text(encoding="utf-8") == "main changed\n"
1983
+ assert subprocess.run(
1984
+ ["git", "branch", "--show-current"],
1985
+ cwd=tmp_path,
1986
+ check=True,
1987
+ stdout=subprocess.PIPE,
1988
+ text=True,
1989
+ ).stdout.strip() == "main"
1990
+
1991
+
1992
+ def test_branch_return_commits_wip_without_touching_user_stashes(tmp_path):
1993
+ from prizmkit_runtime.gitops import branch_ensure_return
1994
+
1995
+ _init_merge_repo(tmp_path)
1996
+ manifest = tmp_path / ".prizmkit" / "manifest.json"
1997
+ manifest.write_text('{"version":"stale"}\n', encoding="utf-8")
1998
+ subprocess.run(["git", "stash", "push", "-m", "user-stash", "--", ".prizmkit/manifest.json"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
1999
+ user_stashes = _stash_oids(tmp_path)
2000
+ subprocess.run(["git", "checkout", "-b", "dev/interrupted"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
2001
+ (tmp_path / "app.txt").write_text("interrupted work\n", encoding="utf-8")
2002
+
2003
+ result = branch_ensure_return(tmp_path, "main", "dev/interrupted")
2004
+
2005
+ assert result.ok is True
2006
+ assert _stash_oids(tmp_path) == user_stashes
2007
+ assert subprocess.run(
2008
+ ["git", "branch", "--show-current"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True,
2009
+ ).stdout.strip() == "main"
2010
+ assert subprocess.run(
2011
+ ["git", "show", "dev/interrupted:app.txt"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True,
2012
+ ).stdout == "interrupted work\n"
2013
+
2014
+
2015
+ def test_branch_return_commit_failure_does_not_checkout_base(monkeypatch, tmp_path):
2016
+ from prizmkit_runtime import gitops
2017
+
2018
+ calls = []
2019
+
2020
+ def fake_run(_root, args):
2021
+ args = tuple(args)
2022
+ calls.append(args)
2023
+ if args[:3] == ("rev-parse", "--abbrev-ref", "HEAD"):
2024
+ return gitops.GitCommandResult(args, 0, "dev/interrupted\n", "")
2025
+ if args and args[0] == "commit":
2026
+ return gitops.GitCommandResult(args, 1, "", "commit failed")
2027
+ if args[:2] == ("status", "--porcelain"):
2028
+ return gitops.GitCommandResult(args, 0, " M app.txt\n", "")
2029
+ return gitops.GitCommandResult(args, 0, "", "")
2030
+
2031
+ monkeypatch.setattr(gitops, "run_git_command", fake_run)
2032
+
2033
+ result = gitops.branch_ensure_return(tmp_path, "main", "dev/interrupted")
2034
+
2035
+ assert result.ok is False
2036
+ assert not any(args[:2] == ("checkout", "main") for args in calls)
2037
+ assert not any(args and args[0] == "stash" for args in calls)
2038
+
2039
+
2040
+ def test_non_current_reset_preserves_dirty_workspace_and_user_stashes(tmp_path):
2041
+ from prizmkit_runtime.gitops import reset_cleanup_branch
2042
+
2043
+ _init_merge_repo(tmp_path)
2044
+ subprocess.run(["git", "branch", "dev/other"], cwd=tmp_path, check=True)
2045
+ manifest = tmp_path / ".prizmkit" / "manifest.json"
2046
+ manifest.write_text('{"version":"stale"}\n', encoding="utf-8")
2047
+ subprocess.run(["git", "stash", "push", "-m", "user-stash", "--", ".prizmkit/manifest.json"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
2048
+ user_stashes = _stash_oids(tmp_path)
2049
+ (tmp_path / "app.txt").write_text("unstaged\n", encoding="utf-8")
2050
+ (tmp_path / "staged.txt").write_text("staged\n", encoding="utf-8")
2051
+ subprocess.run(["git", "add", "staged.txt"], cwd=tmp_path, check=True)
2052
+ (tmp_path / "untracked.txt").write_text("untracked\n", encoding="utf-8")
2053
+ before = subprocess.run(["git", "status", "--porcelain"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True).stdout
2054
+
2055
+ reset_result = reset_cleanup_branch(tmp_path, "dev/other", return_branch="main", delete=False)
2056
+
2057
+ assert reset_result.branch_preserved is True
2058
+ assert reset_result.checkout_discarded is False
2059
+ assert subprocess.run(["git", "branch", "--show-current"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True).stdout.strip() == "main"
2060
+ assert subprocess.run(["git", "status", "--porcelain"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True).stdout == before
2061
+ assert _stash_oids(tmp_path) == user_stashes
2062
+ assert subprocess.run(["git", "show-ref", "--verify", "refs/heads/dev/other"], cwd=tmp_path, check=False).returncode == 0
2063
+
2064
+ clean_result = reset_cleanup_branch(tmp_path, "dev/other", return_branch="main", delete=True)
2065
+
2066
+ assert clean_result.deleted is True
2067
+ assert subprocess.run(["git", "status", "--porcelain"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True).stdout == before
2068
+ assert _stash_oids(tmp_path) == user_stashes
2069
+
2070
+
1870
2071
  def test_worktree_runtime_context_uses_safe_deterministic_path(tmp_path):
1871
2072
  from prizmkit_runtime.gitops import BranchContext, WorktreePolicy, worktree_runtime_context
1872
2073
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.127",
2
+ "version": "1.1.129",
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.",
@@ -30,10 +30,10 @@
30
30
  "hasScripts": false
31
31
  },
32
32
  "prizmkit-code-review": {
33
- "description": "Independent read-only review with Main-Agent finding adjudication, direct repairs, bounded convergence, and a minimal final report.",
33
+ "description": "Bounded Main-Agent code review with evidence-based finding adjudication, direct repairs, verification, and append-only progress reporting.",
34
34
  "tier": "1",
35
35
  "category": "prizmkit-skill",
36
- "hasAssets": true,
36
+ "hasAssets": false,
37
37
  "hasScripts": true
38
38
  },
39
39
  "prizmkit-committer": {
@@ -361,8 +361,8 @@ Key requirements:
361
361
  - descriptions: minimum 15 words (error), recommended minimum 30/50/80/100+ for low/medium/high/critical (warning). No upper limit — more detail prevents AI guessing
362
362
  - `estimated_complexity` determines pipeline execution tier:
363
363
  - `low` / `medium` → **lite** (single agent, no subagents)
364
- - `high` → **standard** (orchestrator + reviewer guardrails, 3-agent metadata)
365
- - `critical` → **full** (strongest orchestrator/reviewer guardrails). Use for: architectural changes touching 10+ files, cross-module refactoring with API surface changes, or safety/security/data-loss risk
364
+ - `high` → **standard** (Main-Agent review guardrails, 3-agent compatibility metadata)
365
+ - `critical` → **full** (strongest Main-Agent review guardrails). Use for: architectural changes touching 10+ files, cross-module refactoring with API surface changes, or safety/security/data-loss risk
366
366
 
367
367
  **IMPORTANT: Do NOT hand-write the final JSON file.** Instead:
368
368
  1. Write a draft JSON to a temporary path (e.g., `.prizmkit/plans/feature-list.draft.json`)
@@ -110,7 +110,7 @@ PrizmKit supports any development scenario through the same skill chain. `/prizm
110
110
  | `/prizmkit-plan` | First implementation planning step: run ahead of `/prizmkit-implement` to turn natural language into `spec.md` + `plan.md` with executable tasks. | "specify", "plan", "new task", "architect", "break it down" |
111
111
  | `/prizmkit-implement` | Implementation step: use after `/prizmkit-plan` to execute `plan.md` tasks with TDD where applicable, task order, and checkpoints. | "implement", "build", "code it", "start coding" |
112
112
  | `/prizmkit-test` | Risk-triggered quality gate: run after implementation when behavior, interfaces, data, security, or deploy risk requires tests and boundary coverage. | "test", "run tests", "verify", "quality check", "boundary tests" |
113
- | `/prizmkit-code-review` | Full path quality gate: run after implementation; requires the dedicated reviewer agent in the active checkout and stops if that launch mode is unavailable. | "review", "check code", "code review", "is it ready to commit" |
113
+ | `/prizmkit-code-review` | Full path quality gate: the current Main Agent reviews and repairs the complete change in the active checkout without direct or indirect review delegation. | "review", "check code", "code review", "is it ready to commit" |
114
114
  | `/prizmkit-retrospective` | Docs maintenance step: run after review/implementation when structure, interfaces, dependencies, behavior, or durable knowledge changed. | "retrospective", "retro", "update docs", "sync docs", "wrap up" |
115
115
  | `/prizmkit-committer` | Final lifecycle commit step: use after required gates are satisfied; safely stages and creates a Conventional Commit without changing changelog by default. | "commit", "submit", "finish", "done" |
116
116
  | `/prizmkit-prizm-docs` | Documentation system entry point: use for init/status/rebuild/validate/migrate or out-of-band repair, not normal development sync. | "initialize docs", "check docs", "rebuild docs", "validate docs", "docs drifted" |
@@ -1,16 +1,25 @@
1
1
  ---
2
2
  name: "prizmkit-code-review"
3
- description: "Run a risk-routed dual-layer code review against the current spec, plan, workspace changes, applicable rules, contracts, and test evidence. The Main Agent first self-reviews and repairs for up to ten rounds, then semantic risk determines whether zero, one, or two fresh read-only independent Reviewers are required. Findings remain Main-Agent adjudicated, Reviewer 3 is forbidden, and one append-only progress report records the execution through PASS, NEEDS_FIXES, or BLOCKED. (project)"
3
+ description: "Review the complete current change in a bounded Main-Agent loop. Adjudicate findings with evidence, directly repair accepted findings, verify repairs, and append progress until the review converges to PASS or stops with unresolved findings as NEEDS_FIXES. (project)"
4
4
  ---
5
5
 
6
6
  # PrizmKit Code Review
7
7
 
8
- Use a dual-layer review loop: the Main Agent owns iterative review and repair, while fresh independent Reviewers act only as semantic-risk gates.
8
+ Use one Main-Agent review loop. The current Main Agent is the only Code Review executor: it performs the complete review, filters candidate findings, repairs accepted findings, verifies the repairs, and decides the final result.
9
+
10
+ ## Execution Boundary
11
+
12
+ - Do not delegate any part of Code Review directly or indirectly.
13
+ - Do not invoke another review skill or review workflow from inside this skill.
14
+ - Do not launch review work through a general-purpose execution unit or relabel it as a finder, verifier, audit, compatibility review, verification, or gap sweep.
15
+ - These restrictions apply for the entire review phase, including candidate discovery, evidence checks, repair verification, and final gap analysis.
16
+ - The Main Agent may directly use non-delegating read, search, edit, and test capabilities in the active workspace.
17
+ - `{artifact_dir}/review-report.md` is the only persisted review artifact. Do not append separate Review Notes to `context-snapshot.md`.
9
18
 
10
19
  ## When to Use
11
20
 
12
21
  - After `/prizmkit-implement` as the Full path quality gate
13
- - For Fast path when behavior, risk, or the user warrants review
22
+ - For Fast path when behavior, impact, or the user warrants review
14
23
  - When the user asks to validate implementation, find defects, assess regressions, or decide commit readiness
15
24
 
16
25
  ## Input
@@ -19,167 +28,101 @@ Use a dual-layer review loop: the Main Agent owns iterative review and repair, w
19
28
  |---|---|---|
20
29
  | `artifact_dir` | No | Directory containing `spec.md` and `plan.md`. Reuse a caller-provided directory; otherwise locate the current completed change artifact. |
21
30
 
22
- ## Required Assets
31
+ ## Required Asset
23
32
 
24
- - `${SKILL_DIR}/references/reviewer-agent-prompt.md`: independent Reviewer input and output contract
25
33
  - `${SKILL_DIR}/references/review-report-template.md`: report lifecycle and append contract
26
- - `${SKILL_DIR}/assets/reviewer-role.json`: semantic read-only and non-delegating Reviewer boundary
27
-
28
- Do not weaken or summarize the Reviewer prompt. The protocol specifies semantic capabilities rather than platform-specific tool names.
29
34
 
30
35
  ## Phase 0: Initialize Report and Collect Context
31
36
 
32
37
  1. Resolve `{artifact_dir}` and `{artifact_dir}/review-report.md`.
33
- 2. replace any prior report with a new execution header using the report template. The new report begins with `## Status: IN_PROGRESS` and contains no prior Final Result.
38
+ 2. At the start of every execution, replace any prior report with a new execution header using the report template. The new report begins with `## Status: IN_PROGRESS` and contains no prior Final Result.
34
39
  3. Read `spec.md`, `plan.md`, relevant `/prizmkit-test` evidence, `.prizmkit/prizm-docs/root.prizm`, applicable progressive docs, and project rules.
35
- 4. Inspect and capture the complete current Git change:
40
+ 4. Inspect the complete current Git change:
36
41
  - staged and unstaged tracked changes;
37
42
  - untracked files;
38
43
  - deleted and renamed files;
39
44
  - relevant unchanged callers, dependents, contracts, and tests.
40
- 5. Preserve the existing Reviewer input behavior: staged and unstaged Git diffs, full content of every untracked file, and explicit deleted/renamed states.
41
- 6. If no changes exist, append risk `low` and exactly one final result with `PASS`, then finish without a Reviewer.
42
-
43
- ### Checkout Access
44
-
45
- Prefer direct access to the active checkout. If the platform forces an isolated worktree, provide the same staged and unstaged diffs, untracked file contents, and changed-path states; use the worktree only for baseline and surrounding-context reads. Do not require workspace-equivalence proof.
46
-
47
- ## Phase 1: Semantic Risk Assessment
48
-
49
- Classify the current change from behavior and failure impact, not changed-file count or a fixed path allowlist:
50
-
51
- - `low: 0` independent Reviewers — documentation, test text, mechanical change, local low-impact configuration, or trivially verifiable behavior.
52
- - `medium: 1` independent Reviewer — general business behavior, internal interface changes, or non-critical data processing with user-visible regression potential.
53
- - `high: 2` independent Reviewers maximum — payments, financial ledgers, authentication, authorization, security, migration, concurrent transactions, irreversible data operations, or public contracts.
54
-
55
- Mixed risks use the highest applicable level. A large mechanical diff is not automatically high; a small money or authorization change is high.
45
+ 5. Review in the active workspace so dirty and untracked content is authoritative.
46
+ 6. If no changes exist, append final verification and exactly one final result with `PASS`, then finish.
56
47
 
57
- Append `## Risk Assessment` with the selected risk and concrete reasons before review begins.
48
+ ## Phase 1: Main-Agent Review Loop
58
49
 
59
- ## Phase 2: Main-Agent Self-Review Loop
50
+ The Main Agent reviews and repairs in the current context. The fixed limit is ten completed review rounds.
60
51
 
61
- The Main Agent reviews and repairs in the current context. Track Main-Agent rounds independently from Reviewer launch attempts:
52
+ Track cumulative counts:
62
53
 
63
54
  ```yaml
64
55
  main_review_rounds: 0
65
- independent_reviewers_started: 0
66
- reviewer_1_accepted_high: false
56
+ accepted_findings: 0
57
+ fixed_findings: 0
58
+ rejected_findings: 0
59
+ unresolved_findings: 0
67
60
  ```
68
61
 
69
- Every Reviewer Agent launch attempt increments `independent_reviewers_started`, including a retry that starts a new Agent. The total may never exceed the semantic-risk limit.
70
-
71
- ### Main-Agent Self-Review Loop
62
+ ### Review One Round
72
63
 
73
64
  Each round examines the complete current change against goals, contracts, rules, callers, dependents, regression risks, and test evidence.
74
65
 
75
- 1. Identify concrete candidate findings.
76
- 2. Classify each as:
77
- - `accepted`: evidence supports the failure scenario;
78
- - `rejected`: code or governing evidence disproves it or its regression path.
79
- 3. Append `## Main Review Round N` with findings, accepted, rejected, and next action.
80
- 4. Apply these rules:
66
+ 1. Identify concrete candidate findings. A finding must describe a reproducible failure scenario, affected behavior, and supporting evidence.
67
+ 2. Classify each candidate as exactly one of:
68
+ - `accepted`: concrete evidence supports the failure scenario and an in-scope repair is required;
69
+ - `rejected`: code, tests, contracts, or governing evidence disproves the failure scenario;
70
+ - `unresolved`: correctness cannot be established or repaired safely with the available evidence or environment.
71
+ 3. Treat Missing tools, permissions, environment, or required evidence as an unresolved finding when they prevent required verification. Do not treat missing evidence as success.
72
+ 4. Append `## Main Review Round N` with findings, accepted, rejected, unresolved, and the next action.
73
+ 5. Apply these rules:
81
74
 
82
75
  ```text
83
- accepted = 0 -> self-review converged
84
- accepted > 0 and round < 10 -> Main Agent directly repairs, verifies, and continues
85
- accepted > 0 at ten completed Main-Agent rounds -> NEEDS_FIXES
86
- repair cannot be completed safely -> NEEDS_FIXES
87
- unresolved new in-scope test failure -> NEEDS_FIXES
76
+ accepted = 0 and unresolved = 0 -> review converged
77
+ accepted > 0 and round < 10 -> Main Agent directly repairs, verifies, and continues
78
+ accepted > 0 at ten completed review rounds -> NEEDS_FIXES
79
+ unresolved > 0 -> NEEDS_FIXES
80
+ repair cannot be completed safely -> unresolved finding -> NEEDS_FIXES
81
+ required verification fails or cannot be performed -> unresolved finding -> NEEDS_FIXES
88
82
  ```
89
83
 
90
- When all findings are rejected, `accepted = 0` and the phase converges. Main-Agent rounds never increase the independent Reviewer counter. The fixed limit is ten completed Main-Agent rounds.
91
-
92
- After each repair batch, append `## Repair Verification` with fixed findings, verification evidence, and next phase.
93
-
94
- ## Phase 3: Independent Reviewer 1
95
-
96
- After Main-Agent self-review and required tests converge:
84
+ When all candidate findings are rejected, `accepted = 0` and `unresolved = 0`, so the review converges. Rejected findings do not cause another round.
97
85
 
98
- - low risk: skip all independent Reviewers and proceed to final verification;
99
- - medium or high risk: launch Reviewer 1.
86
+ ## Phase 2: Repair and Verification
100
87
 
101
- Before launch, append:
102
-
103
- ```markdown
104
- ## Independent Reviewer 1
105
-
106
- - Status: RUNNING
107
- - Risk Trigger: <medium|high>
108
- ```
88
+ When a round has accepted findings and fewer than ten rounds have completed:
109
89
 
110
- Launch exactly one fresh foreground Reviewer using the unchanged prompt and role. Do not provide previous review findings, filtering decisions, rejection reasons, or repair explanations.
90
+ 1. Main Agent directly repairs every accepted in-scope finding in the active workspace.
91
+ 2. Run targeted tests, static checks, or other verification appropriate to each repaired behavior.
92
+ 3. Inspect resulting changes and ensure the repair did not introduce a new regression.
93
+ 4. Append `## Repair Verification` with fixed findings, verification evidence, and the next round.
94
+ 5. Start the next complete review round.
111
95
 
112
- ### Reviewer Infrastructure Failure
96
+ If a repair is unsafe, incomplete, or cannot receive required verification, record the affected finding as unresolved and finish with `NEEDS_FIXES`.
113
97
 
114
- If the Reviewer cannot start, exits abnormally, returns unusable output, or lacks essential context:
115
-
116
- 1. append the observable failure;
117
- 2. count the failed launch attempt against the semantic-risk Reviewer limit;
118
- 3. allow at most one infrastructure retry at this same Reviewer position only when the risk limit still has an unused launch;
119
- 4. append a new RUNNING retry section before retrying and increment the Reviewer launch counter;
120
- 5. if the retry fails or the risk limit is exhausted, append Final Result `BLOCKED` and stop;
121
- 6. do not convert infrastructure failure into a code finding;
122
- 7. Do not substitute Main-Agent self-review for a required independent result.
123
-
124
- ### Finding Adjudication
125
-
126
- For a usable Reviewer result, append `## Independent Reviewer 1 Result`, then classify every finding as accepted or rejected with evidence.
127
-
128
- ```text
129
- accepted = 0 -> Reviewer 1 converged
130
- accepted > 0 -> Main Agent repairs, verifies, and reruns its self-review loop
131
- ```
132
-
133
- Accepted findings do not automatically trigger another independent Reviewer.
134
-
135
- ## Phase 4: Reviewer 2 Eligibility
136
-
137
- Reviewer 2 is allowed only when every condition is true:
138
-
139
- - risk is `high`;
140
- - Reviewer 1 contained at least one accepted high-severity finding;
141
- - all accepted high findings were repaired;
142
- - targeted verification passed;
143
- - Main-Agent self-review reconverged.
144
-
145
- Accepted medium or low findings alone never trigger Reviewer 2. Medium risk never starts Reviewer 2.
146
-
147
- When eligible, append a RUNNING section and launch one fresh Reviewer 2 with the unchanged complete-review prompt and current change input.
148
-
149
- After Reviewer 2:
150
-
151
- - accepted = 0: proceed to final verification;
152
- - accepted > 0: Main Agent repairs, verifies, and runs its final self-review loop;
153
- - unresolved repair: `NEEDS_FIXES`;
154
- - Do not launch Reviewer 3 under any condition.
155
-
156
- ## Phase 5: Append-Only Reporting
98
+ ## Phase 3: Append-Only Reporting
157
99
 
158
100
  `{artifact_dir}/review-report.md` is the only required persisted review artifact.
159
101
 
160
102
  Within one execution, append new sections only. Do not rewrite an earlier progress section. Append after:
161
103
 
162
- - risk assessment;
163
104
  - every Main-Agent review round;
164
105
  - every repair and verification batch;
165
- - every Reviewer launch;
166
- - every Reviewer result and adjudication;
167
- - every infrastructure retry;
168
- - final verification.
106
+ - final verification;
107
+ - the final result.
108
+
109
+ An interrupted execution remains `IN_PROGRESS` and shows its latest completed phase. It has no terminal verdict.
169
110
 
170
- A RUNNING section is not edited after completion; append a separate result section. An interrupted execution remains `IN_PROGRESS` and shows its latest running or completed phase.
111
+ ## Phase 4: Final Verification and Result
171
112
 
172
- ## Phase 6: Final Result
113
+ Before completing:
173
114
 
174
- Append exactly one final result:
115
+ 1. Confirm the final workspace still represents the complete reviewed change.
116
+ 2. Confirm required tests and checks have credible evidence.
117
+ 3. Confirm no accepted or unresolved finding remains for `PASS`.
118
+ 4. Append `## Final Verification`.
119
+ 5. Append exactly one final result:
175
120
 
176
121
  ```markdown
177
122
  ## Final Result
178
123
 
179
- - Verdict: PASS | NEEDS_FIXES | BLOCKED
180
- - Risk: low | medium | high
124
+ - Verdict: PASS | NEEDS_FIXES
181
125
  - Main Review Rounds: <count>
182
- - Independent Reviewers Started: <count>
183
126
  - Accepted Findings: <count>
184
127
  - Fixed Findings: <count>
185
128
  - Rejected Findings: <count>
@@ -189,9 +132,8 @@ Append exactly one final result:
189
132
 
190
133
  Final outcomes:
191
134
 
192
- - `PASS`: Main-Agent review converged, every required independent review completed, and no accepted finding remains unresolved.
193
- - `NEEDS_FIXES`: Main-Agent round ten still has accepted findings, a repair is unsafe, or verification remains unresolved.
194
- - `BLOCKED`: a required independent Reviewer position failed and either its one permitted retry failed or the semantic-risk launch limit left no retry capacity; essential independent-review context is unavailable.
135
+ - `PASS`: review converged with `accepted = 0`, `unresolved = 0`, and required verification evidence is complete.
136
+ - `NEEDS_FIXES`: round ten still has accepted findings, any finding remains unresolved, a repair cannot be completed safely, or required verification is unavailable or failed.
195
137
 
196
138
  Exactly one final result is allowed. Do not append progress after Final Result.
197
139
 
@@ -199,4 +141,3 @@ Completion handoff:
199
141
 
200
142
  - `PASS`: run `/prizmkit-retrospective` when structural docs or durable knowledge changed; otherwise proceed to `/prizmkit-committer`.
201
143
  - `NEEDS_FIXES`: report unresolved findings and stop.
202
- - `BLOCKED`: report infrastructure evidence and permit recovery.