prizmkit 1.1.119 → 1.1.121
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/bin/create-prizmkit.js +1 -5
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/README.md +41 -38
- package/bundled/dev-pipeline/assets/skill-subagent-integration.md +76 -0
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +2 -8
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/platform_detection.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +23 -25
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +8 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +10 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +88 -32
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +28 -6
- package/bundled/dev-pipeline/scripts/continuation.py +51 -6
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +60 -102
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/{init-dev-team.py → init-change-artifact.py} +6 -16
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +364 -76
- package/bundled/dev-pipeline/scripts/update-bug-status.py +57 -14
- package/bundled/dev-pipeline/scripts/update-feature-status.py +54 -5
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +57 -14
- package/bundled/dev-pipeline/scripts/utils.py +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +9 -11
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +2 -1
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -2
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +3 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +5 -3
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +20 -0
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
- package/bundled/dev-pipeline/tests/test_auto_skip.py +5 -5
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +214 -144
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +25 -12
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +11 -14
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +235 -32
- package/bundled/dev-pipeline/tests/test_unified_cli.py +219 -16
- package/bundled/skills/_metadata.json +4 -4
- package/bundled/skills/app-planner/SKILL.md +2 -2
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -3
- package/bundled/skills/prizmkit-code-review/SKILL.md +50 -47
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +13 -8
- package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +47 -33
- package/bundled/skills/prizmkit-code-review/references/reviewer-workspace-protocol.md +90 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +21 -1
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +67 -0
- package/bundled/skills/prizmkit-test/SKILL.md +159 -155
- package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +420 -0
- package/bundled/skills/prizmkit-test/assets/behavior-risk-matrix.schema.json +116 -0
- package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +112 -0
- package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +97 -0
- package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +76 -192
- package/bundled/skills/prizmkit-test/references/contract-mock-protocol.md +65 -0
- package/bundled/skills/prizmkit-test/references/evidence-protocol.md +194 -0
- package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +78 -0
- package/bundled/skills/prizmkit-test/references/examples.md +65 -108
- package/bundled/skills/prizmkit-test/references/service-boundary-test-catalog.md +10 -7
- package/bundled/skills/prizmkit-test/references/test-generation-steps.md +90 -82
- package/bundled/skills/prizmkit-test/references/test-report-template.md +77 -98
- package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +97 -0
- package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +723 -0
- package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +1426 -0
- package/package.json +1 -1
- package/src/clean.js +12 -8
- package/src/config.js +24 -42
- package/src/index.js +1 -10
- package/src/manifest.js +3 -9
- package/src/metadata.js +0 -26
- package/src/prompts.js +0 -13
- package/src/scaffold.js +76 -201
- package/src/upgrade.js +16 -33
- package/bundled/adapters/claude/agent-adapter.js +0 -96
- package/bundled/adapters/claude/team-adapter.js +0 -183
- package/bundled/adapters/codebuddy/agent-adapter.js +0 -42
- package/bundled/adapters/codebuddy/team-adapter.js +0 -46
- package/bundled/adapters/codex/agent-adapter.js +0 -38
- package/bundled/adapters/codex/team-adapter.js +0 -37
- package/bundled/agents/prizm-dev-team-dev.md +0 -123
- package/bundled/agents/prizm-dev-team-reviewer.md +0 -113
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +0 -65
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +0 -436
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +0 -510
- package/bundled/skills/prizmkit-test/scripts/validate_boundary_report.py +0 -347
- package/bundled/team/prizm-dev-team.json +0 -27
|
@@ -41,6 +41,17 @@ def run_cli(*args):
|
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def _load_progress_parser_module():
|
|
45
|
+
import importlib.util
|
|
46
|
+
|
|
47
|
+
parser_path = PIPELINE_ROOT / "scripts" / "parse-stream-progress.py"
|
|
48
|
+
spec = importlib.util.spec_from_file_location("parse_stream_progress", parser_path)
|
|
49
|
+
module = importlib.util.module_from_spec(spec)
|
|
50
|
+
assert spec.loader is not None
|
|
51
|
+
spec.loader.exec_module(module)
|
|
52
|
+
return module
|
|
53
|
+
|
|
54
|
+
|
|
44
55
|
def test_cli_help_exposes_python_runtime_command_groups():
|
|
45
56
|
result = run_cli("--help")
|
|
46
57
|
|
|
@@ -791,24 +802,28 @@ def test_session_preamble_writes_redacted_start_command_for_all_launch_profiles(
|
|
|
791
802
|
assert str(prompt) not in "\n".join(lines[:6])
|
|
792
803
|
|
|
793
804
|
|
|
794
|
-
def
|
|
805
|
+
def test_headless_review_guidance_uses_workspace_equivalence_protocol():
|
|
795
806
|
guidance_files = [
|
|
796
|
-
REPO_ROOT / "dev-pipeline" / "templates" / "
|
|
807
|
+
REPO_ROOT / "dev-pipeline" / "templates" / "sections" / "phase-review-full.md",
|
|
797
808
|
REPO_ROOT / "dev-pipeline" / "templates" / "bootstrap-tier3.md",
|
|
798
809
|
REPO_ROOT / "core" / "skills" / "prizmkit-skill" / "prizmkit-code-review" / "SKILL.md",
|
|
799
810
|
]
|
|
800
811
|
|
|
801
812
|
for path in guidance_files:
|
|
802
813
|
text = path.read_text(encoding="utf-8")
|
|
803
|
-
assert
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
assert "
|
|
809
|
-
assert "
|
|
810
|
-
assert "
|
|
811
|
-
|
|
814
|
+
assert "platform-supported" in text, path
|
|
815
|
+
assert "snapshot" in text and "equivalent" in text, path
|
|
816
|
+
assert "Main-Agent self-review" in text, path
|
|
817
|
+
assert "current-workspace / active-checkout / no-worktree" not in text, path
|
|
818
|
+
assert ".claude/worktrees/..." not in text, path
|
|
819
|
+
assert ".prizmkit/state/worktrees/..." not in text, path
|
|
820
|
+
assert "USE_WORKTREE" not in text, path
|
|
821
|
+
assert "isolation:" not in text, path
|
|
822
|
+
|
|
823
|
+
skill_text = guidance_files[-1].read_text(encoding="utf-8")
|
|
824
|
+
assert "reviewer-workspace-protocol.md" in skill_text
|
|
825
|
+
assert "staged, unstaged, untracked, deleted, and renamed" in skill_text
|
|
826
|
+
assert "WORKSPACE_MISMATCH" in skill_text
|
|
812
827
|
|
|
813
828
|
for path in guidance_files[:-1]:
|
|
814
829
|
text = path.read_text(encoding="utf-8")
|
|
@@ -840,6 +855,145 @@ def test_progress_parser_adds_required_metadata(tmp_path):
|
|
|
840
855
|
assert data["permission_denial_count"] == 1
|
|
841
856
|
|
|
842
857
|
|
|
858
|
+
|
|
859
|
+
def test_progress_parser_normalizes_claude_subagents_without_double_counting(tmp_path):
|
|
860
|
+
module = _load_progress_parser_module()
|
|
861
|
+
tracker = module.ProgressTracker()
|
|
862
|
+
|
|
863
|
+
tracker.process_event({"type": "system", "subtype": "init", "session_id": "claude-session", "cwd": str(tmp_path)})
|
|
864
|
+
tracker.process_event({
|
|
865
|
+
"type": "assistant",
|
|
866
|
+
"message": {"content": [{
|
|
867
|
+
"type": "tool_use",
|
|
868
|
+
"id": "tool-1",
|
|
869
|
+
"name": "Agent",
|
|
870
|
+
"input": {"description": "review code", "prompt": "check", "subagent_type": "reviewer"},
|
|
871
|
+
}]},
|
|
872
|
+
})
|
|
873
|
+
tracker.process_event({
|
|
874
|
+
"type": "system",
|
|
875
|
+
"subtype": "task_started",
|
|
876
|
+
"task_id": "task-1",
|
|
877
|
+
"tool_use_id": "tool-1",
|
|
878
|
+
"task_type": "in_process_teammate",
|
|
879
|
+
"subagent_type": "reviewer",
|
|
880
|
+
"description": "review code",
|
|
881
|
+
})
|
|
882
|
+
tracker.process_event({"type": "assistant", "parent_tool_use_id": "tool-1", "message": {"content": [{"type": "text", "text": "child activity"}]}})
|
|
883
|
+
tracker.process_event({"type": "system", "subtype": "task_started", "task_id": "bash-1", "task_type": "local_bash", "description": "ls"})
|
|
884
|
+
tracker.process_event({"type": "system", "subtype": "task_notification", "task_id": "task-1", "tool_use_id": "tool-1", "status": "completed", "summary": "done"})
|
|
885
|
+
|
|
886
|
+
data = tracker.to_dict()
|
|
887
|
+
|
|
888
|
+
assert data["subagent_stats_source"] == "session_log"
|
|
889
|
+
assert data["subagent_spawn_count"] == 1
|
|
890
|
+
assert data["active_subagent_count"] == 0
|
|
891
|
+
assert data["subagent_states"] == [{"status": "completed", "count": 1}]
|
|
892
|
+
assert "task-1" in data["subagent_observed_ids"]
|
|
893
|
+
assert "tool-1" in data["subagent_statistics"]["parent_activity_ids"]
|
|
894
|
+
assert all("bash" not in record["id"] for record in data["subagent_statistics"]["records"])
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
def test_progress_parser_normalizes_codebuddy_agent_tools_with_deduplication():
|
|
898
|
+
module = _load_progress_parser_module()
|
|
899
|
+
tracker = module.ProgressTracker()
|
|
900
|
+
args = {"prompt": "inspect", "description": "inspect", "subagent_type": "Explore"}
|
|
901
|
+
|
|
902
|
+
tracker.process_event({
|
|
903
|
+
"type": "message",
|
|
904
|
+
"sessionId": "cb-session",
|
|
905
|
+
"cwd": "/tmp/project",
|
|
906
|
+
"role": "assistant",
|
|
907
|
+
"content": [{"type": "tool_use", "id": "call-1", "name": "Agent", "input": args}],
|
|
908
|
+
})
|
|
909
|
+
tracker.process_event({
|
|
910
|
+
"type": "function_call",
|
|
911
|
+
"sessionId": "cb-session",
|
|
912
|
+
"cwd": "/tmp/project",
|
|
913
|
+
"id": "call-1",
|
|
914
|
+
"name": "Agent",
|
|
915
|
+
"arguments": json.dumps(args),
|
|
916
|
+
})
|
|
917
|
+
tracker.process_event({
|
|
918
|
+
"type": "function_call",
|
|
919
|
+
"sessionId": "cb-session",
|
|
920
|
+
"cwd": "/tmp/project",
|
|
921
|
+
"id": "task-call",
|
|
922
|
+
"name": "TaskCreate",
|
|
923
|
+
"arguments": json.dumps({"description": "background", "subject": "status"}),
|
|
924
|
+
})
|
|
925
|
+
|
|
926
|
+
data = tracker.to_dict()
|
|
927
|
+
|
|
928
|
+
assert data["cb_session_id"] == "cb-session"
|
|
929
|
+
assert data["subagent_provider"] == "codebuddy"
|
|
930
|
+
assert data["subagent_spawn_count"] == 2
|
|
931
|
+
assert data["active_subagent_count"] == 2
|
|
932
|
+
assert {item["status"] for item in data["subagent_states"]} == {"running"}
|
|
933
|
+
assert len(data["subagent_statistics"]["records"]) == 2
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
def test_progress_parser_normalizes_codex_collab_metadata_with_missing_fields():
|
|
937
|
+
module = _load_progress_parser_module()
|
|
938
|
+
tracker = module.ProgressTracker()
|
|
939
|
+
|
|
940
|
+
tracker.process_event({"type": "thread.started", "thread_id": "parent"})
|
|
941
|
+
tracker.process_event({
|
|
942
|
+
"type": "item.started",
|
|
943
|
+
"item": {
|
|
944
|
+
"type": "collab_tool_call",
|
|
945
|
+
"tool": "delegate",
|
|
946
|
+
"receiver_thread_ids": ["thread-a", "thread-b"],
|
|
947
|
+
"agents_states": {
|
|
948
|
+
"thread-a": {"status": "running", "message": "working"},
|
|
949
|
+
"thread-b": {"status": "completed", "message": "done"},
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
})
|
|
953
|
+
tracker.process_event({"type": "item.completed", "item": {"type": "collab_tool_call", "tool": "delegate"}})
|
|
954
|
+
|
|
955
|
+
data = tracker.to_dict()
|
|
956
|
+
|
|
957
|
+
assert data["event_format"] == "codex-json"
|
|
958
|
+
assert data["child_thread_ids"] == ["thread-a", "thread-b"]
|
|
959
|
+
assert data["subagent_spawn_count"] == 2
|
|
960
|
+
assert data["active_subagent_count"] == 1
|
|
961
|
+
assert {state["status"]: state["count"] for state in data["subagent_states"]} == {"running": 1, "completed": 1}
|
|
962
|
+
assert data["subagent_source_metadata"]["child_activity_source"] == "filesystem_liveness_only"
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
def test_progress_parser_keeps_child_files_liveness_only(tmp_path, monkeypatch):
|
|
966
|
+
module = _load_progress_parser_module()
|
|
967
|
+
claude_home = tmp_path / "claude"
|
|
968
|
+
project_key = str(tmp_path).replace("\\", "-").replace("/", "-").replace(":", "")
|
|
969
|
+
subagents_dir = claude_home / "projects" / project_key / "parent-session" / "subagents"
|
|
970
|
+
subagents_dir.mkdir(parents=True)
|
|
971
|
+
child_log = subagents_dir / "agent-child.jsonl"
|
|
972
|
+
child_log.write_text("child activity", encoding="utf-8")
|
|
973
|
+
monkeypatch.setenv("CLAUDE_HOME", str(claude_home))
|
|
974
|
+
|
|
975
|
+
tracker = module.ProgressTracker()
|
|
976
|
+
tracker.process_event({"type": "system", "subtype": "init", "session_id": "parent-session", "cwd": str(tmp_path)})
|
|
977
|
+
tracker.process_event({
|
|
978
|
+
"type": "system",
|
|
979
|
+
"subtype": "task_started",
|
|
980
|
+
"task_id": "task-1",
|
|
981
|
+
"tool_use_id": "tool-1",
|
|
982
|
+
"task_type": "in_process_teammate",
|
|
983
|
+
"description": "agent",
|
|
984
|
+
})
|
|
985
|
+
first = tracker.to_dict()
|
|
986
|
+
child_log.write_text("child activity grew", encoding="utf-8")
|
|
987
|
+
tracker.refresh_child_session_activity(force=True)
|
|
988
|
+
second = tracker.to_dict()
|
|
989
|
+
|
|
990
|
+
assert first["subagent_spawn_count"] == 1
|
|
991
|
+
assert second["subagent_spawn_count"] == 1
|
|
992
|
+
assert second["child_total_bytes"] > first["child_total_bytes"]
|
|
993
|
+
assert second["child_session_files"]
|
|
994
|
+
assert second["child_activity_source"] == "filesystem_liveness_only"
|
|
995
|
+
assert second["subagent_statistics"]["source"] == "session_log"
|
|
996
|
+
|
|
843
997
|
def test_session_dual_writes_progress_and_recovers_backup(tmp_path):
|
|
844
998
|
from prizmkit_runtime.sessions import AISessionConfig, AISessionLauncher, recover_session_log
|
|
845
999
|
|
|
@@ -935,6 +1089,10 @@ def test_custom_session_launch_writes_existing_logs_and_progress(tmp_path):
|
|
|
935
1089
|
progress_data = json.loads(progress.read_text(encoding="utf-8"))
|
|
936
1090
|
assert progress_data["event_type_counts"]["result"] == 1
|
|
937
1091
|
assert progress_data["has_usage"] is True
|
|
1092
|
+
assert progress_data["subagent_stats_source"] == "session_log"
|
|
1093
|
+
assert progress_data["subagent_spawn_count"] == 0
|
|
1094
|
+
assert progress_data["subagent_statistics"]["providers"] == []
|
|
1095
|
+
assert progress_data["child_activity_source"] == "filesystem_liveness_only"
|
|
938
1096
|
|
|
939
1097
|
|
|
940
1098
|
@pytest.mark.parametrize("platform", ["claude", "codex", "codebuddy"])
|
|
@@ -1031,7 +1189,10 @@ def test_compact_progress_line_hides_stale_until_no_progress(tmp_path):
|
|
|
1031
1189
|
json.dumps(
|
|
1032
1190
|
{
|
|
1033
1191
|
"child_total_bytes": 2 * 1024 * 1024,
|
|
1192
|
+
"child_session_files": [{"path": "a"}, {"path": "b"}],
|
|
1034
1193
|
"subagent_spawn_count": 5,
|
|
1194
|
+
"active_subagent_count": 2,
|
|
1195
|
+
"subagent_states": [{"status": "running", "count": 2}, {"status": "completed", "count": 3}],
|
|
1035
1196
|
"current_phase": "stream-derived-phase",
|
|
1036
1197
|
"current_tool": "Read",
|
|
1037
1198
|
"message_count": 465,
|
|
@@ -1059,7 +1220,9 @@ def test_compact_progress_line_hides_stale_until_no_progress(tmp_path):
|
|
|
1059
1220
|
|
|
1060
1221
|
assert "▶ [HEARTBEAT]" in running_line
|
|
1061
1222
|
assert "log: 4MB" in running_line
|
|
1062
|
-
assert "
|
|
1223
|
+
assert "subagents: spawned=5 active=2 states:running=2,completed=3" in running_line
|
|
1224
|
+
assert "child logs: 2MB/2 files" in running_line
|
|
1225
|
+
assert "child: 2MB/5" not in running_line
|
|
1063
1226
|
assert "phase: Retrospective" in running_line
|
|
1064
1227
|
assert "stream-derived-phase" not in running_line
|
|
1065
1228
|
assert "tool: Read" in running_line
|
|
@@ -1417,6 +1580,46 @@ def test_recovery_sessions_receive_live_heartbeat_configuration(tmp_path, monkey
|
|
|
1417
1580
|
assert config.suppress_stream_output is True
|
|
1418
1581
|
|
|
1419
1582
|
|
|
1583
|
+
|
|
1584
|
+
def test_session_summary_reports_normalized_subagents_and_child_liveness(tmp_path, capsys):
|
|
1585
|
+
import prizmkit_runtime.runners as runners
|
|
1586
|
+
from prizmkit_runtime.runner_models import SessionPaths
|
|
1587
|
+
|
|
1588
|
+
logs = tmp_path / "sessions" / "s1" / "logs"
|
|
1589
|
+
logs.mkdir(parents=True)
|
|
1590
|
+
session_log = logs / "session.log"
|
|
1591
|
+
progress = logs / "progress.json"
|
|
1592
|
+
session_log.write_text("one\ntwo\n", encoding="utf-8")
|
|
1593
|
+
progress.write_text(
|
|
1594
|
+
json.dumps({
|
|
1595
|
+
"subagent_spawn_count": 2,
|
|
1596
|
+
"active_subagent_count": 1,
|
|
1597
|
+
"subagent_states": [{"status": "running", "count": 1}, {"status": "completed", "count": 1}],
|
|
1598
|
+
"subagent_statistics": {"spawned": 2, "active": 1, "providers": ["claude"], "source": "session_log"},
|
|
1599
|
+
"child_total_bytes": 2048,
|
|
1600
|
+
"child_session_files": [{"path": "child-a"}],
|
|
1601
|
+
}),
|
|
1602
|
+
encoding="utf-8",
|
|
1603
|
+
)
|
|
1604
|
+
paths = SessionPaths(
|
|
1605
|
+
session_dir=logs.parent,
|
|
1606
|
+
prompt_path=logs.parent / "bootstrap-prompt.md",
|
|
1607
|
+
logs_dir=logs,
|
|
1608
|
+
session_log=session_log,
|
|
1609
|
+
progress_json=progress,
|
|
1610
|
+
heartbeat_json=logs / "heartbeat.json",
|
|
1611
|
+
session_status_json=logs / "session-status.json",
|
|
1612
|
+
)
|
|
1613
|
+
result = type("Result", (), {"exit_code": 0})()
|
|
1614
|
+
classification = type("Classification", (), {"session_status": "success"})()
|
|
1615
|
+
|
|
1616
|
+
runners._emit_session_summary(result, paths, classification)
|
|
1617
|
+
|
|
1618
|
+
captured = capsys.readouterr()
|
|
1619
|
+
assert "Subagents: spawned=2, active=1, states: running=1, completed=1 (claude; source=session.log)" in captured.err
|
|
1620
|
+
assert "Child log activity: 2KB across 1 files (heartbeat liveness only)" in captured.err
|
|
1621
|
+
assert "Subagent calls detected" not in captured.err
|
|
1622
|
+
|
|
1420
1623
|
def test_session_live_output_does_not_forward_cli_output_without_verbose(tmp_path, capsys):
|
|
1421
1624
|
from prizmkit_runtime.sessions import AISessionConfig, AISessionLauncher
|
|
1422
1625
|
|
|
@@ -1995,8 +2198,8 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
|
|
|
1995
2198
|
subprocess.run(["git", "add", ".gitignore"], cwd=repo, check=True)
|
|
1996
2199
|
subprocess.run(["git", "commit", "-m", "ignore support"], cwd=repo, check=True, stdout=subprocess.DEVNULL)
|
|
1997
2200
|
|
|
1998
|
-
(repo / ".claude" / "
|
|
1999
|
-
(repo / ".claude" / "
|
|
2201
|
+
(repo / ".claude" / "commands").mkdir(parents=True)
|
|
2202
|
+
(repo / ".claude" / "commands" / "prizmkit.md").write_text("skill", encoding="utf-8")
|
|
2000
2203
|
(repo / ".prizmkit" / "prizm-docs").mkdir(parents=True)
|
|
2001
2204
|
(repo / ".prizmkit" / "prizm-docs" / "root.prizm").write_text("PRIZM_VERSION: 1\n", encoding="utf-8")
|
|
2002
2205
|
(repo / ".prizmkit" / "config.json").write_text("{}", encoding="utf-8")
|
|
@@ -2014,12 +2217,12 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
|
|
|
2014
2217
|
)
|
|
2015
2218
|
setup = ensure_linked_worktree(runtime)
|
|
2016
2219
|
assert setup.ok
|
|
2017
|
-
assert not (runtime.worktree_path / ".claude" / "
|
|
2220
|
+
assert not (runtime.worktree_path / ".claude" / "commands" / "prizmkit.md").exists()
|
|
2018
2221
|
|
|
2019
2222
|
result = materialize_worktree_support_assets(runtime)
|
|
2020
2223
|
|
|
2021
2224
|
assert result.ok
|
|
2022
|
-
assert (runtime.worktree_path / ".claude" / "
|
|
2225
|
+
assert (runtime.worktree_path / ".claude" / "commands" / "prizmkit.md").is_file()
|
|
2023
2226
|
assert (runtime.worktree_path / ".prizmkit" / "prizm-docs" / "root.prizm").is_file()
|
|
2024
2227
|
assert (runtime.worktree_path / ".prizmkit" / "config.json").is_file()
|
|
2025
2228
|
assert (runtime.worktree_path / ".prizmkit" / "manifest.json").is_file()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.
|
|
2
|
+
"version": "1.1.121",
|
|
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.",
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
"hasScripts": false
|
|
66
66
|
},
|
|
67
67
|
"prizmkit-test": {
|
|
68
|
-
"description": "
|
|
68
|
+
"description": "Auditable project-native test evidence with request-driven execution, runner-generated receipts, differential proof, replay, and deterministic validation.",
|
|
69
69
|
"tier": "1",
|
|
70
70
|
"category": "prizmkit-skill",
|
|
71
|
-
"hasAssets":
|
|
72
|
-
"hasScripts":
|
|
71
|
+
"hasAssets": true,
|
|
72
|
+
"hasScripts": true
|
|
73
73
|
},
|
|
74
74
|
"feature-workflow": {
|
|
75
75
|
"description": "One-stop entry point for feature development. Orchestrates feature-planner → feature-pipeline-launcher → background execution. Handles multi-feature batch development from a single request.",
|
|
@@ -47,7 +47,7 @@ If you believe the task is better suited for a different workflow, you MUST:
|
|
|
47
47
|
- Claude Code → `CLAUDE.md`
|
|
48
48
|
- CodeBuddy → `CODEBUDDY.md`
|
|
49
49
|
- `all` → all three files.
|
|
50
|
-
- Only when the manifest is missing, fall back to installed PrizmKit-owned platform files such as `.
|
|
50
|
+
- Only when the manifest is missing, fall back to installed PrizmKit-owned platform files such as `.claude/commands/prizmkit.md`, `.agents/skills/prizmkit/SKILL.md`, or `.codebuddy/skills/prizmkit/SKILL.md`. Do not treat a generic `.agents/` directory as Codex.
|
|
51
51
|
|
|
52
52
|
**After planning is complete**, you MUST:
|
|
53
53
|
1. Present the summary of captured project-level context (vision, conventions, architecture decisions, project brief)
|
|
@@ -126,7 +126,7 @@ Before questions, check optional context files (never block if absent):
|
|
|
126
126
|
Note:
|
|
127
127
|
- This skill **reads** `.prizmkit/config.json` if present.
|
|
128
128
|
- This skill does **not** create `.prizmkit/config.json` directly.
|
|
129
|
-
- Creation/update is handled by bootstrap/init flows (e.g., `prizmkit-init`, `.prizmkit/dev-pipeline/scripts/init-
|
|
129
|
+
- Creation/update is handled by bootstrap/init flows (e.g., `prizmkit-init`, `.prizmkit/dev-pipeline/scripts/init-change-artifact.py`).
|
|
130
130
|
|
|
131
131
|
## Interaction Style (Hard Rule)
|
|
132
132
|
|
|
@@ -29,9 +29,7 @@ After Phase 2 (Confirm constraints and tech assumptions), before Phase 3 (Captur
|
|
|
29
29
|
- `codex` → append to `AGENTS.md`
|
|
30
30
|
- `claude` → append to `CLAUDE.md`
|
|
31
31
|
- `codebuddy` → append to `CODEBUDDY.md`
|
|
32
|
-
- `all` → append to all three files.
|
|
33
|
-
- Only when the manifest is missing, fall back to PrizmKit-owned install artifacts: `.codex/agents/*.toml`, `.claude/commands/prizmkit.md`, `.codebuddy/skills/prizmkit/SKILL.md`.
|
|
34
|
-
- Do not treat a generic `.agents/` directory as Codex; it may contain unrelated third-party skills.
|
|
32
|
+
- `all` → append to all three files.
|
|
35
33
|
- If no platform can be determined, skip (no project instruction file).
|
|
36
34
|
|
|
37
35
|
2. **Check for existing section** — read the target file and look for `### Architecture Decisions` heading:
|
|
@@ -1,55 +1,53 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "prizmkit-code-review"
|
|
3
|
-
description: "Iterative review-fix loop against spec
|
|
3
|
+
description: "Iterative independent review-fix loop against spec, plan, workspace changes, and test evidence. Establishes a verified review snapshot using any platform-supported subagent strategy while keeping review judgment separate from Main-Agent filtering and fixes. Use after /prizmkit-implement as a Full path quality gate or when the user asks to review, check code, validate implementation, or decide whether changes are ready to commit. Loops until PASS or max 3 rounds. (project)"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PrizmKit Code Review
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Run an iterative review-fix loop against the current change. Keep review judgment independent from fix application: an independent read-only Reviewer evaluates a verified snapshot, then the Main Agent filters findings and applies accepted fixes.
|
|
9
9
|
|
|
10
10
|
Review modes:
|
|
11
|
-
- `reviewer-
|
|
11
|
+
- `independent-reviewer-verified-snapshot`: an independent Reviewer verified that its review snapshot is equivalent to the Main Agent's current change.
|
|
12
12
|
- `not-run-no-changes`: no workspace changes were detected.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
The skill defines review invariants rather than platform tool parameters. Choose any platform-supported subagent launch and snapshot transport strategy that satisfies `${SKILL_DIR}/references/reviewer-workspace-protocol.md`.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
Cannot run /prizmkit-code-review because this platform cannot start prizm-dev-team-reviewer in the active checkout without worktree isolation.
|
|
18
|
-
```
|
|
16
|
+
If no independent Reviewer can receive and verify an equivalent snapshot, stop normal review and report the workspace verification failure. Do not replace the independent review with Main-Agent self-review because that would remove the separation between judgment and implementation.
|
|
19
17
|
|
|
20
18
|
### When to Use
|
|
21
19
|
- After `/prizmkit-implement` as the Full path quality gate
|
|
22
|
-
- For Fast path
|
|
23
|
-
-
|
|
20
|
+
- For Fast path when risk, scope, or the user warrants review
|
|
21
|
+
- When the user says "review", "check code", "review my implementation", or "is it ready to commit"
|
|
24
22
|
- Before `/prizmkit-committer` when the chosen lifecycle path requires review
|
|
25
23
|
|
|
26
24
|
### When NOT to Use
|
|
27
25
|
- Direct edit or low-risk Fast path where review is not required
|
|
28
|
-
- No spec.md or plan.md exists and there is no clear task goal to review against
|
|
26
|
+
- No `spec.md` or `plan.md` exists and there is no clear task goal to review against
|
|
29
27
|
- Trivial typo, formatting, or config-only changes that the user wants committed directly
|
|
30
28
|
|
|
31
29
|
## Input
|
|
32
30
|
|
|
33
31
|
| Parameter | Required | Description |
|
|
34
32
|
|-----------|----------|-------------|
|
|
35
|
-
| `artifact_dir` | No | Directory containing `spec.md`
|
|
33
|
+
| `artifact_dir` | No | Directory containing `spec.md` and `plan.md`. If omitted, scan `.prizmkit/` subdirectories for the most recently modified directory with a completed `plan.md`. When invoked as a handoff step, reuse the caller's `artifact_dir` rather than re-detecting. |
|
|
36
34
|
|
|
37
|
-
## Phase 0: Context
|
|
35
|
+
## Phase 0: Context and Snapshot
|
|
38
36
|
|
|
39
37
|
1. Read `spec.md` from the artifact directory and extract goals plus acceptance criteria.
|
|
40
38
|
2. Read `plan.md` from the artifact directory and extract architecture decisions plus completed tasks.
|
|
41
|
-
3. Read scoped `/prizmkit-test` report when present:
|
|
39
|
+
3. Read a scoped `/prizmkit-test` report when present:
|
|
42
40
|
- If `{artifact_dir}/test-report-path.txt` exists, read the pointed report.
|
|
43
41
|
- Extract Scope, Generated / Updated Tests, In-Scope Failures, Baseline Failures, Out of Scope Gaps, Boundary Matrix / Boundary Completion Gate, and Verdict when present.
|
|
44
|
-
- If no
|
|
42
|
+
- If no report exists, pass `No scoped /prizmkit-test report found` as informational context. Treat missing tests as a finding only when the lifecycle path required testing before review.
|
|
45
43
|
4. Read dev rules when configured: load `.prizmkit/prizm-docs/root.prizm`, then referenced `.prizmkit/rules/<layer>-rules.md` files if any exist.
|
|
46
|
-
5. Capture
|
|
47
|
-
-
|
|
48
|
-
- `git diff`
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- relevant root
|
|
52
|
-
6. If no changes are detected, skip Phase 1 and write `review-report.md` with verdict PASS, rounds 0,
|
|
44
|
+
5. Capture the current workspace manifest and review payload according to `${SKILL_DIR}/references/reviewer-workspace-protocol.md`. Include:
|
|
45
|
+
- baseline repository and revision identity
|
|
46
|
+
- `git status`, `git diff`, and `git diff --cached` evidence
|
|
47
|
+
- staged, unstaged, untracked, deleted, and renamed path inventory
|
|
48
|
+
- changed content and stable content identities sufficient to detect missing, stale, or mixed snapshots
|
|
49
|
+
- relevant root Prizm rules and plan decisions
|
|
50
|
+
6. If no changes are detected, skip Phase 1 and write `review-report.md` with verdict PASS, rounds 0, review mode `not-run-no-changes`, and snapshot verification `NOT_APPLICABLE`.
|
|
53
51
|
|
|
54
52
|
## Phase 1: Review-Fix Loop
|
|
55
53
|
|
|
@@ -69,41 +67,43 @@ python3 --version 2>/dev/null && echo "SCRIPT_MODE" || echo "TEXT_MODE"
|
|
|
69
67
|
- `round = 1`
|
|
70
68
|
- `max_rounds = 3`
|
|
71
69
|
- `findings_history = []`
|
|
72
|
-
- `review_mode = reviewer-
|
|
70
|
+
- `review_mode = independent-reviewer-verified-snapshot` after snapshot verification succeeds
|
|
73
71
|
|
|
74
|
-
### Step 1:
|
|
72
|
+
### Step 1: Establish Independent Review
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
Use the skill-owned review contract:
|
|
77
75
|
|
|
78
76
|
```yaml
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
prompt_reference: ${SKILL_DIR}/references/reviewer-agent-prompt.md
|
|
78
|
+
workspace_protocol: ${SKILL_DIR}/references/reviewer-workspace-protocol.md
|
|
79
|
+
reviewer_contract: independent, read-only, workspace-equivalent
|
|
81
80
|
```
|
|
82
81
|
|
|
83
|
-
1.
|
|
84
|
-
2.
|
|
85
|
-
3.
|
|
86
|
-
4.
|
|
87
|
-
5.
|
|
82
|
+
1. Read both references and fill the Reviewer prompt with Phase 0 context plus the workspace manifest and payload.
|
|
83
|
+
2. Choose a subagent launch and snapshot transport strategy supported by the current platform. Strategy choice belongs to the Main Agent because platforms expose different capabilities; do not treat a particular tool parameter, checkout layout, branch name, or transport as part of the skill contract.
|
|
84
|
+
3. Require the Reviewer to verify snapshot equivalence before reviewing. Different physical paths or execution environments are acceptable when the verified review view is content-equivalent to the captured Main-Agent workspace.
|
|
85
|
+
4. If the Reviewer returns `WORKSPACE_MISMATCH`, repair or replace the strategy only when equivalence can be established safely. Otherwise write a `NEEDS_FIXES` report with the verification failure unresolved and stop; do not perform Main-Agent self-review.
|
|
86
|
+
5. After the Main Agent applies fixes, capture and verify a fresh snapshot for the next round because the previous snapshot is stale by definition.
|
|
88
87
|
|
|
89
88
|
### Step 2: Run Review
|
|
90
89
|
|
|
91
90
|
Round context:
|
|
92
91
|
- Round 1: examine all current changes comprehensively.
|
|
93
|
-
- Round 2+:
|
|
92
|
+
- Round 2+: verify prior fixes, look for regressions introduced by the fixes, and identify accepted findings that remain.
|
|
94
93
|
|
|
95
94
|
Review result:
|
|
96
95
|
- `PASS`: no findings.
|
|
97
96
|
- `NEEDS_FIXES`: one or more findings with severity, dimension, location, problem, and suggested fix.
|
|
97
|
+
- `WORKSPACE_MISMATCH`: snapshot equivalence was not established; this is a review transport failure, not a code verdict.
|
|
98
98
|
|
|
99
99
|
### Step 3: Loop Exit Gate
|
|
100
100
|
|
|
101
|
-
Call the gate only
|
|
101
|
+
Call the gate only when:
|
|
102
102
|
|
|
103
103
|
1. Review returned `PASS`.
|
|
104
|
-
2. Main Agent has filtered `NEEDS_FIXES` findings.
|
|
104
|
+
2. The Main Agent has filtered `NEEDS_FIXES` findings.
|
|
105
105
|
|
|
106
|
-
Do not call the gate for `NEEDS_FIXES` before filtering because `accepted_count` is not known
|
|
106
|
+
Do not call the gate for `NEEDS_FIXES` before filtering because `accepted_count` is not known. Handle `WORKSPACE_MISMATCH` through Step 1 rather than passing it to the code-verdict gate.
|
|
107
107
|
|
|
108
108
|
Script mode invocation:
|
|
109
109
|
|
|
@@ -111,7 +111,7 @@ Script mode invocation:
|
|
|
111
111
|
echo '{"reviewer_result":"NEEDS_FIXES","accepted_count":2,"findings_count":3,"round":1,"findings_history":[],"max_rounds":3,"filtering_done":true}' | python3 ${SKILL_DIR}/scripts/check_loop.py
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
The gate output determines whether to end the loop. If `divergenceWarning` is true, warn the user that the loop may not be converging.
|
|
115
115
|
|
|
116
116
|
### Text Fallback Constraints
|
|
117
117
|
|
|
@@ -128,36 +128,39 @@ When Python is unavailable, apply these rules manually:
|
|
|
128
128
|
|
|
129
129
|
For each finding, decide whether it is reasonable:
|
|
130
130
|
|
|
131
|
-
- Is
|
|
132
|
-
- Is
|
|
133
|
-
- Would
|
|
134
|
-
- Does
|
|
131
|
+
- Is the finding relevant to the current changes?
|
|
132
|
+
- Is it a real problem rather than a subjective style preference?
|
|
133
|
+
- Would the fix improve the code without broad out-of-scope refactoring?
|
|
134
|
+
- Does the finding conflict with the spec, plan, dev rules, or current test evidence?
|
|
135
135
|
|
|
136
136
|
Output per finding:
|
|
137
137
|
- Accepted: queue for direct Main Agent fix work.
|
|
138
|
-
- Rejected: record a short reason such as out of scope, not a defect, or too risky for current task.
|
|
138
|
+
- Rejected: record a short reason such as out of scope, not a defect, or too risky for the current task.
|
|
139
139
|
|
|
140
140
|
After filtering, call the Loop Exit Gate. If `endLoop=true`, proceed to Phase 2.
|
|
141
141
|
|
|
142
142
|
### Step 5: Main Agent Applies Accepted Fixes
|
|
143
143
|
|
|
144
|
-
The Main Agent applies accepted findings directly in
|
|
144
|
+
The Main Agent applies accepted findings directly in its current workspace. Keeping fix ownership with the Main Agent prevents the read-only Reviewer from becoming a second, conflicting implementation authority.
|
|
145
145
|
|
|
146
|
-
If an accepted finding cannot be safely
|
|
146
|
+
If an accepted finding cannot be fixed safely within scope, record the reason and carry the finding into `review-report.md` as unresolved.
|
|
147
147
|
|
|
148
|
-
After fixes are complete, record results, increment the round, and return to Step
|
|
148
|
+
After fixes are complete, record results, increment the round, capture a fresh workspace snapshot, and return to Step 1.
|
|
149
149
|
|
|
150
150
|
## Phase 2: Output
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
Write `review-report.md` to the artifact directory, including no-change PASS and workspace-verification failure results. Read `${SKILL_DIR}/references/review-report-template.md` for the full output format.
|
|
153
153
|
|
|
154
154
|
Required report fields:
|
|
155
155
|
- Verdict: `PASS` or `NEEDS_FIXES`
|
|
156
|
-
- Review Mode: `reviewer-
|
|
156
|
+
- Review Mode: `independent-reviewer-verified-snapshot` or `not-run-no-changes`
|
|
157
|
+
- Reviewer Strategy: concise strategy summary without relying on platform-specific parameter names
|
|
158
|
+
- Snapshot Verification: `VERIFIED`, `FAILED`, or `NOT_APPLICABLE`
|
|
159
|
+
- Snapshot Identity: manifest identity or failure reason
|
|
157
160
|
- Rounds and total findings
|
|
158
161
|
- Fixed, rejected, and unresolved findings
|
|
159
162
|
- Final summary
|
|
160
163
|
|
|
161
164
|
Completion summary:
|
|
162
165
|
- `PASS`: hand off to `/prizmkit-retrospective` when docs or durable knowledge changed, otherwise `/prizmkit-committer`.
|
|
163
|
-
- `NEEDS_FIXES`: inform the caller of
|
|
166
|
+
- `NEEDS_FIXES`: inform the caller of unresolved code findings or snapshot-verification blockers.
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Review Report Output Template
|
|
2
2
|
|
|
3
|
-
Used in Phase 2 of `/prizmkit-code-review`.
|
|
3
|
+
Used in Phase 2 of `/prizmkit-code-review`. Write `review-report.md` to the artifact directory using this format.
|
|
4
4
|
|
|
5
5
|
```markdown
|
|
6
6
|
# Review Report
|
|
7
7
|
|
|
8
8
|
## Verdict: <PASS|NEEDS_FIXES>
|
|
9
|
-
## Review Mode: <reviewer-
|
|
10
|
-
##
|
|
9
|
+
## Review Mode: <independent-reviewer-verified-snapshot|not-run-no-changes>
|
|
10
|
+
## Reviewer Strategy: <platform-selected strategy summary|not-applicable>
|
|
11
|
+
## Snapshot Verification: <VERIFIED|FAILED|NOT_APPLICABLE>
|
|
12
|
+
## Snapshot Identity: <manifest identity or failure reason>
|
|
13
|
+
## Rounds: <number of completed review rounds; use 0 for no-change PASS or pre-review snapshot failure>
|
|
11
14
|
## Total findings: <total> → Fixed: <fixed>, Rejected: <rejected>, Unresolved: <unresolved>
|
|
12
15
|
|
|
13
16
|
## Round <N>
|
|
@@ -15,18 +18,20 @@ Findings: <count> | Accepted: <count>, Rejected: <count>
|
|
|
15
18
|
|
|
16
19
|
### Finding <N>: <short title>
|
|
17
20
|
- Severity: <high|medium|low>
|
|
18
|
-
- Dimension: <goal-alignment|defect|completeness|consistency|security|rules-compliance>
|
|
21
|
+
- Dimension: <goal-alignment|defect|completeness|consistency|security|test-quality|rules-compliance>
|
|
19
22
|
- Location: <filepath:line or project-level>
|
|
20
23
|
- Problem: <what was wrong and why it mattered>
|
|
21
24
|
- Status: <fixed (round N)|rejected — reason|unresolved — reason>
|
|
22
25
|
|
|
23
26
|
## Final Summary
|
|
24
|
-
<One to three sentences summarizing the review outcome,
|
|
27
|
+
<One to three sentences summarizing the review outcome, snapshot verification, and any remaining blocker.>
|
|
25
28
|
```
|
|
26
29
|
|
|
27
|
-
For `PASS` with no findings, write `Total findings: 0 → Fixed: 0, Rejected: 0, Unresolved: 0` and `## Round 0: PASS — no workspace changes to review` or `## Round N: PASS — no issues found`.
|
|
30
|
+
For `PASS` with no findings, write `Total findings: 0 → Fixed: 0, Rejected: 0, Unresolved: 0` and either `## Round 0: PASS — no workspace changes to review` or `## Round N: PASS — no issues found`.
|
|
31
|
+
|
|
32
|
+
For snapshot verification failure, use verdict `NEEDS_FIXES`, snapshot verification `FAILED`, and record the mismatch as an unresolved review blocker rather than an ordinary code finding.
|
|
28
33
|
|
|
29
34
|
## Verdict Rules
|
|
30
35
|
|
|
31
|
-
- `PASS`: Reviewer returned no findings, no workspace changes existed, or all
|
|
32
|
-
- `NEEDS_FIXES`: Max rounds completed
|
|
36
|
+
- `PASS`: Reviewer returned no findings from a verified snapshot, no workspace changes existed, or all findings from a verified snapshot were rejected as unreasonable.
|
|
37
|
+
- `NEEDS_FIXES`: Max rounds completed with accepted findings unresolved, or no independent Reviewer could verify an equivalent current snapshot.
|