prizmkit 1.1.104 → 1.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/README.md +6 -7
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +357 -158
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +98 -9
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +37 -28
- package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +4 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +62 -38
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +57 -49
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -1
- package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +2 -2
- package/bundled/dev-pipeline/templates/sections/directory-convention-full.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +1 -0
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +1 -0
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +46 -0
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +100 -0
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +0 -71
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
## PrizmKit Directory Convention
|
|
2
2
|
|
|
3
3
|
```
|
|
4
|
-
.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md ← orchestrator writes Sections 1-4
|
|
4
|
+
.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md ← orchestrator writes Sections 1-4 + Implementation Log; Reviewer appends Review Notes
|
|
5
5
|
.prizmkit/specs/{{FEATURE_SLUG}}/plan.md ← includes Tasks section
|
|
6
6
|
```
|
|
7
7
|
|
|
8
|
-
**`context-snapshot.md`** is the shared knowledge base. Orchestrator writes Sections 1-4
|
|
8
|
+
**`context-snapshot.md`** is the shared knowledge base. Orchestrator writes Sections 1-4 and the Implementation Log; Reviewer appends Review Notes. Append-only after initial creation.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
## PrizmKit Directory Convention
|
|
2
2
|
|
|
3
3
|
```
|
|
4
|
-
.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md ← orchestrator writes Sections 1-4
|
|
4
|
+
.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md ← orchestrator writes Sections 1-4 + Implementation Log; Reviewer appends Review Notes
|
|
5
5
|
.prizmkit/specs/{{FEATURE_SLUG}}/spec.md
|
|
6
6
|
.prizmkit/specs/{{FEATURE_SLUG}}/plan.md ← includes Tasks section
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
**`context-snapshot.md`** is the shared knowledge base. Orchestrator writes Sections 1-4
|
|
9
|
+
**`context-snapshot.md`** is the shared knowledge base. Orchestrator writes Sections 1-4 and the Implementation Log; Reviewer appends Review Notes. This eliminates redundant I/O across review and orchestration phases.
|
|
@@ -22,6 +22,7 @@ grep -c '^\- \[ \]' .prizmkit/specs/{{FEATURE_SLUG}}/plan.md 2>/dev/null || true
|
|
|
22
22
|
- Implements task-by-task, marking each `[x]` immediately
|
|
23
23
|
- Creates/updates L2 `.prizm` docs when creating new modules
|
|
24
24
|
- Defers scoped/full test execution until after the code-review loop completes
|
|
25
|
+
- Preserves Reviewer/Critic behavior; only the top-level implementation Dev handoff is removed
|
|
25
26
|
- If plan.md has >5 tasks: update checkpoints after every 3 tasks
|
|
26
27
|
|
|
27
28
|
**3c. Focused checks only (no test gate here)**:
|
|
@@ -23,6 +23,7 @@ Save pre-existing failing tests as `BASELINE_FAILURES`.
|
|
|
23
23
|
- Implements task-by-task, marking each `[x]` immediately
|
|
24
24
|
- Creates/updates L2 `.prizm` docs when creating new modules
|
|
25
25
|
- Defers scoped/full test execution until after the code-review loop completes
|
|
26
|
+
- Preserves Reviewer/Critic behavior; only the top-level implementation Dev handoff is removed
|
|
26
27
|
- If plan.md has >5 tasks: update checkpoints after every 3 tasks
|
|
27
28
|
|
|
28
29
|
**3c. Focused checks only (no test gate here)**:
|
|
@@ -8,6 +8,7 @@ from argparse import Namespace
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
10
|
from generate_bootstrap_prompt import (
|
|
11
|
+
ACTIVE_AGENT_PROMPTS,
|
|
11
12
|
compute_feature_slug,
|
|
12
13
|
find_feature,
|
|
13
14
|
format_acceptance_criteria,
|
|
@@ -21,6 +22,7 @@ from generate_bootstrap_prompt import (
|
|
|
21
22
|
build_replacements,
|
|
22
23
|
generate_checkpoint_definition,
|
|
23
24
|
merge_checkpoint_state,
|
|
25
|
+
load_active_agent_prompts,
|
|
24
26
|
load_log_size_section,
|
|
25
27
|
main as generate_bootstrap_main,
|
|
26
28
|
)
|
|
@@ -809,6 +811,50 @@ class TestHeadlessRecoveryReframing:
|
|
|
809
811
|
assert "run `/compact` after" not in rendered
|
|
810
812
|
|
|
811
813
|
|
|
814
|
+
class TestDirectOrchestratorImplementationPrompts:
|
|
815
|
+
def test_active_agent_prompt_loader_excludes_retired_dev_implement_prompt(self):
|
|
816
|
+
templates_dir = Path("dev-pipeline/templates").resolve()
|
|
817
|
+
|
|
818
|
+
replacements = load_active_agent_prompts(str(templates_dir))
|
|
819
|
+
|
|
820
|
+
assert "dev-implement.md" not in ACTIVE_AGENT_PROMPTS
|
|
821
|
+
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in replacements
|
|
822
|
+
assert "{{AGENT_PROMPT_CRITIC_PLAN_CHALLENGE}}" in replacements
|
|
823
|
+
assert (templates_dir / "agent-prompts" / "dev-implement.md").exists() is False
|
|
824
|
+
|
|
825
|
+
def test_sections_all_modes_use_direct_orchestrator_implementation(self):
|
|
826
|
+
sections_dir = Path("dev-pipeline/templates/sections").resolve()
|
|
827
|
+
|
|
828
|
+
for mode in ("lite", "standard", "full"):
|
|
829
|
+
rendered = "\n".join(
|
|
830
|
+
section for _name, section in assemble_sections(
|
|
831
|
+
mode, str(sections_dir), init_done=True, is_resume=False,
|
|
832
|
+
critic_enabled=(mode == "full"), browser_enabled=False,
|
|
833
|
+
)
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
assert "/prizmkit-implement" in rendered
|
|
837
|
+
assert "orchestrator) execute" in rendered or "Run `/prizmkit-implement`" in rendered
|
|
838
|
+
assert "Spawn Dev subagent" not in rendered
|
|
839
|
+
assert "Spawn Dev agent" not in rendered
|
|
840
|
+
assert "Implement — Dev" not in rendered
|
|
841
|
+
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in rendered
|
|
842
|
+
assert "dev-implement.md" not in rendered
|
|
843
|
+
assert "Reviewer Agent → filter → Dev Agent fix" in rendered
|
|
844
|
+
|
|
845
|
+
def test_legacy_tier_templates_use_direct_orchestrator_implementation(self):
|
|
846
|
+
for template_name in ("bootstrap-tier2.md", "bootstrap-tier3.md"):
|
|
847
|
+
rendered = (Path("dev-pipeline/templates") / template_name).read_text(encoding="utf-8")
|
|
848
|
+
|
|
849
|
+
assert "/prizmkit-implement" in rendered
|
|
850
|
+
assert "Implement — Orchestrator Direct" in rendered
|
|
851
|
+
assert "Spawn Dev subagent" not in rendered
|
|
852
|
+
assert "Spawn Dev agent" not in rendered
|
|
853
|
+
assert "Implement — Dev" not in rendered
|
|
854
|
+
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in rendered
|
|
855
|
+
assert "dev-implement.md" not in rendered
|
|
856
|
+
|
|
857
|
+
|
|
812
858
|
# ---------------------------------------------------------------------------
|
|
813
859
|
# continuation handoff
|
|
814
860
|
# ---------------------------------------------------------------------------
|
|
@@ -864,6 +864,98 @@ def test_default_no_worktree_preserves_main_worktree_branch_launch(monkeypatch,
|
|
|
864
864
|
assert "branch_merge" in plan_names
|
|
865
865
|
|
|
866
866
|
|
|
867
|
+
def test_no_worktree_runner_ignores_recovery_side_effect_branch(monkeypatch, tmp_path):
|
|
868
|
+
from prizmkit_runtime import runners
|
|
869
|
+
from prizmkit_runtime.runner_models import family_for, parse_invocation
|
|
870
|
+
|
|
871
|
+
monkeypatch.delenv("DEV_BRANCH", raising=False)
|
|
872
|
+
paths = _make_paths(tmp_path)
|
|
873
|
+
family = family_for("feature", paths)
|
|
874
|
+
invocation = parse_invocation(family, "run", ())
|
|
875
|
+
invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
|
|
876
|
+
observed = _install_runner_session_fakes(monkeypatch, runners)
|
|
877
|
+
branch_names = []
|
|
878
|
+
|
|
879
|
+
monkeypatch.setenv("DEV_BRANCH", "dev/F-001-recovery-20260707")
|
|
880
|
+
monkeypatch.setattr(runners, "current_branch", lambda _root: "dev/F-001-recovery-20260707")
|
|
881
|
+
|
|
882
|
+
def fake_run_git_plan(project_root, plan):
|
|
883
|
+
if plan.name == "branch_create":
|
|
884
|
+
branch_names.append(plan.commands[1].args[2])
|
|
885
|
+
return SimpleNamespace(ok=True, plan=plan, results=())
|
|
886
|
+
|
|
887
|
+
monkeypatch.setattr(runners, "run_git_plan", fake_run_git_plan)
|
|
888
|
+
|
|
889
|
+
status = runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
|
|
890
|
+
|
|
891
|
+
assert status == "completed"
|
|
892
|
+
assert branch_names and branch_names[0].startswith("dev/F-001-")
|
|
893
|
+
assert "recovery" not in branch_names[0]
|
|
894
|
+
assert observed.updates[-1][2]["active_dev_branch"] == branch_names[0]
|
|
895
|
+
assert observed.updates[-1][2]["base_branch"] == "main"
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
def test_foreground_runner_emits_structured_feature_progress(monkeypatch, tmp_path, capsys):
|
|
899
|
+
from prizmkit_runtime import runners
|
|
900
|
+
from prizmkit_runtime.runner_models import family_for, parse_invocation
|
|
901
|
+
|
|
902
|
+
monkeypatch.setenv("DEV_BRANCH", "dev/F-001-output")
|
|
903
|
+
paths = _make_paths(tmp_path)
|
|
904
|
+
family = family_for("feature", paths)
|
|
905
|
+
invocation = parse_invocation(family, "run", ())
|
|
906
|
+
invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
|
|
907
|
+
_install_runner_session_fakes(monkeypatch, runners)
|
|
908
|
+
monkeypatch.setattr(runners, "run_git_plan", lambda project_root, plan: SimpleNamespace(ok=True, plan=plan, results=()))
|
|
909
|
+
|
|
910
|
+
status = runners._process_item(
|
|
911
|
+
family,
|
|
912
|
+
invocation,
|
|
913
|
+
"F-001",
|
|
914
|
+
paths,
|
|
915
|
+
initial_metadata={"title": "Readable output", "retry_count": 1, "infra_error_count": 2},
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
captured = capsys.readouterr()
|
|
919
|
+
assert status == "completed"
|
|
920
|
+
assert "────────────────────────────────────────────────────" in captured.err
|
|
921
|
+
assert "Feature: F-001 — Readable output" in captured.err
|
|
922
|
+
assert "Code retry: 1 / 3" in captured.err
|
|
923
|
+
assert "Infrastructure retry: 2 / 3" in captured.err
|
|
924
|
+
assert "Pipeline mode: lite (Tier 1 — Single Agent)" in captured.err
|
|
925
|
+
assert "Agents: 1 (critic: disabled)" in captured.err
|
|
926
|
+
assert "Spawning AI CLI session: F-001-session-1" in captured.err
|
|
927
|
+
assert "Session result: success" in captured.err
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
def test_no_worktree_interrupt_saves_wip_and_returns_to_base(monkeypatch, tmp_path):
|
|
931
|
+
from prizmkit_runtime import runners
|
|
932
|
+
from prizmkit_runtime.runner_models import family_for, parse_invocation
|
|
933
|
+
|
|
934
|
+
monkeypatch.setenv("DEV_BRANCH", "dev/F-001-interrupt")
|
|
935
|
+
paths = _make_paths(tmp_path)
|
|
936
|
+
family = family_for("feature", paths)
|
|
937
|
+
invocation = parse_invocation(family, "run", ())
|
|
938
|
+
invocation = invocation.__class__(**{**invocation.__dict__, "list_path": paths.feature_plan})
|
|
939
|
+
_install_runner_session_fakes(monkeypatch, runners)
|
|
940
|
+
ensure_calls = []
|
|
941
|
+
monkeypatch.setattr(runners, "run_git_plan", lambda project_root, plan: SimpleNamespace(ok=True, plan=plan, results=()))
|
|
942
|
+
monkeypatch.setattr(runners, "branch_ensure_return", lambda project_root, base, branch: ensure_calls.append((base, branch)))
|
|
943
|
+
|
|
944
|
+
class InterruptingLauncher:
|
|
945
|
+
def __init__(self, config):
|
|
946
|
+
self.config = config
|
|
947
|
+
|
|
948
|
+
def run(self):
|
|
949
|
+
raise KeyboardInterrupt
|
|
950
|
+
|
|
951
|
+
monkeypatch.setattr(runners, "AISessionLauncher", InterruptingLauncher)
|
|
952
|
+
|
|
953
|
+
with pytest.raises(KeyboardInterrupt):
|
|
954
|
+
runners._process_item(family, invocation, "F-001", paths, initial_metadata={})
|
|
955
|
+
|
|
956
|
+
assert ensure_calls == [("main", "dev/F-001-interrupt")]
|
|
957
|
+
|
|
958
|
+
|
|
867
959
|
def test_context_overflow_reuses_worktree_and_skips_cleanup_until_terminal_outcome(monkeypatch, tmp_path):
|
|
868
960
|
from prizmkit_runtime import runners
|
|
869
961
|
from prizmkit_runtime.runner_models import family_for, parse_invocation
|
|
@@ -964,6 +1056,14 @@ def test_classification_stalls_after_repeated_no_progress_context_overflow(tmp_p
|
|
|
964
1056
|
assert classification.no_progress_count == 2
|
|
965
1057
|
|
|
966
1058
|
|
|
1059
|
+
def test_recovery_prompt_keeps_existing_branch_instead_of_recovery_suffix():
|
|
1060
|
+
text = (PIPELINE_ROOT / "scripts" / "generate-recovery-prompt.py").read_text(encoding="utf-8")
|
|
1061
|
+
|
|
1062
|
+
assert "fix/{bug_id}-recovery" not in text
|
|
1063
|
+
assert "do not create an additional" in text
|
|
1064
|
+
assert "last-resort fallback" in text
|
|
1065
|
+
|
|
1066
|
+
|
|
967
1067
|
def test_recovery_detector_resolver_prefers_installed_platform_asset(tmp_path):
|
|
968
1068
|
from prizmkit_runtime.paths import resolve_runtime_paths
|
|
969
1069
|
from prizmkit_runtime.runner_recovery import RecoveryDetectorResolver
|
package/package.json
CHANGED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"<!-- DEPRECATED (P0-6): This prompt was injected into a Dev subagent spawn.
|
|
2
|
-
The orchestrator now implements directly (see phase-implement-agent.md / phase-implement-full.md).
|
|
3
|
-
This file is retained only so load_agent_prompts() does not break; it is no longer referenced
|
|
4
|
-
by any phase section. Do not add new rules here — add them to the phase-implement-* sections instead.
|
|
5
|
-
The rules below are the legacy Dev-subagent version, kept for reference only. -->
|
|
6
|
-
|
|
7
|
-
Read {{DEV_SUBAGENT_PATH}}. Implement feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
|
|
8
|
-
|
|
9
|
-
## Task Summary Card
|
|
10
|
-
|
|
11
|
-
**Objective**: Implement {{FEATURE_TITLE}}.
|
|
12
|
-
|
|
13
|
-
**Primary files** (see context-snapshot.md Section 4 for full manifest):
|
|
14
|
-
- Review plan.md Tasks section for the complete task-to-file mapping.
|
|
15
|
-
- Each task's `— file:` suffix identifies the target file.
|
|
16
|
-
|
|
17
|
-
**Test command**: `{{TEST_CMD}}`
|
|
18
|
-
|
|
19
|
-
**Known baseline failures**: `{{BASELINE_FAILURES}}`
|
|
20
|
-
|
|
21
|
-
**DO NOT**:
|
|
22
|
-
- Re-read source files already listed in context-snapshot.md Section 4 File Manifest
|
|
23
|
-
- Create new files unless a plan.md task explicitly requires it
|
|
24
|
-
- Run git commands
|
|
25
|
-
- Use mock success data or fake rows in UI/tests
|
|
26
|
-
|
|
27
|
-
## Required Inputs
|
|
28
|
-
|
|
29
|
-
1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` first.
|
|
30
|
-
2. Use Section 4 File Manifest for targeted reads.
|
|
31
|
-
3. Do not expand scope beyond the Task Contract and Verification Gates.
|
|
32
|
-
4. Do not re-read source files already listed in Section 4 unless implementation details are missing from the manifest.
|
|
33
|
-
|
|
34
|
-
## Work
|
|
35
|
-
|
|
36
|
-
Run `/prizmkit-implement` to execute `plan.md`.
|
|
37
|
-
|
|
38
|
-
Test command:
|
|
39
|
-
`{{TEST_CMD}}`
|
|
40
|
-
|
|
41
|
-
Known baseline failures:
|
|
42
|
-
`{{BASELINE_FAILURES}}`
|
|
43
|
-
|
|
44
|
-
If plan.md has more than 5 tasks, update durable checkpoints/artifacts after every 3 tasks, minimize output, and rely on runner continuation if context overflow occurs. In an interactive Claude Code session operated manually outside the headless pipeline, `/compact` may be used as an optional convenience only.
|
|
45
|
-
|
|
46
|
-
## Required Outputs
|
|
47
|
-
|
|
48
|
-
Before returning, append `## Implementation Log` to `context-snapshot.md` with:
|
|
49
|
-
- files changed/created
|
|
50
|
-
- key decisions
|
|
51
|
-
- deviations from plan
|
|
52
|
-
- test results
|
|
53
|
-
- Verification Gate status
|
|
54
|
-
- unresolved blockers, if any
|
|
55
|
-
|
|
56
|
-
## Protocol References
|
|
57
|
-
|
|
58
|
-
- Follow the global Context Budget Rules.
|
|
59
|
-
- Carry forward the Dev-isolated subset: skip scaffold/generated files listed in `context-snapshot.md`; verify dependency versions before install/build commands that resolve dependencies; after build/compile commands, ensure outputs are ignored and never commit generated artifacts.
|
|
60
|
-
- If tests fail, follow this Test Failure Recovery subset: classify failures as baseline, new regression, brittle test, or environment/tooling; fix new regressions and brittle tests while progress is being made; document baseline failures; write `failure-log.md` for blockers.
|
|
61
|
-
- Do not run git commands; staging and commit are handled by the orchestrator.
|
|
62
|
-
- **Edit safety**: If an Edit fails with 'String to replace not found', grep for the target text before retrying. Never guess file offsets — verify them with a Read or grep first.
|
|
63
|
-
- **Read safety**: If 3 consecutive Reads to the same file return 'shorter than offset' or 'Wasted call', STOP and report BLOCKED.
|
|
64
|
-
- **Test gate placement**: Do not run mandatory periodic or full-suite tests here. The scoped/full test gate runs after code review; only use tiny targeted checks when needed for local debugging.
|
|
65
|
-
|
|
66
|
-
Do not return success unless:
|
|
67
|
-
1. implementation tasks are complete;
|
|
68
|
-
2. `## Implementation Log` exists;
|
|
69
|
-
3. every Verification Gate is verified.
|
|
70
|
-
|
|
71
|
-
If any Verification Gate is blocked, write `failure-log.md` and return a blocked/incomplete result instead of success."
|