prizmkit 1.1.119 → 1.1.120
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/runners.py +45 -3
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +28 -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/utils.py +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -9
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +2 -2
- 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 +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +20 -0
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +2 -2
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +204 -141
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +16 -10
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +2 -13
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +13 -14
- package/bundled/dev-pipeline/tests/test_unified_cli.py +205 -6
- package/bundled/skills/_metadata.json +1 -1
- 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 +16 -14
- package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +9 -9
- package/bundled/skills/prizmkit-implement/SKILL.md +21 -1
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +67 -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/team/prizm-dev-team.json +0 -27
|
@@ -811,8 +811,8 @@ def test_prompt_generation_passes_explicit_execution_root_to_generator(monkeypat
|
|
|
811
811
|
"output_path": str(session_paths.prompt_path),
|
|
812
812
|
"checkpoint_path": str(execution_root / ".prizmkit" / "specs" / "001-low" / "workflow-checkpoint.json"),
|
|
813
813
|
"model": "",
|
|
814
|
-
"pipeline_mode": "
|
|
815
|
-
"agent_count":
|
|
814
|
+
"pipeline_mode": "full",
|
|
815
|
+
"agent_count": 3,
|
|
816
816
|
}
|
|
817
817
|
),
|
|
818
818
|
stderr="",
|
|
@@ -876,8 +876,8 @@ def _install_runner_session_fakes(monkeypatch, runners, *, statuses=("success",)
|
|
|
876
876
|
return PromptGenerationResult(
|
|
877
877
|
output_path=session_paths.prompt_path,
|
|
878
878
|
model="per-item-model",
|
|
879
|
-
pipeline_mode="
|
|
880
|
-
agent_count=
|
|
879
|
+
pipeline_mode="full",
|
|
880
|
+
agent_count=3,
|
|
881
881
|
checkpoint_path=execution_root / ".prizmkit" / "specs" / "001-low" / "workflow-checkpoint.json",
|
|
882
882
|
artifact_path=execution_root / ".prizmkit" / "specs" / "001-low",
|
|
883
883
|
raw={},
|
|
@@ -1090,13 +1090,12 @@ def test_explicit_worktree_materializes_ignored_support_assets_before_prompt_and
|
|
|
1090
1090
|
subprocess.run(["git", "add", ".gitignore", "tracked.txt"], cwd=project, check=True)
|
|
1091
1091
|
subprocess.run(["git", "commit", "-m", "base"], cwd=project, check=True, stdout=subprocess.DEVNULL)
|
|
1092
1092
|
|
|
1093
|
-
(project / ".claude" / "
|
|
1094
|
-
(project / ".claude" / "
|
|
1095
|
-
(project / ".claude" / "team-info.json").write_text("{}", encoding="utf-8")
|
|
1093
|
+
(project / ".claude" / "commands").mkdir(parents=True)
|
|
1094
|
+
(project / ".claude" / "commands" / "prizmkit.md").write_text("skill", encoding="utf-8")
|
|
1096
1095
|
(project / ".prizmkit" / "prizm-docs").mkdir(parents=True)
|
|
1097
1096
|
(project / ".prizmkit" / "prizm-docs" / "root.prizm").write_text("PRIZM_VERSION: 1\n", encoding="utf-8")
|
|
1098
1097
|
(project / ".prizmkit" / "dev-pipeline" / "scripts").mkdir(parents=True)
|
|
1099
|
-
(project / ".prizmkit" / "dev-pipeline" / "scripts" / "init-
|
|
1098
|
+
(project / ".prizmkit" / "dev-pipeline" / "scripts" / "init-change-artifact.py").write_text("# init", encoding="utf-8")
|
|
1100
1099
|
(project / ".prizmkit" / "config.json").write_text("{}", encoding="utf-8")
|
|
1101
1100
|
(project / ".prizmkit" / "manifest.json").write_text("{}", encoding="utf-8")
|
|
1102
1101
|
|
|
@@ -1128,18 +1127,18 @@ def test_explicit_worktree_materializes_ignored_support_assets_before_prompt_and
|
|
|
1128
1127
|
def fake_generate_prompt(family, invocation, **kwargs):
|
|
1129
1128
|
execution_root = kwargs["execution_root"]
|
|
1130
1129
|
assert execution_root != project
|
|
1131
|
-
assert (execution_root / ".claude" / "
|
|
1130
|
+
assert (execution_root / ".claude" / "commands" / "prizmkit.md").is_file()
|
|
1132
1131
|
assert (execution_root / ".prizmkit" / "prizm-docs" / "root.prizm").is_file()
|
|
1133
1132
|
assert (execution_root / ".prizmkit" / "config.json").is_file()
|
|
1134
1133
|
assert (execution_root / ".prizmkit" / "manifest.json").is_file()
|
|
1135
|
-
assert (execution_root / ".prizmkit" / "dev-pipeline" / "scripts" / "init-
|
|
1134
|
+
assert (execution_root / ".prizmkit" / "dev-pipeline" / "scripts" / "init-change-artifact.py").is_file()
|
|
1136
1135
|
assert not (execution_root / ".prizmkit" / "dev-pipeline" / "run-feature.sh").exists()
|
|
1137
1136
|
session_paths = kwargs["session_paths"]
|
|
1138
1137
|
return PromptGenerationResult(
|
|
1139
1138
|
output_path=session_paths.prompt_path,
|
|
1140
1139
|
model="",
|
|
1141
|
-
pipeline_mode="
|
|
1142
|
-
agent_count=
|
|
1140
|
+
pipeline_mode="full",
|
|
1141
|
+
agent_count=3,
|
|
1143
1142
|
checkpoint_path=execution_root / ".prizmkit" / "specs" / "001-support" / "workflow-checkpoint.json",
|
|
1144
1143
|
artifact_path=execution_root / ".prizmkit" / "specs" / "001-support",
|
|
1145
1144
|
raw={},
|
|
@@ -1535,8 +1534,8 @@ def test_foreground_runner_emits_structured_feature_progress(monkeypatch, tmp_pa
|
|
|
1535
1534
|
assert "Feature: F-001 — Readable output" in captured.err
|
|
1536
1535
|
assert "Code retry: 1 / 3" in captured.err
|
|
1537
1536
|
assert "Preflight: no user-visible changes to preserve before feature task F-001" in captured.err
|
|
1538
|
-
assert "Pipeline mode:
|
|
1539
|
-
assert "Agents:
|
|
1537
|
+
assert "Pipeline mode: full (Tier 3 — Orchestrator + Reviewer)" in captured.err
|
|
1538
|
+
assert "Agents: 3" in captured.err
|
|
1540
1539
|
assert "Spawning AI CLI session: F-001-session-1" in captured.err
|
|
1541
1540
|
assert "Session result: success" in captured.err
|
|
1542
1541
|
|
|
@@ -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
|
|
|
@@ -793,7 +804,7 @@ def test_session_preamble_writes_redacted_start_command_for_all_launch_profiles(
|
|
|
793
804
|
|
|
794
805
|
def test_headless_subagent_prompt_guidance_keeps_no_worktree_boundary_visible():
|
|
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
|
]
|
|
@@ -840,6 +851,145 @@ def test_progress_parser_adds_required_metadata(tmp_path):
|
|
|
840
851
|
assert data["permission_denial_count"] == 1
|
|
841
852
|
|
|
842
853
|
|
|
854
|
+
|
|
855
|
+
def test_progress_parser_normalizes_claude_subagents_without_double_counting(tmp_path):
|
|
856
|
+
module = _load_progress_parser_module()
|
|
857
|
+
tracker = module.ProgressTracker()
|
|
858
|
+
|
|
859
|
+
tracker.process_event({"type": "system", "subtype": "init", "session_id": "claude-session", "cwd": str(tmp_path)})
|
|
860
|
+
tracker.process_event({
|
|
861
|
+
"type": "assistant",
|
|
862
|
+
"message": {"content": [{
|
|
863
|
+
"type": "tool_use",
|
|
864
|
+
"id": "tool-1",
|
|
865
|
+
"name": "Agent",
|
|
866
|
+
"input": {"description": "review code", "prompt": "check", "subagent_type": "reviewer"},
|
|
867
|
+
}]},
|
|
868
|
+
})
|
|
869
|
+
tracker.process_event({
|
|
870
|
+
"type": "system",
|
|
871
|
+
"subtype": "task_started",
|
|
872
|
+
"task_id": "task-1",
|
|
873
|
+
"tool_use_id": "tool-1",
|
|
874
|
+
"task_type": "in_process_teammate",
|
|
875
|
+
"subagent_type": "reviewer",
|
|
876
|
+
"description": "review code",
|
|
877
|
+
})
|
|
878
|
+
tracker.process_event({"type": "assistant", "parent_tool_use_id": "tool-1", "message": {"content": [{"type": "text", "text": "child activity"}]}})
|
|
879
|
+
tracker.process_event({"type": "system", "subtype": "task_started", "task_id": "bash-1", "task_type": "local_bash", "description": "ls"})
|
|
880
|
+
tracker.process_event({"type": "system", "subtype": "task_notification", "task_id": "task-1", "tool_use_id": "tool-1", "status": "completed", "summary": "done"})
|
|
881
|
+
|
|
882
|
+
data = tracker.to_dict()
|
|
883
|
+
|
|
884
|
+
assert data["subagent_stats_source"] == "session_log"
|
|
885
|
+
assert data["subagent_spawn_count"] == 1
|
|
886
|
+
assert data["active_subagent_count"] == 0
|
|
887
|
+
assert data["subagent_states"] == [{"status": "completed", "count": 1}]
|
|
888
|
+
assert "task-1" in data["subagent_observed_ids"]
|
|
889
|
+
assert "tool-1" in data["subagent_statistics"]["parent_activity_ids"]
|
|
890
|
+
assert all("bash" not in record["id"] for record in data["subagent_statistics"]["records"])
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
def test_progress_parser_normalizes_codebuddy_agent_tools_with_deduplication():
|
|
894
|
+
module = _load_progress_parser_module()
|
|
895
|
+
tracker = module.ProgressTracker()
|
|
896
|
+
args = {"prompt": "inspect", "description": "inspect", "subagent_type": "Explore"}
|
|
897
|
+
|
|
898
|
+
tracker.process_event({
|
|
899
|
+
"type": "message",
|
|
900
|
+
"sessionId": "cb-session",
|
|
901
|
+
"cwd": "/tmp/project",
|
|
902
|
+
"role": "assistant",
|
|
903
|
+
"content": [{"type": "tool_use", "id": "call-1", "name": "Agent", "input": args}],
|
|
904
|
+
})
|
|
905
|
+
tracker.process_event({
|
|
906
|
+
"type": "function_call",
|
|
907
|
+
"sessionId": "cb-session",
|
|
908
|
+
"cwd": "/tmp/project",
|
|
909
|
+
"id": "call-1",
|
|
910
|
+
"name": "Agent",
|
|
911
|
+
"arguments": json.dumps(args),
|
|
912
|
+
})
|
|
913
|
+
tracker.process_event({
|
|
914
|
+
"type": "function_call",
|
|
915
|
+
"sessionId": "cb-session",
|
|
916
|
+
"cwd": "/tmp/project",
|
|
917
|
+
"id": "task-call",
|
|
918
|
+
"name": "TaskCreate",
|
|
919
|
+
"arguments": json.dumps({"description": "background", "subject": "status"}),
|
|
920
|
+
})
|
|
921
|
+
|
|
922
|
+
data = tracker.to_dict()
|
|
923
|
+
|
|
924
|
+
assert data["cb_session_id"] == "cb-session"
|
|
925
|
+
assert data["subagent_provider"] == "codebuddy"
|
|
926
|
+
assert data["subagent_spawn_count"] == 2
|
|
927
|
+
assert data["active_subagent_count"] == 2
|
|
928
|
+
assert {item["status"] for item in data["subagent_states"]} == {"running"}
|
|
929
|
+
assert len(data["subagent_statistics"]["records"]) == 2
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
def test_progress_parser_normalizes_codex_collab_metadata_with_missing_fields():
|
|
933
|
+
module = _load_progress_parser_module()
|
|
934
|
+
tracker = module.ProgressTracker()
|
|
935
|
+
|
|
936
|
+
tracker.process_event({"type": "thread.started", "thread_id": "parent"})
|
|
937
|
+
tracker.process_event({
|
|
938
|
+
"type": "item.started",
|
|
939
|
+
"item": {
|
|
940
|
+
"type": "collab_tool_call",
|
|
941
|
+
"tool": "delegate",
|
|
942
|
+
"receiver_thread_ids": ["thread-a", "thread-b"],
|
|
943
|
+
"agents_states": {
|
|
944
|
+
"thread-a": {"status": "running", "message": "working"},
|
|
945
|
+
"thread-b": {"status": "completed", "message": "done"},
|
|
946
|
+
},
|
|
947
|
+
},
|
|
948
|
+
})
|
|
949
|
+
tracker.process_event({"type": "item.completed", "item": {"type": "collab_tool_call", "tool": "delegate"}})
|
|
950
|
+
|
|
951
|
+
data = tracker.to_dict()
|
|
952
|
+
|
|
953
|
+
assert data["event_format"] == "codex-json"
|
|
954
|
+
assert data["child_thread_ids"] == ["thread-a", "thread-b"]
|
|
955
|
+
assert data["subagent_spawn_count"] == 2
|
|
956
|
+
assert data["active_subagent_count"] == 1
|
|
957
|
+
assert {state["status"]: state["count"] for state in data["subagent_states"]} == {"running": 1, "completed": 1}
|
|
958
|
+
assert data["subagent_source_metadata"]["child_activity_source"] == "filesystem_liveness_only"
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
def test_progress_parser_keeps_child_files_liveness_only(tmp_path, monkeypatch):
|
|
962
|
+
module = _load_progress_parser_module()
|
|
963
|
+
claude_home = tmp_path / "claude"
|
|
964
|
+
project_key = str(tmp_path).replace("\\", "-").replace("/", "-").replace(":", "")
|
|
965
|
+
subagents_dir = claude_home / "projects" / project_key / "parent-session" / "subagents"
|
|
966
|
+
subagents_dir.mkdir(parents=True)
|
|
967
|
+
child_log = subagents_dir / "agent-child.jsonl"
|
|
968
|
+
child_log.write_text("child activity", encoding="utf-8")
|
|
969
|
+
monkeypatch.setenv("CLAUDE_HOME", str(claude_home))
|
|
970
|
+
|
|
971
|
+
tracker = module.ProgressTracker()
|
|
972
|
+
tracker.process_event({"type": "system", "subtype": "init", "session_id": "parent-session", "cwd": str(tmp_path)})
|
|
973
|
+
tracker.process_event({
|
|
974
|
+
"type": "system",
|
|
975
|
+
"subtype": "task_started",
|
|
976
|
+
"task_id": "task-1",
|
|
977
|
+
"tool_use_id": "tool-1",
|
|
978
|
+
"task_type": "in_process_teammate",
|
|
979
|
+
"description": "agent",
|
|
980
|
+
})
|
|
981
|
+
first = tracker.to_dict()
|
|
982
|
+
child_log.write_text("child activity grew", encoding="utf-8")
|
|
983
|
+
tracker.refresh_child_session_activity(force=True)
|
|
984
|
+
second = tracker.to_dict()
|
|
985
|
+
|
|
986
|
+
assert first["subagent_spawn_count"] == 1
|
|
987
|
+
assert second["subagent_spawn_count"] == 1
|
|
988
|
+
assert second["child_total_bytes"] > first["child_total_bytes"]
|
|
989
|
+
assert second["child_session_files"]
|
|
990
|
+
assert second["child_activity_source"] == "filesystem_liveness_only"
|
|
991
|
+
assert second["subagent_statistics"]["source"] == "session_log"
|
|
992
|
+
|
|
843
993
|
def test_session_dual_writes_progress_and_recovers_backup(tmp_path):
|
|
844
994
|
from prizmkit_runtime.sessions import AISessionConfig, AISessionLauncher, recover_session_log
|
|
845
995
|
|
|
@@ -935,6 +1085,10 @@ def test_custom_session_launch_writes_existing_logs_and_progress(tmp_path):
|
|
|
935
1085
|
progress_data = json.loads(progress.read_text(encoding="utf-8"))
|
|
936
1086
|
assert progress_data["event_type_counts"]["result"] == 1
|
|
937
1087
|
assert progress_data["has_usage"] is True
|
|
1088
|
+
assert progress_data["subagent_stats_source"] == "session_log"
|
|
1089
|
+
assert progress_data["subagent_spawn_count"] == 0
|
|
1090
|
+
assert progress_data["subagent_statistics"]["providers"] == []
|
|
1091
|
+
assert progress_data["child_activity_source"] == "filesystem_liveness_only"
|
|
938
1092
|
|
|
939
1093
|
|
|
940
1094
|
@pytest.mark.parametrize("platform", ["claude", "codex", "codebuddy"])
|
|
@@ -1031,7 +1185,10 @@ def test_compact_progress_line_hides_stale_until_no_progress(tmp_path):
|
|
|
1031
1185
|
json.dumps(
|
|
1032
1186
|
{
|
|
1033
1187
|
"child_total_bytes": 2 * 1024 * 1024,
|
|
1188
|
+
"child_session_files": [{"path": "a"}, {"path": "b"}],
|
|
1034
1189
|
"subagent_spawn_count": 5,
|
|
1190
|
+
"active_subagent_count": 2,
|
|
1191
|
+
"subagent_states": [{"status": "running", "count": 2}, {"status": "completed", "count": 3}],
|
|
1035
1192
|
"current_phase": "stream-derived-phase",
|
|
1036
1193
|
"current_tool": "Read",
|
|
1037
1194
|
"message_count": 465,
|
|
@@ -1059,7 +1216,9 @@ def test_compact_progress_line_hides_stale_until_no_progress(tmp_path):
|
|
|
1059
1216
|
|
|
1060
1217
|
assert "▶ [HEARTBEAT]" in running_line
|
|
1061
1218
|
assert "log: 4MB" in running_line
|
|
1062
|
-
assert "
|
|
1219
|
+
assert "subagents: spawned=5 active=2 states:running=2,completed=3" in running_line
|
|
1220
|
+
assert "child logs: 2MB/2 files" in running_line
|
|
1221
|
+
assert "child: 2MB/5" not in running_line
|
|
1063
1222
|
assert "phase: Retrospective" in running_line
|
|
1064
1223
|
assert "stream-derived-phase" not in running_line
|
|
1065
1224
|
assert "tool: Read" in running_line
|
|
@@ -1417,6 +1576,46 @@ def test_recovery_sessions_receive_live_heartbeat_configuration(tmp_path, monkey
|
|
|
1417
1576
|
assert config.suppress_stream_output is True
|
|
1418
1577
|
|
|
1419
1578
|
|
|
1579
|
+
|
|
1580
|
+
def test_session_summary_reports_normalized_subagents_and_child_liveness(tmp_path, capsys):
|
|
1581
|
+
import prizmkit_runtime.runners as runners
|
|
1582
|
+
from prizmkit_runtime.runner_models import SessionPaths
|
|
1583
|
+
|
|
1584
|
+
logs = tmp_path / "sessions" / "s1" / "logs"
|
|
1585
|
+
logs.mkdir(parents=True)
|
|
1586
|
+
session_log = logs / "session.log"
|
|
1587
|
+
progress = logs / "progress.json"
|
|
1588
|
+
session_log.write_text("one\ntwo\n", encoding="utf-8")
|
|
1589
|
+
progress.write_text(
|
|
1590
|
+
json.dumps({
|
|
1591
|
+
"subagent_spawn_count": 2,
|
|
1592
|
+
"active_subagent_count": 1,
|
|
1593
|
+
"subagent_states": [{"status": "running", "count": 1}, {"status": "completed", "count": 1}],
|
|
1594
|
+
"subagent_statistics": {"spawned": 2, "active": 1, "providers": ["claude"], "source": "session_log"},
|
|
1595
|
+
"child_total_bytes": 2048,
|
|
1596
|
+
"child_session_files": [{"path": "child-a"}],
|
|
1597
|
+
}),
|
|
1598
|
+
encoding="utf-8",
|
|
1599
|
+
)
|
|
1600
|
+
paths = SessionPaths(
|
|
1601
|
+
session_dir=logs.parent,
|
|
1602
|
+
prompt_path=logs.parent / "bootstrap-prompt.md",
|
|
1603
|
+
logs_dir=logs,
|
|
1604
|
+
session_log=session_log,
|
|
1605
|
+
progress_json=progress,
|
|
1606
|
+
heartbeat_json=logs / "heartbeat.json",
|
|
1607
|
+
session_status_json=logs / "session-status.json",
|
|
1608
|
+
)
|
|
1609
|
+
result = type("Result", (), {"exit_code": 0})()
|
|
1610
|
+
classification = type("Classification", (), {"session_status": "success"})()
|
|
1611
|
+
|
|
1612
|
+
runners._emit_session_summary(result, paths, classification)
|
|
1613
|
+
|
|
1614
|
+
captured = capsys.readouterr()
|
|
1615
|
+
assert "Subagents: spawned=2, active=1, states: running=1, completed=1 (claude; source=session.log)" in captured.err
|
|
1616
|
+
assert "Child log activity: 2KB across 1 files (heartbeat liveness only)" in captured.err
|
|
1617
|
+
assert "Subagent calls detected" not in captured.err
|
|
1618
|
+
|
|
1420
1619
|
def test_session_live_output_does_not_forward_cli_output_without_verbose(tmp_path, capsys):
|
|
1421
1620
|
from prizmkit_runtime.sessions import AISessionConfig, AISessionLauncher
|
|
1422
1621
|
|
|
@@ -1995,8 +2194,8 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
|
|
|
1995
2194
|
subprocess.run(["git", "add", ".gitignore"], cwd=repo, check=True)
|
|
1996
2195
|
subprocess.run(["git", "commit", "-m", "ignore support"], cwd=repo, check=True, stdout=subprocess.DEVNULL)
|
|
1997
2196
|
|
|
1998
|
-
(repo / ".claude" / "
|
|
1999
|
-
(repo / ".claude" / "
|
|
2197
|
+
(repo / ".claude" / "commands").mkdir(parents=True)
|
|
2198
|
+
(repo / ".claude" / "commands" / "prizmkit.md").write_text("skill", encoding="utf-8")
|
|
2000
2199
|
(repo / ".prizmkit" / "prizm-docs").mkdir(parents=True)
|
|
2001
2200
|
(repo / ".prizmkit" / "prizm-docs" / "root.prizm").write_text("PRIZM_VERSION: 1\n", encoding="utf-8")
|
|
2002
2201
|
(repo / ".prizmkit" / "config.json").write_text("{}", encoding="utf-8")
|
|
@@ -2014,12 +2213,12 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
|
|
|
2014
2213
|
)
|
|
2015
2214
|
setup = ensure_linked_worktree(runtime)
|
|
2016
2215
|
assert setup.ok
|
|
2017
|
-
assert not (runtime.worktree_path / ".claude" / "
|
|
2216
|
+
assert not (runtime.worktree_path / ".claude" / "commands" / "prizmkit.md").exists()
|
|
2018
2217
|
|
|
2019
2218
|
result = materialize_worktree_support_assets(runtime)
|
|
2020
2219
|
|
|
2021
2220
|
assert result.ok
|
|
2022
|
-
assert (runtime.worktree_path / ".claude" / "
|
|
2221
|
+
assert (runtime.worktree_path / ".claude" / "commands" / "prizmkit.md").is_file()
|
|
2023
2222
|
assert (runtime.worktree_path / ".prizmkit" / "prizm-docs" / "root.prizm").is_file()
|
|
2024
2223
|
assert (runtime.worktree_path / ".prizmkit" / "config.json").is_file()
|
|
2025
2224
|
assert (runtime.worktree_path / ".prizmkit" / "manifest.json").is_file()
|
|
@@ -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,20 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "prizmkit-code-review"
|
|
3
|
-
description: "Iterative review-fix loop against spec and plan. Always uses
|
|
3
|
+
description: "Iterative review-fix loop against spec and plan. Always uses an independent inline reviewer subagent in the active checkout with a skill-owned prompt reference and no worktree/copy/remote isolation; the Main Agent filters findings and applies accepted fixes directly. If the platform cannot start an active-checkout inline reviewer, stop with checkout-isolation incompatibility instead of falling back to Main-Agent self-review. Loops until PASS or max 3 rounds. Use after /prizmkit-implement for Full path quality gate or when the user says 'review', 'check code', 'code review', or 'is it ready to commit'. (project)"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PrizmKit Code Review
|
|
7
7
|
|
|
8
|
-
An iterative review-fix loop that checks workspace changes against the task spec and plan. It separates review judgment from fix application by requiring
|
|
8
|
+
An iterative review-fix loop that checks workspace changes against the task spec and plan. It separates review judgment from fix application by requiring an independent inline reviewer subagent launched from the active checkout with a prompt loaded from this skill's references. Main Agent applies accepted fixes directly after filtering reviewer findings.
|
|
9
9
|
|
|
10
10
|
Review modes:
|
|
11
|
-
- `reviewer-
|
|
11
|
+
- `inline-reviewer-active-checkout`: required mode. Always spawn an independent reviewer subagent in the current active checkout with no worktree, copied checkout, remote checkout, or branch isolation.
|
|
12
12
|
- `not-run-no-changes`: no workspace changes were detected.
|
|
13
13
|
|
|
14
|
-
If the platform cannot launch
|
|
14
|
+
If the platform cannot launch an inline reviewer subagent in current-workspace / active-checkout / no-worktree mode, stop with this checkout-isolation incompatibility message:
|
|
15
15
|
|
|
16
16
|
```text
|
|
17
|
-
Cannot run /prizmkit-code-review because this platform cannot start
|
|
17
|
+
Cannot run /prizmkit-code-review because this platform cannot start an inline reviewer subagent in the active checkout without worktree, copy, remote, or branch isolation.
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
### When to Use
|
|
@@ -48,6 +48,7 @@ Cannot run /prizmkit-code-review because this platform cannot start prizm-dev-te
|
|
|
48
48
|
- `git diff`
|
|
49
49
|
- `git diff --cached`
|
|
50
50
|
- full paths for untracked and renamed files
|
|
51
|
+
- expected active checkout git top-level from `git rev-parse --show-toplevel`
|
|
51
52
|
- relevant root.prizm RULES and plan decisions
|
|
52
53
|
6. If no changes are detected, skip Phase 1 and write `review-report.md` with verdict PASS, rounds 0, and review mode `not-run-no-changes`.
|
|
53
54
|
|
|
@@ -69,22 +70,23 @@ python3 --version 2>/dev/null && echo "SCRIPT_MODE" || echo "TEXT_MODE"
|
|
|
69
70
|
- `round = 1`
|
|
70
71
|
- `max_rounds = 3`
|
|
71
72
|
- `findings_history = []`
|
|
72
|
-
- `review_mode = reviewer-
|
|
73
|
+
- `review_mode = inline-reviewer-active-checkout` after confirming an inline reviewer subagent can launch in the active checkout
|
|
73
74
|
|
|
74
|
-
### Step 1: Launch Required Reviewer
|
|
75
|
+
### Step 1: Launch Required Inline Reviewer
|
|
75
76
|
|
|
76
|
-
Always spawn
|
|
77
|
+
Always spawn an independent reviewer subagent using this skill-owned inline contract:
|
|
77
78
|
|
|
78
79
|
```yaml
|
|
79
|
-
|
|
80
|
+
prompt_reference: ${SKILL_DIR}/references/reviewer-agent-prompt.md
|
|
80
81
|
isolation: current-workspace / active-checkout / no-worktree
|
|
82
|
+
subagent_kind: inline reviewer prompt, not a platform-installed named agent
|
|
81
83
|
```
|
|
82
84
|
|
|
83
|
-
1.
|
|
85
|
+
1. Read `${SKILL_DIR}/references/reviewer-agent-prompt.md` and fill it with the active-checkout context from Phase 0.
|
|
84
86
|
2. The captured git diff, staged diff, untracked files, spec, plan, dev rules, and scoped test report are the primary review scope.
|
|
85
|
-
3. Never use
|
|
87
|
+
3. Never use worktree isolation, remote isolation, copied checkouts, branch switching, broad repository exploration, or a generic code explorer as a substitute for the required inline reviewer prompt. Do not request or create tool-managed worktrees, pipeline-managed worktrees, copied repositories, or remote checkouts. Do not use `.claude/worktrees/...` or `.prizmkit/state/worktrees/...`. Pipeline runner `USE_WORKTREE` controls outer infrastructure only; it does not change this skill's active-checkout reviewer requirement.
|
|
86
88
|
4. Never perform Main-Agent self-review or fallback review; the Main Agent's job is filtering and fixing, not acting as the reviewer.
|
|
87
|
-
5. If the platform cannot launch the reviewer in the active checkout without worktree isolation, stop with the
|
|
89
|
+
5. If the platform cannot launch the reviewer in the active checkout without worktree/copy/remote/branch isolation, stop with the checkout-isolation incompatibility message from this skill's introduction.
|
|
88
90
|
|
|
89
91
|
### Step 2: Run Review
|
|
90
92
|
|
|
@@ -141,7 +143,7 @@ After filtering, call the Loop Exit Gate. If `endLoop=true`, proceed to Phase 2.
|
|
|
141
143
|
|
|
142
144
|
### Step 5: Main Agent Applies Accepted Fixes
|
|
143
145
|
|
|
144
|
-
The Main Agent applies accepted findings directly in the active checkout. Do not spawn a separate
|
|
146
|
+
The Main Agent applies accepted findings directly in the active checkout. Do not spawn a separate implementation subagent for review fixes.
|
|
145
147
|
|
|
146
148
|
If an accepted finding cannot be safely fixed within scope, record the reason and carry it into `review-report.md` as unresolved.
|
|
147
149
|
|
|
@@ -153,7 +155,7 @@ Always write `review-report.md` to the artifact directory, including no-change P
|
|
|
153
155
|
|
|
154
156
|
Required report fields:
|
|
155
157
|
- Verdict: `PASS` or `NEEDS_FIXES`
|
|
156
|
-
- Review Mode: `reviewer-
|
|
158
|
+
- Review Mode: `inline-reviewer-active-checkout` or `not-run-no-changes`
|
|
157
159
|
- Rounds and total findings
|
|
158
160
|
- Fixed, rejected, and unresolved findings
|
|
159
161
|
- Final summary
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# Reviewer
|
|
1
|
+
# Reviewer Subagent Prompt Template
|
|
2
2
|
|
|
3
|
-
Used in Phase 1 Step 1 of `/prizmkit-code-review`. The orchestrator fills `{goals}`, `{plan decisions}`, `{scoped test report}`, `{workspace context}`, `{dev rules}`, `{round N}`, and `{round_context}` before spawning
|
|
3
|
+
Used in Phase 1 Step 1 of `/prizmkit-code-review`. The orchestrator fills `{goals}`, `{plan decisions}`, `{scoped test report}`, `{workspace context}`, `{dev rules}`, `{round N}`, and `{round_context}` before spawning an independent inline reviewer subagent from the active checkout.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
You are
|
|
6
|
+
You are an independent PrizmKit reviewer subagent launched by `/prizmkit-code-review` from the active checkout. Review workspace changes against the spec goals, plan decisions, scoped test evidence, and per-layer dev rules. Do not modify files and do not apply fixes; the Main Agent will filter findings and apply accepted fixes directly.
|
|
7
7
|
|
|
8
8
|
## Spec Goals
|
|
9
9
|
{goals and acceptance criteria from spec.md}
|
|
@@ -15,18 +15,18 @@ You are the dedicated PrizmKit Reviewer agent (`prizm-dev-team-reviewer`). Revie
|
|
|
15
15
|
{summary from artifact_dir/test-report-path.txt and test-report.md, including Scope, Generated / Updated Tests, In-Scope Failures, Baseline Failures, Out of Scope Gaps, Boundary Matrix / Boundary Completion Gate if present, and Verdict. If no scoped report exists for a change artifact, write "No scoped /prizmkit-test report found (expected for pre-test review)." Treat that absence as informational unless the calling workflow explicitly requires a prior test report.}
|
|
16
16
|
|
|
17
17
|
## Workspace Context
|
|
18
|
-
{git status, unstaged diff summary, staged diff summary, current working directory, expected active checkout git top-level, and new-file paths captured by the Main Agent in Phase 0 from the active checkout. This is your primary review scope — use this context to understand what changed. Request targeted file reads only when you need specific line-level detail for a finding, not to re-discover or re-index the repository. Do not read files that are not in the workspace context unless you need them to verify impact (callers, dependents, shared patterns).
|
|
18
|
+
{git status, unstaged diff summary, staged diff summary, current working directory, expected active checkout git top-level, and new-file paths captured by the Main Agent in Phase 0 from the active checkout. This is your primary review scope — use this context to understand what changed. Request targeted file reads only when you need specific line-level detail for a finding, not to re-discover or re-index the repository. Do not read files that are not in the workspace context unless you need them to verify impact (callers, dependents, shared patterns).}
|
|
19
19
|
|
|
20
20
|
## Active Checkout Guard
|
|
21
21
|
The orchestrator must provide the expected active checkout git top-level in Workspace Context. Before reviewing, verify that your current git top-level matches that expected active checkout.
|
|
22
22
|
|
|
23
|
-
If your current checkout is different, or appears to be under `.claude/worktrees/`, `.prizmkit/state/worktrees/`, a remote checkout, or any
|
|
23
|
+
If your current checkout is different, or appears to be under `.claude/worktrees/`, `.prizmkit/state/worktrees/`, a copied checkout, a remote isolated checkout, a temporary repository clone, or any branch/top-level other than the orchestrator-provided active checkout:
|
|
24
24
|
- Stop immediately.
|
|
25
25
|
- Do not review files.
|
|
26
26
|
- Do not produce normal findings.
|
|
27
27
|
- Report `WRONG_CHECKOUT` and state that `/prizmkit-code-review` cannot continue because the reviewer subagent was not started in the active checkout/no-worktree mode required by this skill.
|
|
28
28
|
|
|
29
|
-
Worktree review
|
|
29
|
+
Worktree, copied-checkout, remote-checkout, and branch-switched review are not supported by `/prizmkit-code-review`; do not continue even if the files appear similar. Do not request or create worktrees, copied repositories, branch switches, or remote checkouts.
|
|
30
30
|
|
|
31
31
|
## Dev Rules (per-layer conventions)
|
|
32
32
|
{rules from .prizmkit/rules/<layer>-rules.md, or "No custom dev rules configured — use general best practices."}
|
|
@@ -38,7 +38,7 @@ Round {N}. {round_context}
|
|
|
38
38
|
Use the orchestrator-provided workspace context as the source of truth for changed files:
|
|
39
39
|
- For new files listed in workspace status, read their full content.
|
|
40
40
|
- For modified files, read enough surrounding context to understand the change.
|
|
41
|
-
- Do not edit files, stage changes, run test suites,
|
|
41
|
+
- Do not edit files, stage changes, run test suites, spawn other agents, or invoke tools that modify the workspace.
|
|
42
42
|
- Do not request or create worktrees — you are reviewing the active checkout's changes. The orchestrator has already captured the full diff and status context; re-discovering the whole repository is wasteful and unnecessary.
|
|
43
43
|
|
|
44
44
|
## Review Dimensions
|
|
@@ -55,10 +55,10 @@ Evaluate the changes across these dimensions (focus on what's relevant):
|
|
|
55
55
|
## Output Format
|
|
56
56
|
Respond with EXACTLY this format:
|
|
57
57
|
|
|
58
|
-
### Result: PASS | NEEDS_FIXES
|
|
58
|
+
### Result: PASS | NEEDS_FIXES | WRONG_CHECKOUT
|
|
59
59
|
|
|
60
60
|
### Findings
|
|
61
|
-
(If PASS, write "No issues found.")
|
|
61
|
+
(If PASS, write "No issues found." If WRONG_CHECKOUT, include only checkout mismatch evidence and do not include normal review findings.)
|
|
62
62
|
|
|
63
63
|
#### Finding N
|
|
64
64
|
- **Severity**: high | medium | low
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "prizmkit-implement"
|
|
3
|
-
description: "Execute plan.md tasks with a TDD-oriented approach. Respects task ordering, checkpoints, and dependencies for Fast path or Full path change artifacts. Reads Prizm docs before editing;
|
|
3
|
+
description: "Execute plan.md tasks with a TDD-oriented approach. Respects task ordering, checkpoints, and dependencies for Fast path or Full path change artifacts. Reads Prizm docs before editing; optional inline implementation subagent delegation uses this skill's references and active-checkout/no-worktree constraints. Use after /prizmkit-plan. Trigger on: 'implement', 'build', 'code it', 'start coding', 'execute', 'write the code'. (project)"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PrizmKit Implement
|
|
@@ -39,6 +39,26 @@ Before implementation, load context once:
|
|
|
39
39
|
|
|
40
40
|
If a dev rule conflicts with `plan.md`, call out the conflict and ask the user unless the plan clearly supersedes the rule.
|
|
41
41
|
|
|
42
|
+
## Optional Inline Implementation Subagent Delegation
|
|
43
|
+
|
|
44
|
+
The default execution mode is direct Main Agent implementation. If delegation is useful for a narrow implementation slice, use only this skill's local reference:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
prompt_reference: ${SKILL_DIR}/references/implementation-subagent-procedure.md
|
|
48
|
+
isolation: current-workspace / active-checkout / no-worktree
|
|
49
|
+
subagent_kind: inline implementation prompt, not a platform-installed named agent
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Delegation rules:
|
|
53
|
+
- Read `${SKILL_DIR}/references/implementation-subagent-procedure.md` before preparing the subagent prompt.
|
|
54
|
+
- Pass the expected active checkout git top-level and the exact delegated task/file scope.
|
|
55
|
+
- Do not use worktree isolation, copied checkouts, remote isolated checkouts, branch switching, or a platform-installed named implementation agent.
|
|
56
|
+
- If active-checkout/no-worktree launch cannot be satisfied, stop with:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
Cannot delegate /prizmkit-implement because this platform cannot start an inline implementation subagent in the active checkout without worktree, copy, remote, or branch isolation.
|
|
60
|
+
```
|
|
61
|
+
|
|
42
62
|
## Execution
|
|
43
63
|
|
|
44
64
|
For each unchecked task in `plan.md`, in order:
|