prizmkit 1.1.131 → 1.1.134

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 (65) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/claude/command-adapter.js +0 -2
  3. package/bundled/dev-pipeline/assets/skill-subagent-integration.md +11 -6
  4. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +2 -9
  5. package/bundled/dev-pipeline/prizmkit_runtime/processes.py +21 -1
  6. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +104 -17
  7. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +3 -2
  8. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +15 -13
  9. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +3 -13
  10. package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +5 -4
  11. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +1 -1
  12. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +4 -4
  13. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +9 -9
  14. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +4 -7
  15. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +3 -3
  16. package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +2 -2
  17. package/bundled/dev-pipeline/templates/sections/bugfix-phase-manual-verification.md +5 -10
  18. package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +5 -5
  19. package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +1 -1
  20. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
  21. package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +2 -3
  22. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +2 -2
  23. package/bundled/dev-pipeline/templates/sections/phase-commit.md +2 -2
  24. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +5 -5
  25. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +5 -5
  26. package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +1 -1
  27. package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +5 -5
  28. package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +1 -1
  29. package/bundled/dev-pipeline/templates/sections/subagent-timeout-recovery.md +1 -1
  30. package/bundled/dev-pipeline/templates/sections/task-contract.md +4 -0
  31. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +39 -26
  32. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +7 -10
  33. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +3 -3
  34. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +156 -5
  35. package/bundled/dev-pipeline/tests/test_unified_cli.py +34 -7
  36. package/bundled/skills/_metadata.json +3 -3
  37. package/bundled/skills/prizmkit/references/workflow-state-protocol.md +3 -3
  38. package/bundled/skills/prizmkit-code-review/SKILL.md +22 -6
  39. package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +243 -0
  40. package/bundled/skills/prizmkit-code-review/references/review-report-template.md +41 -0
  41. package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +3 -3
  42. package/bundled/skills/prizmkit-code-review/scripts/render_review_report.py +93 -1
  43. package/bundled/skills/prizmkit-committer/SKILL.md +6 -13
  44. package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +3 -3
  45. package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +3 -3
  46. package/bundled/skills/prizmkit-plan/SKILL.md +17 -3
  47. package/bundled/skills/prizmkit-plan/assets/plan-template.md +18 -0
  48. package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +242 -0
  49. package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +4 -4
  50. package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +3 -3
  51. package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +3 -3
  52. package/bundled/skills/prizmkit-test/SKILL.md +25 -1
  53. package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +63 -12
  54. package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +1 -1
  55. package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +13 -0
  56. package/bundled/skills/prizmkit-test/references/evidence-protocol.md +6 -1
  57. package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +8 -1
  58. package/bundled/skills/prizmkit-test/references/test-generation-steps.md +4 -1
  59. package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +15 -0
  60. package/bundled/skills/prizmkit-test/references/workflow-state-protocol.md +3 -3
  61. package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +744 -23
  62. package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +194 -15
  63. package/bundled/skills/prizmkit-workflow/SKILL.md +1 -1
  64. package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +3 -3
  65. package/package.json +1 -1
@@ -3,6 +3,7 @@
3
3
  import json
4
4
  import os
5
5
  import shutil
6
+ import signal
6
7
  import subprocess
7
8
  import sys
8
9
  from pathlib import Path
@@ -1959,26 +1960,29 @@ def test_completed_checkout_blocks_rerun_until_explicit_reset(monkeypatch, tmp_p
1959
1960
  runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
1960
1961
 
1961
1962
 
1962
- def test_no_worktree_interrupt_saves_wip_and_returns_to_base(monkeypatch, tmp_path):
1963
+ def test_no_worktree_interrupt_saves_wip_and_returns_to_base(monkeypatch, tmp_path, capsys):
1963
1964
  from prizmkit_runtime import runners
1965
+ from prizmkit_runtime.gitops import current_branch as real_current_branch
1966
+ from prizmkit_runtime.gitops import run_git_command as real_run_git_command
1964
1967
  from prizmkit_runtime.runner_models import family_for, parse_invocation
1965
1968
  from prizmkit_runtime.task_checkout import load_task_checkout
1966
1969
 
1967
1970
  monkeypatch.setenv("DEV_BRANCH", "dev/F-001-interrupt")
1968
1971
  paths = _make_paths(tmp_path)
1972
+ _init_bookkeeping_repo(paths.project_root)
1969
1973
  family = family_for("feature", paths)
1970
1974
  invocation = parse_invocation(family, "run", ())
1971
1975
  invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
1972
1976
  _install_runner_session_fakes(monkeypatch, runners)
1973
- ensure_calls = []
1974
- monkeypatch.setattr(runners, "run_git_plan", lambda project_root, plan: SimpleNamespace(ok=True, plan=plan, results=()))
1975
- monkeypatch.setattr(runners, "branch_ensure_return", lambda project_root, base, branch: ensure_calls.append((base, branch)))
1977
+ monkeypatch.setattr(runners, "current_branch", real_current_branch)
1978
+ monkeypatch.setattr(runners, "run_git_command", real_run_git_command)
1976
1979
 
1977
1980
  class InterruptingLauncher:
1978
1981
  def __init__(self, config):
1979
1982
  self.config = config
1980
1983
 
1981
1984
  def run(self):
1985
+ (self.config.cwd / "interrupted.txt").write_text("preserved\n", encoding="utf-8")
1982
1986
  raise KeyboardInterrupt
1983
1987
 
1984
1988
  monkeypatch.setattr(runners, "AISessionLauncher", InterruptingLauncher)
@@ -1987,11 +1991,158 @@ def test_no_worktree_interrupt_saves_wip_and_returns_to_base(monkeypatch, tmp_pa
1987
1991
  runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
1988
1992
 
1989
1993
  checkout = load_task_checkout(family.state_dir, family.task_type, "F-001")
1994
+ captured = capsys.readouterr()
1990
1995
  assert checkout is not None
1991
1996
  assert checkout.is_active
1992
1997
  assert checkout.active_dev_branch == "dev/F-001-interrupt"
1993
1998
  assert checkout.base_branch == "main"
1994
- assert ensure_calls == [("main", "dev/F-001-interrupt")]
1999
+ assert real_current_branch(paths.project_root) == "main"
2000
+ assert subprocess.run(
2001
+ ["git", "show", "dev/F-001-interrupt:interrupted.txt"],
2002
+ cwd=paths.project_root,
2003
+ check=True,
2004
+ stdout=subprocess.PIPE,
2005
+ text=True,
2006
+ ).stdout == "preserved\n"
2007
+ assert "Interrupted task F-001: work preserved and returned to main" in captured.err
2008
+
2009
+
2010
+ def test_interrupt_return_failure_is_reported_without_forcing_checkout(monkeypatch, tmp_path, capsys):
2011
+ from prizmkit_runtime import runners
2012
+ from prizmkit_runtime.runner_models import family_for, parse_invocation
2013
+
2014
+ monkeypatch.setenv("DEV_BRANCH", "dev/F-001-interrupt")
2015
+ paths = _make_paths(tmp_path)
2016
+ family = family_for("feature", paths)
2017
+ invocation = parse_invocation(family, "run", ())
2018
+ invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
2019
+ _install_runner_session_fakes(monkeypatch, runners)
2020
+ monkeypatch.setattr(runners, "run_git_plan", lambda project_root, plan: SimpleNamespace(ok=True, plan=plan, results=()))
2021
+ failure = SimpleNamespace(
2022
+ ok=False,
2023
+ plan=SimpleNamespace(
2024
+ commands=(
2025
+ SimpleNamespace(allow_failure=True),
2026
+ SimpleNamespace(allow_failure=False),
2027
+ )
2028
+ ),
2029
+ results=(
2030
+ SimpleNamespace(
2031
+ args=("commit", "--no-verify", "-m", "wip"),
2032
+ return_code=1,
2033
+ stdout="nothing to commit",
2034
+ stderr="",
2035
+ ),
2036
+ SimpleNamespace(
2037
+ args=("checkout", "main"),
2038
+ return_code=1,
2039
+ stdout="",
2040
+ stderr="untracked files would be overwritten",
2041
+ ),
2042
+ ),
2043
+ )
2044
+ monkeypatch.setattr(runners, "branch_ensure_return", lambda project_root, base, branch: failure)
2045
+
2046
+ class InterruptingLauncher:
2047
+ def __init__(self, config):
2048
+ self.config = config
2049
+
2050
+ def run(self):
2051
+ raise KeyboardInterrupt
2052
+
2053
+ monkeypatch.setattr(runners, "AISessionLauncher", InterruptingLauncher)
2054
+
2055
+ with pytest.raises(KeyboardInterrupt):
2056
+ runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
2057
+
2058
+ captured = capsys.readouterr()
2059
+ assert "Could not safely return to main; leaving dev/F-001-interrupt active" in captured.err
2060
+ assert "git checkout main failed: untracked files would be overwritten" in captured.err
2061
+ assert "After resolving the Git blocker, run: git checkout main" in captured.err
2062
+
2063
+
2064
+ def test_worktree_interrupt_preserves_task_worktree_without_returning_caller_checkout(monkeypatch, tmp_path, capsys):
2065
+ from prizmkit_runtime import runners
2066
+ from prizmkit_runtime.runner_models import family_for, parse_invocation
2067
+
2068
+ monkeypatch.setenv("USE_WORKTREE", "1")
2069
+ monkeypatch.setenv("DEV_BRANCH", "dev/F-001-interrupt")
2070
+ paths = _make_paths(tmp_path)
2071
+ family = family_for("feature", paths)
2072
+ invocation = parse_invocation(family, "run", ())
2073
+ invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
2074
+ observed = _install_runner_session_fakes(monkeypatch, runners)
2075
+ monkeypatch.setattr(
2076
+ runners,
2077
+ "ensure_linked_worktree",
2078
+ lambda runtime: SimpleNamespace(ok=True, runtime=runtime, reason=""),
2079
+ )
2080
+ return_calls = []
2081
+ monkeypatch.setattr(
2082
+ runners,
2083
+ "branch_ensure_return",
2084
+ lambda *args: return_calls.append(args),
2085
+ )
2086
+
2087
+ class InterruptingLauncher:
2088
+ def __init__(self, config):
2089
+ self.config = config
2090
+
2091
+ def run(self):
2092
+ raise KeyboardInterrupt
2093
+
2094
+ monkeypatch.setattr(runners, "AISessionLauncher", InterruptingLauncher)
2095
+
2096
+ with pytest.raises(KeyboardInterrupt):
2097
+ runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
2098
+
2099
+ captured = capsys.readouterr()
2100
+ assert observed.wip_calls
2101
+ assert return_calls == []
2102
+ assert "Interrupted task F-001: work preserved in" in captured.err
2103
+ assert "task worktree remains active" in captured.err
2104
+
2105
+
2106
+ def test_run_pipeline_command_bridges_sigterm_and_restores_handler(monkeypatch, tmp_path):
2107
+ from prizmkit_runtime import runners
2108
+ from prizmkit_runtime.runner_models import PipelineRunResult
2109
+
2110
+ paths = _make_paths(tmp_path)
2111
+ paths.feature_plan.write_text("{}", encoding="utf-8")
2112
+ previous = signal.getsignal(signal.SIGTERM)
2113
+ observed = []
2114
+
2115
+ def interrupted_pipeline(*args, **kwargs):
2116
+ installed = signal.getsignal(signal.SIGTERM)
2117
+ observed.append(installed)
2118
+ try:
2119
+ installed(signal.SIGTERM, None)
2120
+ except KeyboardInterrupt:
2121
+ return PipelineRunResult(False, 1, "interrupted", "interrupted")
2122
+ raise AssertionError("SIGTERM handler did not interrupt the pipeline")
2123
+
2124
+ monkeypatch.setattr(runners, "_run_pipeline", interrupted_pipeline)
2125
+
2126
+ result = runners.run_pipeline_command("feature", "run", (), paths)
2127
+
2128
+ assert result.exit_code == 1
2129
+ assert result.message == "processed=1 completed=False stopped_reason=interrupted"
2130
+ assert observed and observed[0] not in {previous, signal.SIG_DFL, signal.SIG_IGN}
2131
+ assert signal.getsignal(signal.SIGTERM) is previous
2132
+
2133
+
2134
+ def test_interruption_cleanup_shield_ignores_and_restores_signals():
2135
+ from prizmkit_runtime.processes import shield_interruption_signals
2136
+
2137
+ previous_sigint = signal.getsignal(signal.SIGINT)
2138
+ previous_sigterm = signal.getsignal(signal.SIGTERM)
2139
+
2140
+ with shield_interruption_signals():
2141
+ assert signal.getsignal(signal.SIGINT) is signal.SIG_IGN
2142
+ assert signal.getsignal(signal.SIGTERM) is signal.SIG_IGN
2143
+
2144
+ assert signal.getsignal(signal.SIGINT) is previous_sigint
2145
+ assert signal.getsignal(signal.SIGTERM) is previous_sigterm
1995
2146
 
1996
2147
 
1997
2148
  @pytest.mark.parametrize(
@@ -828,13 +828,12 @@ def test_headless_review_guidance_uses_main_agent_review_loop():
828
828
 
829
829
  for path in headless_guidance_files:
830
830
  text = path.read_text(encoding="utf-8")
831
- assert "Main-Agent review loop" in text, path
831
+ assert "mandatory Main-Agent review" in text, path
832
832
  assert "up to ten completed rounds" in text, path
833
833
  assert "text final-verdict" 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
834
+ assert "strict structural capability gate" in text, path
835
+ assert "skill-owned independent Reviewer" in text, path
836
836
  assert "low=0" not in text and "Reviewer 3" not in text, path
837
- assert "REVIEW_BLOCKED" not in text, path
838
837
  assert "forced-worktree changed-content fallback" not in text, path
839
838
  assert "isolation:" not in text, path
840
839
 
@@ -843,9 +842,11 @@ def test_headless_review_guidance_uses_main_agent_review_loop():
843
842
  assert "untracked, deleted, and renamed files" in skill_text
844
843
  assert "accepted = 0" in skill_text
845
844
  assert "ten completed review rounds" in skill_text
845
+ assert "## Phase 3: Independent Code Review" in skill_text
846
+ assert "maximum five Reviewer responses" in skill_text
846
847
  assert "## Final Result" in skill_text
847
848
  assert "PASS | NEEDS_FIXES" in skill_text
848
- assert "BLOCKED" not in skill_text
849
+ assert "Verdict: <PASS | NEEDS_FIXES | BLOCKED>" not in skill_text
849
850
  assert "Reviewer 2" not in skill_text
850
851
  assert "reviewer-workspace-protocol.md" not in skill_text
851
852
  assert "reviewer-execution-protocol.md" not in skill_text
@@ -2012,6 +2013,32 @@ def test_branch_return_commits_wip_without_touching_user_stashes(tmp_path):
2012
2013
  ).stdout == "interrupted work\n"
2013
2014
 
2014
2015
 
2016
+ def test_branch_return_ignores_installed_runtime_paths_without_blocking_wip_commit(tmp_path):
2017
+ from prizmkit_runtime.gitops import branch_ensure_return
2018
+
2019
+ _init_merge_repo(tmp_path)
2020
+ (tmp_path / ".gitignore").write_text(".prizmkit/*\n.claude/\n", encoding="utf-8")
2021
+ subprocess.run(["git", "add", ".gitignore"], cwd=tmp_path, check=True)
2022
+ subprocess.run(["git", "commit", "-m", "ignore installed runtime"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
2023
+ runtime_file = tmp_path / ".prizmkit" / "dev-pipeline" / "cli.py"
2024
+ runtime_file.parent.mkdir(parents=True)
2025
+ runtime_file.write_text("# installed runtime\n", encoding="utf-8")
2026
+ manifest = tmp_path / ".prizmkit" / "manifest.json"
2027
+ manifest.write_text('{}\n', encoding="utf-8")
2028
+ subprocess.run(["git", "checkout", "-b", "dev/interrupted"], cwd=tmp_path, check=True, stdout=subprocess.DEVNULL)
2029
+ (tmp_path / "interrupted.txt").write_text("preserved\n", encoding="utf-8")
2030
+
2031
+ result = branch_ensure_return(tmp_path, "main", "dev/interrupted")
2032
+
2033
+ assert result.ok is True
2034
+ assert subprocess.run(
2035
+ ["git", "branch", "--show-current"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True,
2036
+ ).stdout.strip() == "main"
2037
+ assert subprocess.run(
2038
+ ["git", "show", "dev/interrupted:interrupted.txt"], cwd=tmp_path, check=True, stdout=subprocess.PIPE, text=True,
2039
+ ).stdout == "preserved\n"
2040
+
2041
+
2015
2042
  def test_branch_return_commit_failure_does_not_checkout_base(monkeypatch, tmp_path):
2016
2043
  from prizmkit_runtime import gitops
2017
2044
 
@@ -2200,8 +2227,8 @@ def test_git_status_safe_ignores_worktree_support_assets(monkeypatch, tmp_path):
2200
2227
  joined = " ".join(status_args)
2201
2228
  assert ":(top,exclude).prizmkit-worktree" in status_args
2202
2229
  assert ":(top,exclude).claude" in status_args
2203
- assert ":(top,exclude).prizmkit/dev-pipeline" in status_args
2204
- assert ":(top,exclude,glob).prizmkit/dev-pipeline/**" in status_args
2230
+ assert ":(top,exclude).prizmkit" in status_args
2231
+ assert ":(top,exclude,glob).prizmkit/**" in status_args
2205
2232
  assert all(exclude in status_args for exclude in HIDDEN_TOOL_WORKTREE_EXCLUDES)
2206
2233
  assert ".prizmkit-worktree" in joined
2207
2234
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.131",
2
+ "version": "1.1.134",
3
3
  "skills": {
4
4
  "prizmkit": {
5
5
  "description": "Framework introduction and navigation for the formal single-requirement lifecycle, project initialization, Prizm docs, and independent deployment.",
@@ -23,7 +23,7 @@
23
23
  "hasScripts": false
24
24
  },
25
25
  "prizmkit-plan": {
26
- "description": "Formal requirement lifecycle entry: natural language → reviewed spec.md and plan.md with stable artifact identity and workflow-state handoff.",
26
+ "description": "Formal requirement lifecycle entry: natural language → spec.md and plan.md with mandatory Main-Agent planning review, optional capability-gated independent correctness review, stable artifact identity, and workflow-state handoff.",
27
27
  "tier": "1",
28
28
  "category": "prizmkit-skill",
29
29
  "hasAssets": true,
@@ -37,7 +37,7 @@
37
37
  "hasScripts": false
38
38
  },
39
39
  "prizmkit-code-review": {
40
- "description": "Bounded Main-Agent code review with evidence-based finding adjudication, direct repairs, verification, and append-only progress reporting.",
40
+ "description": "Mandatory bounded Main-Agent code review plus optional capability-gated independent correctness review, with evidence-based adjudication, direct repairs, verification, and append-only progress reporting.",
41
41
  "tier": "1",
42
42
  "category": "prizmkit-skill",
43
43
  "hasAssets": false,
@@ -157,12 +157,12 @@ Trusted headless execution:
157
157
  ```text
158
158
  a trusted host explicitly authorizes the current local task commit
159
159
  → host injects mode=<host-defined-headless-mode>, owner=<trusted-host-identifier>,
160
- local_commit_authorized=true, push_authorized=false
160
+ local_commit_authorized=true
161
161
  → committer verifies gates and commits automatically
162
- → no question, wait, or push is permitted
162
+ → no question or wait is permitted
163
163
  ```
164
164
 
165
- A self-declared or otherwise untrusted headless context does not authorize a commit. Push is never implied by either mode.
165
+ A self-declared or otherwise untrusted headless context does not authorize a commit. Remote publication remains a separate host-runtime decision.
166
166
 
167
167
  ## Recovery
168
168
 
@@ -1,24 +1,26 @@
1
1
  ---
2
2
  name: "prizmkit-code-review"
3
- description: "Review the complete current change for a formal PrizmKit requirement in a bounded Main-Agent loop. Directly repair accepted findings, verify repairs, converge to PASS or stop with NEEDS_FIXES, and hand off to prizmkit-test. (project)"
3
+ description: "Review the complete current change for a formal PrizmKit requirement with a mandatory bounded Main-Agent loop and optional capability-gated independent correctness review. Directly repair accepted corrections, verify repairs, converge to PASS or stop with NEEDS_FIXES, and hand off to prizmkit-test. (project)"
4
4
  ---
5
5
 
6
6
  # PrizmKit Code Review
7
7
 
8
- `/prizmkit-code-review` is the mandatory review stage after implementation and before the full test stage. The current Main Agent is the only Code Review executor. It owns the complete review loop: it discovers findings, adjudicates them, directly repairs accepted findings, verifies repairs, and continues until the review converges or stops safely.
8
+ `/prizmkit-code-review` is the mandatory review stage after implementation and before the full test stage. The current Main Agent owns the complete baseline review loop: it discovers findings, adjudicates them, directly repairs accepted findings, verifies repairs, and continues until the review converges or stops safely. After convergence, one strictly capability-gated independent Reviewer may objectively check the complete current implementation without taking mutation or final-decision authority.
9
9
 
10
10
  ## Execution Boundary
11
11
 
12
- - Do not delegate any part of Code Review directly or indirectly.
12
+ - Main-Agent review remains mandatory and must not be delegated directly or indirectly.
13
+ - After Main-Agent convergence only, this skill may create the single independent Reviewer defined by `${SKILL_DIR}/references/independent-code-review.md` when every structural capability in that reference is proven.
13
14
  - 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
+ - Do not launch any additional review work through a general-purpose execution unit or relabel it as a finder, verifier, audit, compatibility review, verification, or gap sweep.
16
+ - The independent Reviewer cannot mutate, execute arbitrary commands, or create downstream execution units; prompt instructions never substitute for these structural guarantees.
15
17
  - The Main Agent may directly read, search, edit, and run targeted verification in the active workspace.
16
18
  - Review repairs occur before the full `/prizmkit-test` stage so final test evidence represents the final reviewed workspace.
17
19
  - `{artifact_dir}/review-report.md` is the only persisted review artifact for this execution.
18
20
 
19
21
  ## Atomic Stage Boundary
20
22
 
21
- `prizmkit-code-review` owns only the complete Main-Agent review, accepted-finding repairs, and review verification. It writes its truthful terminal result and `next_stage`, then returns control. It must not invoke `prizmkit-test` or `prizmkit-implement` itself; the active orchestrator owns outer repair routing and the next-stage invocation.
23
+ `prizmkit-code-review` owns the complete mandatory Main-Agent review, the optional independent correctness review, accepted-correction repairs, and review verification. It writes its truthful terminal result and `next_stage`, then returns control. It must not invoke `prizmkit-test` or `prizmkit-implement` itself; the active orchestrator owns outer repair routing and the next-stage invocation.
22
24
 
23
25
  ## When to Use
24
26
 
@@ -111,7 +113,21 @@ Do not run the full auditable testing protocol as a substitute for this review s
111
113
 
112
114
  If a repair is unsafe, incomplete, or unverifiable, record an unresolved finding and finish with `NEEDS_FIXES`.
113
115
 
114
- ## Phase 3: Final Result
116
+ ## Phase 3: Independent Code Review
117
+
118
+ Run only after the Main-Agent review and repair loop converges with no unresolved finding. Main-Agent review remains mandatory on every host; this optional check never replaces or weakens it.
119
+
120
+ 1. Read `${SKILL_DIR}/references/independent-code-review.md` and follow its complete contract.
121
+ 2. Apply its all-or-nothing semantic Host Capability Gate. If any required structural capability is unavailable or unproven, create no Reviewer, append `independent-review-downgrade`, and preserve the valid completed Main-Agent review.
122
+ 3. When the gate passes, capture bounded immutable input for the complete current change and create exactly one Code Reviewer with the reference's Initial Reviewer Prompt.
123
+ 4. Use maximum five Reviewer responses. Append `independent-review-round` and `independent-adjudication` events. The Main Agent adjudicates every correction as `accepted`, `rejected`, or `unresolved` and retains all mutation authority.
124
+ 5. For accepted corrections, repair directly in the active checkout, run targeted verification, and inspect the complete resulting change.
125
+ 6. When responses remain, capture the complete fresh state and natively resume the exact same Reviewer. Never create a replacement Reviewer or simulate continuation with a fresh Reviewer plus summary.
126
+ 7. If native resume fails after repair, append downgrade and rerun the Main-Agent review over that repair within the existing ten-round safety fuse.
127
+ 8. If the fifth response causes a repair, run targeted verification, inspect the complete final change, record `Final State Independently Rechecked: no`, and do not send a sixth response.
128
+ 9. `NO_CORRECTION_NEEDED` or all corrections rejected with evidence converges independent review. Any unresolved correction produces `NEEDS_FIXES`.
129
+
130
+ ## Phase 4: Final Result
115
131
 
116
132
  Before completing:
117
133
 
@@ -0,0 +1,243 @@
1
+ # Independent Code Review
2
+
3
+ ## Purpose
4
+
5
+ Run one optional independent correctness review after the mandatory Main-Agent review and repair loop has converged. The Reviewer determines whether the complete current implementation correctly satisfies the requirement and plan. It is not required to disagree and must return `NO_CORRECTION_NEEDED` when no correction is justified.
6
+
7
+ This reference is complete within `prizmkit-code-review`. Do not depend on another skill's prompt or a platform-generated Reviewer role.
8
+
9
+ ## Required Ordering and Budget
10
+
11
+ ```text
12
+ Implementation complete
13
+ → mandatory Main-Agent review and repair loop: maximum ten rounds
14
+ → optional independent Code Reviewer: maximum five responses
15
+ → PASS or NEEDS_FIXES
16
+ ```
17
+
18
+ The independent budget does not replace, reduce, or extend the Main-Agent loop. Create at most one Reviewer for this Code Review stage. Never reuse it in another stage.
19
+
20
+ ## Host Capability Gate
21
+
22
+ The gate is all-or-nothing. Before creating a Reviewer, the host must prove this semantic execution contract:
23
+
24
+ ```yaml
25
+ execution_unit:
26
+ count: 1
27
+ access: read-only
28
+ mutation: unavailable
29
+ arbitrary_command_execution: unavailable
30
+ downstream_execution: structurally-unavailable
31
+ context_continuation: same-unit-native-resume
32
+ workspace_observation: bounded-active-checkout-input
33
+ model_configuration: inherit-current-session
34
+ ```
35
+
36
+ Rules:
37
+
38
+ - Prompt instructions cannot satisfy a missing structural capability.
39
+ - The decision must not branch on platform identity, tool name, execution-unit type name, adapter output, or a platform allowlist.
40
+ - If any capability is missing or cannot be proven, do not create a Reviewer. Use Strict Downgrade.
41
+ - A general execution unit with a prompt saying "do not mutate or delegate" is not eligible when those capabilities remain available.
42
+ - The Reviewer inherits the current session's model configuration. Do not add a separate model-selection contract.
43
+
44
+ ## Review Input
45
+
46
+ Before each response, the Main Agent captures one bounded review input that is immutable for one response:
47
+
48
+ ```text
49
+ review-input
50
+ ├── manifest: input identity, response number, exact changed paths, states, and consistency markers
51
+ ├── context: requirement, plan decisions, applicable rules, and prior adjudication on resume
52
+ └── payload: complete captured current change plus targeted supporting material
53
+ ```
54
+
55
+ The Code payload contains a logical representation of:
56
+
57
+ - staged tracked changes;
58
+ - unstaged tracked changes;
59
+ - untracked files;
60
+ - deleted and renamed files;
61
+ - the exact changed-file manifest;
62
+ - requirement goals and acceptance criteria;
63
+ - relevant plan decisions;
64
+ - applicable project rules and Prizm traps;
65
+ - targeted unchanged callers, dependents, contracts, schemas, or tests implicated by changed interfaces.
66
+
67
+ The Main Agent captures authoritative workspace state. The Reviewer does not run Git commands. Do not provide broad repository access as a substitute for complete current-change capture. The representation may use host-native immutable content or a read-only temporary payload outside the project change set; the protocol does not require a particular temporary path or command.
68
+
69
+ Before ordinary review, the Reviewer verifies that manifest, context, and payload agree. Missing paths, unexplained changed files, stale content, or mixed-round input produces `REVIEW_BLOCKED`, never partial success.
70
+
71
+ ## Initial Reviewer Prompt
72
+
73
+ Instantiate the bracketed fields and retain every boundary below.
74
+
75
+ ```text
76
+ You are the sole independent Code Reviewer for this PrizmKit Code Review stage.
77
+
78
+ Purpose:
79
+ Objectively determine whether the Main Agent's complete current implementation correctly satisfies the confirmed requirement and plan. You are not an adversary and are not required to disagree. Return NO_CORRECTION_NEEDED when the current implementation is correct.
80
+
81
+ Response:
82
+ This is response [RESPONSE_NUMBER] of a maximum five responses.
83
+ Review-input identity: [INPUT_ID]
84
+ Manifest: [MANIFEST]
85
+ Context: [CONTEXT]
86
+ Payload: [PAYLOAD]
87
+ Permitted targeted paths, if represented separately: [TARGETED_PATHS_OR_NONE]
88
+
89
+ Execution boundaries:
90
+ - Complete this review personally.
91
+ - Do not create, schedule, resume, continue, request, or coordinate another execution unit.
92
+ - Do not ask the Main Agent to create a helper.
93
+ - Do not re-enter orchestration, delegation, another review workflow, or an equivalent process.
94
+ - Do not modify, create, delete, rename, stage, commit, or otherwise mutate files.
95
+ - Do not execute commands, tests, builds, network calls, or any operation that can change state.
96
+ - Read only the bounded review input and explicitly permitted targeted paths.
97
+ - Do not perform broad repository discovery or a full repository scan.
98
+ - Report only corrections supported by a concrete target and evidence.
99
+ - Do not invent an issue merely to return feedback.
100
+ - Return REVIEW_BLOCKED rather than delegate or provide an incomplete success result.
101
+ - Do not expose private reasoning traces. Return only the required output.
102
+
103
+ First validate input consistency. Then review requirement and acceptance-criteria alignment, implementation completeness, concrete failure scenarios, error handling, security, authorization, data integrity, transaction/concurrency/state-transition behavior, public and internal contracts, compatibility and regression risk, test-boundary or evidence defects that can conceal incorrect behavior, and applicable project-rule compliance.
104
+
105
+ Do not rewrite the plan, modify code, execute tests, or perform broad exploratory repository discovery.
106
+
107
+ Return exactly one result using the Reviewer Output Protocol.
108
+ ```
109
+
110
+ ## Resume Prompt
111
+
112
+ Resume the exact same Reviewer; do not create a new Reviewer with this text. Instantiate the bracketed fields.
113
+
114
+ ```text
115
+ Continue as the same independent Code Reviewer.
116
+
117
+ Response:
118
+ This is response [RESPONSE_NUMBER] of a maximum five responses.
119
+ New review-input identity: [INPUT_ID]
120
+ New manifest: [MANIFEST]
121
+ Current context: [CONTEXT]
122
+ Current payload: [PAYLOAD]
123
+ Previously accepted corrections: [ACCEPTED_CORRECTIONS_OR_NONE]
124
+ Repairs actually made: [REPAIRS_OR_NONE]
125
+ Main-Agent targeted verification: [VERIFICATION]
126
+ Previously rejected corrections and rejection evidence: [REJECTIONS_OR_NONE]
127
+ Unresolved items: [UNRESOLVED_OR_NONE]
128
+
129
+ All initial execution boundaries and the Reviewer Output Protocol remain mandatory. Review the complete current state, not only the repair and not the superseded payload. Do not repeat a rejected correction unless the new state invalidates the recorded rejection evidence. Validate the new input before ordinary review and return exactly one result.
130
+ ```
131
+
132
+ ## Reviewer Output Protocol
133
+
134
+ Return exactly one of these forms. Do not add severity, confidence, dimension, workflow impact, or acceptance fields.
135
+
136
+ ### No Correction Needed
137
+
138
+ ```markdown
139
+ ### Result: NO_CORRECTION_NEEDED
140
+
141
+ ### Corrections
142
+ None.
143
+
144
+ ### Summary
145
+ <one or two sentences confirming what was reviewed>
146
+ ```
147
+
148
+ ### Correction Needed
149
+
150
+ ```markdown
151
+ ### Result: CORRECTION_NEEDED
152
+
153
+ ### Corrections
154
+
155
+ #### Correction 1
156
+ - Target: <file and location, contract, or behavior>
157
+ - Problem: <what is currently incorrect>
158
+ - Evidence: <concrete basis or reproducible scenario>
159
+ - Correction: <recommended correction>
160
+
161
+ ### Summary
162
+ <one or two sentences describing the current state>
163
+ ```
164
+
165
+ Every correction contains only `Target`, `Problem`, `Evidence`, and `Correction`.
166
+
167
+ ### Review Blocked
168
+
169
+ ```markdown
170
+ ### Result: REVIEW_BLOCKED
171
+
172
+ ### Blocker
173
+ - Target: <missing or inconsistent review input>
174
+ - Problem: <why a complete review cannot be performed>
175
+ - Evidence: <concrete mismatch or capability failure>
176
+ - Correction: <what input or host condition would unblock review>
177
+
178
+ ### Summary
179
+ No review verdict was produced.
180
+ ```
181
+
182
+ `REVIEW_BLOCKED` is an internal independent-review result, not a lifecycle verdict.
183
+
184
+ ## Main-Agent Adjudication
185
+
186
+ The Main Agent verifies each proposed correction and records exactly one decision:
187
+
188
+ | Decision | Meaning | Action |
189
+ |---|---|---|
190
+ | `accepted` | Evidence proves an in-scope implementation correction is needed. | Main Agent repairs the current implementation and performs targeted verification. |
191
+ | `rejected` | Current code, contracts, tests, artifacts, or rules disprove the proposed problem. | Record concrete rejection evidence and make no change for it. |
192
+ | `unresolved` | Correctness or a safe repair cannot be established. | Record the item and return `NEEDS_FIXES`. |
193
+
194
+ The Reviewer never modifies files and cannot overrule adjudication.
195
+
196
+ Independent review converges normally when:
197
+
198
+ 1. the Reviewer returns `NO_CORRECTION_NEEDED`; or
199
+ 2. every correction in the current response is rejected with concrete evidence and no unresolved item remains.
200
+
201
+ ## Response Algorithm
202
+
203
+ 1. Run only after the Main-Agent review and repair loop converges with no unresolved finding.
204
+ 2. Apply the Host Capability Gate.
205
+ 3. If eligible, capture response 1 input and create exactly one Reviewer with the Initial Reviewer Prompt.
206
+ 4. Validate the result against the Reviewer Output Protocol and append an independent-review round event.
207
+ 5. Adjudicate every correction and append independent-adjudication events. Any unresolved item returns `NEEDS_FIXES`.
208
+ 6. For accepted corrections, the Main Agent repairs the active checkout, runs targeted verification, and inspects the complete resulting change.
209
+ 7. If one or more responses remain, capture the complete fresh current change and resume the exact same Reviewer with the Resume Prompt. Do not restart the complete ten-round Main-Agent loop after every ordinary independent correction.
210
+ 8. If the fifth response causes a repair, no sixth response is allowed. Run targeted verification, inspect the complete final change, record final-budget handling and `Final State Independently Rechecked: no`, and do not exceed the response budget.
211
+ 9. End the Reviewer when review converges, reaches the response limit, fails irrecoverably, or the stage becomes blocked. Explicitly terminate it when the host safely supports that operation; otherwise stop sending messages.
212
+ 10. Complete the existing final verification and append exactly one `## Final Result` with `PASS` or `NEEDS_FIXES`.
213
+
214
+ ## Strict Downgrade
215
+
216
+ Use strict downgrade in any of these cases:
217
+
218
+ - a required capability is unavailable or unproven before creation;
219
+ - Reviewer creation fails;
220
+ - the exact same Reviewer cannot be resumed or resume fails;
221
+ - execution-unit integrity becomes uncertain.
222
+
223
+ Behavior:
224
+
225
+ 1. Never create a weaker or replacement Reviewer.
226
+ 2. Never create a fresh Reviewer with a summary of the prior conversation; a summary is context, not native continuation.
227
+ 3. When no Reviewer is created, record the downgrade and continue from the completed Main-Agent review if it remains valid.
228
+ 4. When creation fails before any response, record the failure and preserve the completed Main-Agent review.
229
+ 5. When resume fails after an accepted repair, Never create a replacement Reviewer; rerun the Main-Agent review over the repair, within the existing ten-round safety fuse, record the downgrade and fallback, and return `NEEDS_FIXES` if review cannot establish convergence.
230
+ 6. Reviewer input problems may be corrected and sent to the same Reviewer only while response budget and native continuation remain available. Otherwise downgrade.
231
+ 7. Report temporary input-cleanup failures honestly; cleanup failure does not change an otherwise verified review result.
232
+
233
+ Strict downgrade is visible reduced assurance, not a new lifecycle verdict and not permission to weaken the gate.
234
+
235
+ ## Report Recording
236
+
237
+ Use the existing append-only `review-report.md` lifecycle and renderer events:
238
+
239
+ - `independent-review-round`: response number `1..5`, result, correction count, adjudication counts, and next action;
240
+ - `independent-adjudication`: correction summary, `accepted | rejected | unresolved`, evidence, and actual modification;
241
+ - `independent-review-downgrade`: reason, Main-Agent fallback, and whether the final state was independently rechecked.
242
+
243
+ The report remains the only persisted Code Review artifact. It ends with exactly one `## Final Result`; valid final verdicts remain `PASS | NEEDS_FIXES`.