prizmkit 1.1.106 → 1.1.108
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 +4 -0
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +81 -14
- package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +19 -8
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +0 -1
- package/bundled/dev-pipeline/prizmkit_runtime/launch_profiles.py +18 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +22 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +56 -5
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -8
- package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +11 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +298 -63
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +243 -37
- package/bundled/dev-pipeline/scripts/continuation.py +0 -5
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +10 -82
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +7 -64
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +40 -63
- package/bundled/dev-pipeline/scripts/utils.py +123 -0
- package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +4 -3
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +5 -6
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +36 -35
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +53 -80
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +43 -78
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +5 -17
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +6 -18
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +14 -48
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +7 -14
- package/bundled/dev-pipeline/templates/sections/feature-context.md +0 -4
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +0 -14
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -14
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-base.md +0 -2
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +6 -8
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +3 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +4 -16
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +4 -17
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +2 -9
- package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +1 -8
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +15 -16
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +3 -10
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +3 -10
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +2 -9
- package/bundled/dev-pipeline/templates/sections/phase0-init.md +0 -7
- package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +2 -15
- package/bundled/dev-pipeline/tests/conftest.py +0 -1
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +395 -21
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +50 -14
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +154 -2
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +431 -3
- package/bundled/dev-pipeline/tests/test_unified_cli.py +857 -5
- package/bundled/skills/_metadata.json +4 -4
- package/bundled/skills/app-planner/SKILL.md +1 -1
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -1
- package/bundled/skills/bug-fix-workflow/SKILL.md +174 -128
- package/bundled/skills/bug-planner/SKILL.md +101 -15
- package/bundled/skills/bug-planner/references/severity-rules.md +20 -8
- package/bundled/skills/feature-planner/SKILL.md +87 -8
- package/bundled/skills/feature-planner/assets/planning-guide.md +34 -10
- package/bundled/skills/feature-workflow/SKILL.md +100 -81
- package/bundled/skills/{prizm-kit → prizmkit}/SKILL.md +1 -1
- package/bundled/skills/prizmkit-code-review/SKILL.md +12 -13
- package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +10 -10
- package/bundled/skills/refactor-planner/SKILL.md +88 -7
- package/bundled/skills/refactor-planner/references/fast-path.md +2 -1
- package/bundled/skills/refactor-planner/references/planning-phases.md +29 -11
- package/bundled/skills/refactor-workflow/SKILL.md +116 -57
- package/bundled/templates/project-memory-template.md +1 -1
- package/package.json +1 -1
- package/src/ai-cli-launch.js +194 -0
- package/src/config.js +26 -14
- package/src/index.js +11 -44
- package/src/platforms.js +10 -3
- package/src/prompts.js +60 -2
- package/src/scaffold.js +26 -14
- package/bundled/dev-pipeline/scripts/prizmkit-test-gate.py +0 -446
- package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +0 -7
- package/bundled/dev-pipeline/templates/agent-prompts/dev-resume.md +0 -5
- package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +0 -20
- package/bundled/dev-pipeline/tests/test_prizmkit_test_gate.py +0 -107
- package/bundled/skills/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
|
@@ -4,7 +4,7 @@ Review the completed implementation before the scoped feature test gate runs. Us
|
|
|
4
4
|
|
|
5
5
|
Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
6
6
|
|
|
7
|
-
The skill runs an internal review-fix loop (Reviewer Agent → filter →
|
|
7
|
+
The skill runs an internal review-fix loop (Reviewer Agent → filter → orchestrator fix, max 3 rounds) and writes `review-report.md` to the artifact directory.
|
|
8
8
|
|
|
9
9
|
**Gate Check — Review Report**:
|
|
10
10
|
After `/prizmkit-code-review` returns, verify the review report:
|
|
@@ -13,8 +13,8 @@ grep -q "## Verdict" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "
|
|
|
13
13
|
```
|
|
14
14
|
If GATE:MISSING:
|
|
15
15
|
- Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
|
|
16
|
-
- Perform one bounded status check; retry at most once: inspect the skill output, `review-report.md` path, and any Reviewer
|
|
17
|
-
- If the missing report is caused by team/config/lock errors from the
|
|
16
|
+
- Perform one bounded status check; retry at most once: inspect the skill output, `review-report.md` path, and any Reviewer agent spawn messages.
|
|
17
|
+
- If the missing report is caused by team/config/lock errors from the Reviewer agent spawn or review skill error, retry `/prizmkit-code-review` at most once only if it appears transient.
|
|
18
18
|
- If the report is still missing after that single check/retry, write `failure-log.md` with the spawn/skill error and last observable state, then either perform a safe inline fallback review (spec/plan/diff/tests → write `review-report.md` with `## Verdict`) or stop with a clear recovery failure.
|
|
19
19
|
|
|
20
20
|
Read `review-report.md` and check the Verdict:
|
|
@@ -24,10 +24,3 @@ Read `review-report.md` and check the Verdict:
|
|
|
24
24
|
**CP-3**: Review complete, report written.
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
**Checkpoint update**: Run the update script to set step `prizmkit-code-review` to `"completed"`:
|
|
28
|
-
```bash
|
|
29
|
-
python3 $PIPELINE_DIR/scripts/update-checkpoint.py \
|
|
30
|
-
--checkpoint-path {{CHECKPOINT_PATH}} \
|
|
31
|
-
--step prizmkit-code-review \
|
|
32
|
-
--status completed
|
|
33
|
-
```
|
|
@@ -45,7 +45,7 @@ ls .prizmkit/specs/{{FEATURE_SLUG}}/ 2>/dev/null
|
|
|
45
45
|
ls .prizmkit/specs/{{FEATURE_SLUG}}/spec.md .prizmkit/specs/{{FEATURE_SLUG}}/plan.md 2>/dev/null
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
- spec.md missing: Run `/prizmkit-plan` → generate spec.md. Resolve
|
|
48
|
+
- spec.md missing: Run `/prizmkit-plan` → generate spec.md. Resolve uncertain requirements from the task description, existing code, and conservative existing-project patterns.
|
|
49
49
|
- plan.md missing: Run `/prizmkit-plan` → generate plan.md (change approach, components, interface design, data model, testing strategy, risk assessment, and Tasks section with `[ ]` checkboxes)
|
|
50
50
|
|
|
51
51
|
> All files go under `.prizmkit/specs/{{FEATURE_SLUG}}/`. Confirm each with `ls` after writing.
|
|
@@ -54,16 +54,9 @@ ls .prizmkit/specs/{{FEATURE_SLUG}}/spec.md .prizmkit/specs/{{FEATURE_SLUG}}/pla
|
|
|
54
54
|
Before proceeding past CP-1, verify:
|
|
55
55
|
1. Plan.md Data Model section references existing schema/model files (scan for `*.prisma`, `*.sql`, `migrations/`, `models/`, `*.entity.*` files; read them if not already in context-snapshot)
|
|
56
56
|
2. All new tables/fields follow existing naming conventions, ID strategy, timestamp patterns, and constraint style
|
|
57
|
-
3. No
|
|
57
|
+
3. No unresolved data model uncertainty remains in the Data Model section — resolve by reading existing code and making a conservative choice that matches existing patterns. Document the resolution in plan.md.
|
|
58
58
|
4. If a DB design decision genuinely cannot be resolved from existing code alone, document the assumption made and flag it in the Implementation Log for user review.
|
|
59
59
|
|
|
60
60
|
**CP-1**: Both spec.md and plan.md exist.
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
**Checkpoint update**: Run the update script to set step `context-snapshot-and-plan` to `"completed"`:
|
|
64
|
-
```bash
|
|
65
|
-
python3 $PIPELINE_DIR/scripts/update-checkpoint.py \
|
|
66
|
-
--checkpoint-path {{CHECKPOINT_PATH}} \
|
|
67
|
-
--step context-snapshot-and-plan \
|
|
68
|
-
--status completed
|
|
69
|
-
```
|
|
@@ -4,10 +4,3 @@
|
|
|
4
4
|
- **CP-0**: Verify `.prizmkit/prizm-docs/root.prizm`, `.prizmkit/config.json` exist
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
**Checkpoint update**: Run the update script to set step `prizmkit-init` to `"completed"`:
|
|
8
|
-
```bash
|
|
9
|
-
python3 $PIPELINE_DIR/scripts/update-checkpoint.py \
|
|
10
|
-
--checkpoint-path {{CHECKPOINT_PATH}} \
|
|
11
|
-
--step prizmkit-init \
|
|
12
|
-
--status completed
|
|
13
|
-
```
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
### Phase 0:
|
|
1
|
+
### Phase 0: Project Already Initialized
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
**Step 2 — Do not run tests yet**: This phase only records the commands that will be used by the post-review PrizmKit Test gate. Do not run baseline, periodic, or full-suite tests here; test execution happens after code review.
|
|
6
|
-
|
|
7
|
-
> **Test Output Rule**: When the post-review gate runs, capture test output to a temp file (`tee /tmp/test-out.txt`). Then grep the file instead of re-running the suite.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**Checkpoint update**: Run the update script to set step `test-baseline` to `"completed"`:
|
|
11
|
-
```bash
|
|
12
|
-
python3 $PIPELINE_DIR/scripts/update-checkpoint.py \
|
|
13
|
-
--checkpoint-path {{CHECKPOINT_PATH}} \
|
|
14
|
-
--step test-baseline \
|
|
15
|
-
--status completed
|
|
16
|
-
```
|
|
3
|
+
The project is already initialized. Proceed to context loading and planning. Test execution belongs to the post-review `/prizmkit-test` gate.
|
|
@@ -25,5 +25,4 @@ def _load_hyphenated_module(module_name, filename):
|
|
|
25
25
|
_load_hyphenated_module("generate_bootstrap_prompt", "generate-bootstrap-prompt.py")
|
|
26
26
|
_load_hyphenated_module("generate_bugfix_prompt", "generate-bugfix-prompt.py")
|
|
27
27
|
_load_hyphenated_module("generate_refactor_prompt", "generate-refactor-prompt.py")
|
|
28
|
-
_load_hyphenated_module("prizmkit_test_gate", "prizmkit-test-gate.py")
|
|
29
28
|
_load_hyphenated_module("update_feature_status", "update-feature-status.py")
|
|
@@ -23,10 +23,24 @@ from generate_bootstrap_prompt import (
|
|
|
23
23
|
generate_checkpoint_definition,
|
|
24
24
|
merge_checkpoint_state,
|
|
25
25
|
load_active_agent_prompts,
|
|
26
|
-
load_log_size_section,
|
|
27
26
|
main as generate_bootstrap_main,
|
|
28
27
|
)
|
|
29
28
|
from continuation import append_continuation_handoff, checkpoint_cursor
|
|
29
|
+
from utils import resolve_prompt_platform
|
|
30
|
+
|
|
31
|
+
REMOVED_MAX_LOG_ENV = "MAX_" + "LOG_SIZE"
|
|
32
|
+
REMOVED_MAX_LOG_HUMAN = REMOVED_MAX_LOG_ENV + "_HUMAN"
|
|
33
|
+
|
|
34
|
+
FORBIDDEN_DEV_FIX_PROMPT = "dev-" + "fix.md"
|
|
35
|
+
FORBIDDEN_DEV_RESUME_PROMPT = "dev-" + "resume.md"
|
|
36
|
+
FORBIDDEN_DEV_FIX_PLACEHOLDER = "{{AGENT_PROMPT_DEV_" + "FIX}}"
|
|
37
|
+
FORBIDDEN_DEV_RESUME_PLACEHOLDER = "{{AGENT_PROMPT_DEV_" + "RESUME}}"
|
|
38
|
+
FORBIDDEN_REVIEW_DEV_FIX = "Reviewer Agent → filter → " + "Dev Agent fix"
|
|
39
|
+
FORBIDDEN_REVIEWER_DEV_SPAWN = "Reviewer/" + "Dev agent spawn"
|
|
40
|
+
FORBIDDEN_EXPLORE_SUBAGENT = "subagent_type: " + "Explore"
|
|
41
|
+
FORBIDDEN_TEST_CMD_PLACEHOLDER = "(" + "$TEST_CMD" + ")"
|
|
42
|
+
FORBIDDEN_THREE_STRIKE = "3-" + "strike"
|
|
43
|
+
FORBIDDEN_TWENTY_STEP = "20-" + "step window"
|
|
30
44
|
|
|
31
45
|
|
|
32
46
|
def scoped_report_text(verdict="PASS", boundary_missing=0,
|
|
@@ -222,6 +236,11 @@ class TestExplicitProjectRoot:
|
|
|
222
236
|
assert not replacements["{{SESSION_STATUS_PATH}}"].startswith(str(execution_root.resolve()))
|
|
223
237
|
assert replacements["{{PROJECT_BRIEF}}"] == "worktree brief"
|
|
224
238
|
assert replacements["{{DEV_SUBAGENT_PATH}}"].startswith(str(execution_root.resolve()))
|
|
239
|
+
assert replacements["{{SESSION_LOG_PATH}}"].endswith(
|
|
240
|
+
".prizmkit/state/features/F-001/sessions/session-1/logs/session.log"
|
|
241
|
+
)
|
|
242
|
+
assert "{{" + REMOVED_MAX_LOG_ENV + "}}" not in replacements
|
|
243
|
+
assert "{{" + REMOVED_MAX_LOG_HUMAN + "}}" not in replacements
|
|
225
244
|
|
|
226
245
|
|
|
227
246
|
def test_main_writes_checkpoint_under_cli_project_root_and_status_under_state_dir(self, tmp_path, monkeypatch):
|
|
@@ -424,9 +443,14 @@ class TestScopedFeatureTestGate:
|
|
|
424
443
|
assert names.index("phase-implement") < names.index("phase-review") < names.index("phase-prizmkit-test")
|
|
425
444
|
|
|
426
445
|
rendered = "\n".join(content for _, content in sections)
|
|
427
|
-
assert "prizmkit-test-gate.py" in rendered
|
|
428
|
-
assert "prizmkit-test-
|
|
429
|
-
assert "
|
|
446
|
+
assert "prizmkit-test-gate.py" not in rendered
|
|
447
|
+
assert ".prizmkit-test-started" in rendered
|
|
448
|
+
assert "when present" not in rendered
|
|
449
|
+
assert "Boundary Matrix" in rendered
|
|
450
|
+
assert "Boundary Completion Gate" in rendered
|
|
451
|
+
assert "Boundary-missing: 0" in rendered
|
|
452
|
+
assert "Happy-path-only: 0" in rendered
|
|
453
|
+
assert "Validator result: passed" in rendered
|
|
430
454
|
assert "/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/" in rendered
|
|
431
455
|
assert ".prizmkit/bugfix/" in rendered # explicitly forbidden in the gate wording
|
|
432
456
|
assert ".prizmkit/refactor/" in rendered # explicitly forbidden in the gate wording
|
|
@@ -437,6 +461,25 @@ class TestScopedFeatureTestGate:
|
|
|
437
461
|
assert "before code review" not in rendered
|
|
438
462
|
assert "Precondition: the `prizmkit-test` checkpoint is completed" not in rendered
|
|
439
463
|
|
|
464
|
+
def test_standard_sections_include_central_checkpoint_helper(self):
|
|
465
|
+
sections_dir = Path(__file__).resolve().parents[1] / "templates" / "sections"
|
|
466
|
+
sections = assemble_sections(
|
|
467
|
+
"standard",
|
|
468
|
+
str(sections_dir),
|
|
469
|
+
init_done=True,
|
|
470
|
+
is_resume=False,
|
|
471
|
+
critic_enabled=False,
|
|
472
|
+
browser_enabled=False,
|
|
473
|
+
)
|
|
474
|
+
rendered = "\n".join(content for _, content in sections)
|
|
475
|
+
|
|
476
|
+
assert "### Checkpoint Update Helper" in rendered
|
|
477
|
+
assert "python3 .prizmkit/dev-pipeline/scripts/update-checkpoint.py" in rendered
|
|
478
|
+
assert "--checkpoint-path {{CHECKPOINT_PATH}}" in rendered
|
|
479
|
+
assert "--step <step-id-or-skill-name>" in rendered
|
|
480
|
+
assert "Do not hand-edit `workflow-checkpoint.json` directly." in rendered
|
|
481
|
+
assert "pipeline progress mechanism" not in rendered
|
|
482
|
+
|
|
440
483
|
def test_lite_sections_include_review_before_prizmkit_test_and_commit(self):
|
|
441
484
|
sections_dir = Path(__file__).resolve().parents[1] / "templates" / "sections"
|
|
442
485
|
sections = assemble_sections(
|
|
@@ -776,22 +819,32 @@ class TestScopedFeatureTestGate:
|
|
|
776
819
|
# ---------------------------------------------------------------------------
|
|
777
820
|
|
|
778
821
|
class TestHeadlessRecoveryReframing:
|
|
779
|
-
def
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
822
|
+
def test_active_prompt_sources_do_not_reference_deleted_log_size_section(self):
|
|
823
|
+
deleted_section = "log-size-" + "awareness.md"
|
|
824
|
+
loader = "load_" + "log_size_section"
|
|
825
|
+
placeholder = "{{LOG_" + "SIZE_AWARENESS}}"
|
|
826
|
+
deleted_title = "Session " + "Checkpoint Awareness"
|
|
827
|
+
active_paths = [
|
|
828
|
+
Path("dev-pipeline/scripts/generate-bootstrap-prompt.py"),
|
|
829
|
+
Path("dev-pipeline/scripts/generate-bugfix-prompt.py"),
|
|
830
|
+
Path("dev-pipeline/scripts/generate-refactor-prompt.py"),
|
|
831
|
+
Path("dev-pipeline/templates/bootstrap-tier1.md"),
|
|
832
|
+
Path("dev-pipeline/templates/bootstrap-tier2.md"),
|
|
833
|
+
Path("dev-pipeline/templates/bootstrap-tier3.md"),
|
|
834
|
+
Path("dev-pipeline/templates/bugfix-bootstrap-prompt.md"),
|
|
835
|
+
Path("dev-pipeline/templates/refactor-bootstrap-prompt.md"),
|
|
836
|
+
]
|
|
837
|
+
|
|
838
|
+
assert (Path("dev-pipeline/templates/sections") / deleted_section).exists() is False
|
|
839
|
+
for path in active_paths:
|
|
840
|
+
content = path.read_text(encoding="utf-8")
|
|
841
|
+
for forbidden in (deleted_section, loader, placeholder, deleted_title):
|
|
842
|
+
assert forbidden not in content
|
|
792
843
|
|
|
793
844
|
def test_assembled_prompts_do_not_spawn_log_monitor_or_require_compact(self):
|
|
794
845
|
sections_dir = Path("dev-pipeline/templates/sections").resolve()
|
|
846
|
+
deleted_title = "Session " + "Checkpoint Awareness"
|
|
847
|
+
placeholder = "{{LOG_" + "SIZE_AWARENESS}}"
|
|
795
848
|
|
|
796
849
|
for mode in ("lite", "standard", "full"):
|
|
797
850
|
rendered = "\n".join(
|
|
@@ -800,8 +853,12 @@ class TestHeadlessRecoveryReframing:
|
|
|
800
853
|
critic_enabled=False, browser_enabled=False,
|
|
801
854
|
)
|
|
802
855
|
)
|
|
803
|
-
assert
|
|
804
|
-
assert
|
|
856
|
+
assert deleted_title not in rendered
|
|
857
|
+
assert placeholder not in rendered
|
|
858
|
+
assert REMOVED_MAX_LOG_ENV not in rendered
|
|
859
|
+
assert REMOVED_MAX_LOG_HUMAN not in rendered
|
|
860
|
+
assert ("209" + "7152") not in rendered
|
|
861
|
+
assert ("2" + "MB") not in rendered
|
|
805
862
|
assert "monitor-log" not in rendered
|
|
806
863
|
assert "COMPACT_NEEDED" not in rendered
|
|
807
864
|
assert "log-size monitor" not in rendered
|
|
@@ -818,9 +875,16 @@ class TestDirectOrchestratorImplementationPrompts:
|
|
|
818
875
|
replacements = load_active_agent_prompts(str(templates_dir))
|
|
819
876
|
|
|
820
877
|
assert "dev-implement.md" not in ACTIVE_AGENT_PROMPTS
|
|
878
|
+
assert FORBIDDEN_DEV_FIX_PROMPT not in ACTIVE_AGENT_PROMPTS
|
|
879
|
+
assert FORBIDDEN_DEV_RESUME_PROMPT not in ACTIVE_AGENT_PROMPTS
|
|
821
880
|
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in replacements
|
|
881
|
+
assert FORBIDDEN_DEV_FIX_PLACEHOLDER not in replacements
|
|
882
|
+
assert FORBIDDEN_DEV_RESUME_PLACEHOLDER not in replacements
|
|
822
883
|
assert "{{AGENT_PROMPT_CRITIC_PLAN_CHALLENGE}}" in replacements
|
|
884
|
+
assert "{{AGENT_PROMPT_REVIEWER_REVIEW}}" in replacements
|
|
823
885
|
assert (templates_dir / "agent-prompts" / "dev-implement.md").exists() is False
|
|
886
|
+
assert (templates_dir / "agent-prompts" / FORBIDDEN_DEV_FIX_PROMPT).exists() is False
|
|
887
|
+
assert (templates_dir / "agent-prompts" / FORBIDDEN_DEV_RESUME_PROMPT).exists() is False
|
|
824
888
|
|
|
825
889
|
def test_sections_all_modes_use_direct_orchestrator_implementation(self):
|
|
826
890
|
sections_dir = Path("dev-pipeline/templates/sections").resolve()
|
|
@@ -840,7 +904,13 @@ class TestDirectOrchestratorImplementationPrompts:
|
|
|
840
904
|
assert "Implement — Dev" not in rendered
|
|
841
905
|
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in rendered
|
|
842
906
|
assert "dev-implement.md" not in rendered
|
|
843
|
-
assert
|
|
907
|
+
assert FORBIDDEN_REVIEW_DEV_FIX not in rendered
|
|
908
|
+
assert FORBIDDEN_REVIEWER_DEV_SPAWN not in rendered
|
|
909
|
+
assert FORBIDDEN_EXPLORE_SUBAGENT not in rendered
|
|
910
|
+
assert FORBIDDEN_TEST_CMD_PLACEHOLDER not in rendered
|
|
911
|
+
assert FORBIDDEN_THREE_STRIKE not in rendered
|
|
912
|
+
assert FORBIDDEN_TWENTY_STEP not in rendered
|
|
913
|
+
assert "Reviewer Agent → filter → orchestrator fix" in rendered
|
|
844
914
|
|
|
845
915
|
def test_legacy_tier_templates_use_direct_orchestrator_implementation(self):
|
|
846
916
|
for template_name in ("bootstrap-tier2.md", "bootstrap-tier3.md"):
|
|
@@ -853,6 +923,12 @@ class TestDirectOrchestratorImplementationPrompts:
|
|
|
853
923
|
assert "Implement — Dev" not in rendered
|
|
854
924
|
assert "{{AGENT_PROMPT_DEV_IMPLEMENT}}" not in rendered
|
|
855
925
|
assert "dev-implement.md" not in rendered
|
|
926
|
+
assert FORBIDDEN_REVIEW_DEV_FIX not in rendered
|
|
927
|
+
assert FORBIDDEN_REVIEWER_DEV_SPAWN not in rendered
|
|
928
|
+
assert FORBIDDEN_EXPLORE_SUBAGENT not in rendered
|
|
929
|
+
assert FORBIDDEN_TEST_CMD_PLACEHOLDER not in rendered
|
|
930
|
+
assert FORBIDDEN_THREE_STRIKE not in rendered
|
|
931
|
+
assert FORBIDDEN_TWENTY_STEP not in rendered
|
|
856
932
|
|
|
857
933
|
|
|
858
934
|
# ---------------------------------------------------------------------------
|
|
@@ -893,11 +969,13 @@ class TestContinuationHandoff:
|
|
|
893
969
|
assert "Treat completed/skipped checkpoint steps as already done." in rendered
|
|
894
970
|
assert "Do not read the previous full `session.log` unless explicitly necessary." in rendered
|
|
895
971
|
assert "prefer synthesized artifacts and summaries over logs" in rendered
|
|
896
|
-
assert "Do not attempt `/compact` as the recovery mechanism." in rendered
|
|
972
|
+
assert "Do not attempt `/compact` as the recovery mechanism." not in rendered
|
|
897
973
|
assert ".prizmkit/specs/123-continuation/workflow-checkpoint.json" in rendered
|
|
898
974
|
assert ".prizmkit/state/features/F-123/sessions/F-123-new/logs/session.log" in rendered
|
|
899
975
|
assert ".prizmkit/state/features/F-123/sessions/F-123-new/logs/progress.json" in rendered
|
|
900
976
|
assert ".prizmkit/state/features/F-123/sessions/F-123-new/logs/ai.pid" in rendered
|
|
977
|
+
assert ("Log " + "monitor") not in rendered
|
|
978
|
+
assert ("log-" + "monitor") not in rendered
|
|
901
979
|
|
|
902
980
|
summary = tmp_path / ".prizmkit/specs/123-continuation/continuation-summary.md"
|
|
903
981
|
assert summary.exists()
|
|
@@ -913,3 +991,299 @@ class TestContinuationHandoff:
|
|
|
913
991
|
{"id": "S03", "skill": "later", "status": "pending"},
|
|
914
992
|
]}
|
|
915
993
|
assert checkpoint_cursor(checkpoint)["first_cursor"] == "S02 (active)"
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
# ---------------------------------------------------------------------------
|
|
997
|
+
# F-033 headless prompt cleanup and platform-aware critic paths
|
|
998
|
+
# ---------------------------------------------------------------------------
|
|
999
|
+
|
|
1000
|
+
HEADLESS_FORBIDDEN_PROMPT_STRINGS = [
|
|
1001
|
+
"### Interactive Claude Code Note",
|
|
1002
|
+
"### Project Conventions",
|
|
1003
|
+
"Read CLAUDE.md for project-level coding standards and architecture decisions.",
|
|
1004
|
+
"Scaffold / generated file awareness",
|
|
1005
|
+
"### Resume Behavior",
|
|
1006
|
+
"[NEEDS CLARIFICATION]",
|
|
1007
|
+
"pause for interactive input",
|
|
1008
|
+
"prizmkit-test-gate.py",
|
|
1009
|
+
"### Phase 0: Detect Test Commands",
|
|
1010
|
+
"TEST_CMDS",
|
|
1011
|
+
]
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
def _write_feature_list(path, feature):
|
|
1015
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
1016
|
+
path.write_text(json.dumps({"features": [feature], "global_context": {"language": "Python"}}), encoding="utf-8")
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
def _render_feature_prompt(tmp_path, mode="standard", critic=False, template=None, platform="claude"):
|
|
1020
|
+
project = tmp_path / "project"
|
|
1021
|
+
project.mkdir(parents=True)
|
|
1022
|
+
(project / ".prizmkit" / "plans").mkdir(parents=True)
|
|
1023
|
+
(project / ".prizmkit" / "config.json").write_text(
|
|
1024
|
+
json.dumps({"platform": platform, "ai_cli": platform}), encoding="utf-8"
|
|
1025
|
+
)
|
|
1026
|
+
for platform_dir, suffix in ((".claude", ".md"), (".codex", ".toml")):
|
|
1027
|
+
agents_dir = project / platform_dir / "agents"
|
|
1028
|
+
agents_dir.mkdir(parents=True)
|
|
1029
|
+
for name in ("dev", "reviewer", "critic"):
|
|
1030
|
+
(agents_dir / f"prizm-dev-team-{name}{suffix}").write_text("agent\n", encoding="utf-8")
|
|
1031
|
+
feature = {
|
|
1032
|
+
"id": "F-123",
|
|
1033
|
+
"title": "Prompt Cleanup",
|
|
1034
|
+
"description": "Clean prompt text",
|
|
1035
|
+
"estimated_complexity": {"lite": "low", "standard": "medium", "full": "high"}[mode],
|
|
1036
|
+
"acceptance_criteria": ["Prompts are clean"],
|
|
1037
|
+
"critic": critic,
|
|
1038
|
+
}
|
|
1039
|
+
feature_list = project / ".prizmkit" / "plans" / "feature-list.json"
|
|
1040
|
+
_write_feature_list(feature_list, feature)
|
|
1041
|
+
output = project / "prompt.md"
|
|
1042
|
+
args = [
|
|
1043
|
+
"generate-bootstrap-prompt.py",
|
|
1044
|
+
"--feature-list", str(feature_list),
|
|
1045
|
+
"--feature-id", "F-123",
|
|
1046
|
+
"--session-id", "session-1",
|
|
1047
|
+
"--run-id", "run-1",
|
|
1048
|
+
"--retry-count", "0",
|
|
1049
|
+
"--resume-phase", "null",
|
|
1050
|
+
"--state-dir", str(project / ".prizmkit" / "state" / "features"),
|
|
1051
|
+
"--project-root", str(project),
|
|
1052
|
+
"--output", str(output),
|
|
1053
|
+
"--mode", mode,
|
|
1054
|
+
]
|
|
1055
|
+
if critic:
|
|
1056
|
+
args.extend(["--critic", "true"])
|
|
1057
|
+
if template:
|
|
1058
|
+
args.extend(["--template", str(Path("dev-pipeline/templates") / template)])
|
|
1059
|
+
old_argv = os.sys.argv
|
|
1060
|
+
old_platform = os.environ.get("PRIZMKIT_PLATFORM")
|
|
1061
|
+
try:
|
|
1062
|
+
os.sys.argv = args
|
|
1063
|
+
if old_platform is not None:
|
|
1064
|
+
os.environ.pop("PRIZMKIT_PLATFORM")
|
|
1065
|
+
try:
|
|
1066
|
+
generate_bootstrap_main()
|
|
1067
|
+
except SystemExit as exc:
|
|
1068
|
+
if exc.code not in (0, None):
|
|
1069
|
+
raise
|
|
1070
|
+
finally:
|
|
1071
|
+
os.sys.argv = old_argv
|
|
1072
|
+
if old_platform is not None:
|
|
1073
|
+
os.environ["PRIZMKIT_PLATFORM"] = old_platform
|
|
1074
|
+
return output.read_text(encoding="utf-8")
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
def _ensure_agent_files(project, platforms=("claude", "codex")):
|
|
1078
|
+
for platform in platforms:
|
|
1079
|
+
platform_dir = ".codex" if platform == "codex" else ".claude"
|
|
1080
|
+
suffix = ".toml" if platform == "codex" else ".md"
|
|
1081
|
+
agents_dir = project / platform_dir / "agents"
|
|
1082
|
+
agents_dir.mkdir(parents=True, exist_ok=True)
|
|
1083
|
+
for name in ("dev", "reviewer", "critic"):
|
|
1084
|
+
(agents_dir / f"prizm-dev-team-{name}{suffix}").write_text("agent\n", encoding="utf-8")
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
def _render_bugfix_prompt(tmp_path, platform="claude", explicit_platform=None):
|
|
1088
|
+
from generate_bugfix_prompt import main as bugfix_main
|
|
1089
|
+
|
|
1090
|
+
project = tmp_path / "bugfix-project"
|
|
1091
|
+
project.mkdir(parents=True)
|
|
1092
|
+
(project / ".prizmkit").mkdir(exist_ok=True)
|
|
1093
|
+
(project / ".prizmkit" / "config.json").write_text(
|
|
1094
|
+
json.dumps({"platform": platform, "ai_cli": platform}), encoding="utf-8"
|
|
1095
|
+
)
|
|
1096
|
+
_ensure_agent_files(project)
|
|
1097
|
+
bug_list = project / ".prizmkit" / "plans" / "bug-fix-list.json"
|
|
1098
|
+
bug_list.parent.mkdir(parents=True)
|
|
1099
|
+
bug_list.write_text(json.dumps({
|
|
1100
|
+
"bugs": [{"id": "B-001", "title": "Broken", "description": "Fix it", "acceptance_criteria": ["Works"]}],
|
|
1101
|
+
"global_context": {"language": "Python"},
|
|
1102
|
+
}), encoding="utf-8")
|
|
1103
|
+
output = project / "bugfix-prompt.md"
|
|
1104
|
+
old_argv = os.sys.argv
|
|
1105
|
+
old_platform = os.environ.get("PRIZMKIT_PLATFORM")
|
|
1106
|
+
try:
|
|
1107
|
+
if explicit_platform is None:
|
|
1108
|
+
os.environ.pop("PRIZMKIT_PLATFORM", None)
|
|
1109
|
+
else:
|
|
1110
|
+
os.environ["PRIZMKIT_PLATFORM"] = explicit_platform
|
|
1111
|
+
os.sys.argv = [
|
|
1112
|
+
"generate-bugfix-prompt.py",
|
|
1113
|
+
"--bug-list", str(bug_list),
|
|
1114
|
+
"--bug-id", "B-001",
|
|
1115
|
+
"--session-id", "session-1",
|
|
1116
|
+
"--run-id", "run-1",
|
|
1117
|
+
"--retry-count", "0",
|
|
1118
|
+
"--resume-phase", "null",
|
|
1119
|
+
"--state-dir", str(project / ".prizmkit" / "state" / "bugfix"),
|
|
1120
|
+
"--project-root", str(project),
|
|
1121
|
+
"--output", str(output),
|
|
1122
|
+
]
|
|
1123
|
+
try:
|
|
1124
|
+
bugfix_main()
|
|
1125
|
+
except SystemExit as exc:
|
|
1126
|
+
if exc.code not in (0, None):
|
|
1127
|
+
raise
|
|
1128
|
+
finally:
|
|
1129
|
+
os.sys.argv = old_argv
|
|
1130
|
+
if old_platform is None:
|
|
1131
|
+
os.environ.pop("PRIZMKIT_PLATFORM", None)
|
|
1132
|
+
else:
|
|
1133
|
+
os.environ["PRIZMKIT_PLATFORM"] = old_platform
|
|
1134
|
+
return output.read_text(encoding="utf-8")
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
def _render_refactor_prompt(tmp_path, platform="claude", explicit_platform=None):
|
|
1138
|
+
from generate_refactor_prompt import main as refactor_main
|
|
1139
|
+
|
|
1140
|
+
project = tmp_path / "refactor-project"
|
|
1141
|
+
project.mkdir(parents=True)
|
|
1142
|
+
(project / ".prizmkit").mkdir(exist_ok=True)
|
|
1143
|
+
(project / ".prizmkit" / "config.json").write_text(
|
|
1144
|
+
json.dumps({"platform": platform, "ai_cli": platform}), encoding="utf-8"
|
|
1145
|
+
)
|
|
1146
|
+
_ensure_agent_files(project)
|
|
1147
|
+
refactor_list = project / ".prizmkit" / "plans" / "refactor-list.json"
|
|
1148
|
+
refactor_list.parent.mkdir(parents=True)
|
|
1149
|
+
refactor_list.write_text(json.dumps({
|
|
1150
|
+
"refactors": [{
|
|
1151
|
+
"id": "R-001",
|
|
1152
|
+
"title": "Restructure",
|
|
1153
|
+
"description": "Preserve behavior",
|
|
1154
|
+
"acceptance_criteria": ["Behavior preserved"],
|
|
1155
|
+
"scope": {"files": ["src/a.py"], "modules": ["src"]},
|
|
1156
|
+
}],
|
|
1157
|
+
"global_context": {"language": "Python"},
|
|
1158
|
+
}), encoding="utf-8")
|
|
1159
|
+
output = project / "refactor-prompt.md"
|
|
1160
|
+
old_argv = os.sys.argv
|
|
1161
|
+
old_platform = os.environ.get("PRIZMKIT_PLATFORM")
|
|
1162
|
+
try:
|
|
1163
|
+
if explicit_platform is None:
|
|
1164
|
+
os.environ.pop("PRIZMKIT_PLATFORM", None)
|
|
1165
|
+
else:
|
|
1166
|
+
os.environ["PRIZMKIT_PLATFORM"] = explicit_platform
|
|
1167
|
+
os.sys.argv = [
|
|
1168
|
+
"generate-refactor-prompt.py",
|
|
1169
|
+
"--refactor-list", str(refactor_list),
|
|
1170
|
+
"--refactor-id", "R-001",
|
|
1171
|
+
"--session-id", "session-1",
|
|
1172
|
+
"--run-id", "run-1",
|
|
1173
|
+
"--retry-count", "0",
|
|
1174
|
+
"--resume-phase", "null",
|
|
1175
|
+
"--state-dir", str(project / ".prizmkit" / "state" / "refactor"),
|
|
1176
|
+
"--output", str(output),
|
|
1177
|
+
]
|
|
1178
|
+
old_cwd = os.getcwd()
|
|
1179
|
+
os.chdir(project)
|
|
1180
|
+
try:
|
|
1181
|
+
try:
|
|
1182
|
+
refactor_main()
|
|
1183
|
+
except SystemExit as exc:
|
|
1184
|
+
if exc.code not in (0, None):
|
|
1185
|
+
raise
|
|
1186
|
+
finally:
|
|
1187
|
+
os.chdir(old_cwd)
|
|
1188
|
+
finally:
|
|
1189
|
+
os.sys.argv = old_argv
|
|
1190
|
+
if old_platform is None:
|
|
1191
|
+
os.environ.pop("PRIZMKIT_PLATFORM", None)
|
|
1192
|
+
else:
|
|
1193
|
+
os.environ["PRIZMKIT_PLATFORM"] = old_platform
|
|
1194
|
+
return output.read_text(encoding="utf-8")
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
class TestHeadlessPromptCleanupF033:
|
|
1198
|
+
def test_rendered_feature_bugfix_refactor_prompts_are_clean(self, tmp_path):
|
|
1199
|
+
prompts = []
|
|
1200
|
+
for mode in ("lite", "standard", "full"):
|
|
1201
|
+
prompts.append(_render_feature_prompt(tmp_path / mode, mode=mode, critic=(mode != "lite")))
|
|
1202
|
+
prompts.append(_render_bugfix_prompt(tmp_path))
|
|
1203
|
+
prompts.append(_render_refactor_prompt(tmp_path))
|
|
1204
|
+
|
|
1205
|
+
for prompt in prompts:
|
|
1206
|
+
for forbidden in HEADLESS_FORBIDDEN_PROMPT_STRINGS:
|
|
1207
|
+
assert forbidden not in prompt
|
|
1208
|
+
if "Feature ID" in prompt:
|
|
1209
|
+
assert "/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/123-prompt-cleanup/" in prompt
|
|
1210
|
+
assert ".prizmkit-test-started" in prompt
|
|
1211
|
+
|
|
1212
|
+
def test_legacy_feature_templates_are_clean_when_rendered(self, tmp_path):
|
|
1213
|
+
for template, mode in (("bootstrap-tier1.md", "lite"), ("bootstrap-tier2.md", "standard"), ("bootstrap-tier3.md", "full")):
|
|
1214
|
+
prompt = _render_feature_prompt(tmp_path / template, mode=mode, critic=(mode != "lite"), template=template)
|
|
1215
|
+
for forbidden in HEADLESS_FORBIDDEN_PROMPT_STRINGS:
|
|
1216
|
+
assert forbidden not in prompt
|
|
1217
|
+
assert "prizmkit-test-gate.py" not in prompt
|
|
1218
|
+
assert ".prizmkit-test-started" in prompt
|
|
1219
|
+
|
|
1220
|
+
def test_claude_config_wins_over_codex_directory_for_critic_path(self, tmp_path, monkeypatch):
|
|
1221
|
+
project = tmp_path / "mixed"
|
|
1222
|
+
(project / ".claude" / "agents").mkdir(parents=True)
|
|
1223
|
+
(project / ".codex" / "agents").mkdir(parents=True)
|
|
1224
|
+
(project / ".prizmkit").mkdir()
|
|
1225
|
+
(project / ".prizmkit" / "config.json").write_text(
|
|
1226
|
+
json.dumps({"platform": "claude", "ai_cli": "claude"}), encoding="utf-8"
|
|
1227
|
+
)
|
|
1228
|
+
monkeypatch.delenv("PRIZMKIT_PLATFORM", raising=False)
|
|
1229
|
+
|
|
1230
|
+
assert resolve_prompt_platform(str(project)) == "claude"
|
|
1231
|
+
prompt = _render_feature_prompt(tmp_path / "rendered-mixed", mode="standard", critic=True, platform="claude")
|
|
1232
|
+
assert ".claude/agents/prizm-dev-team-critic.md" in prompt
|
|
1233
|
+
assert ".codex/agents/prizm-dev-team-critic.toml" not in prompt
|
|
1234
|
+
|
|
1235
|
+
def test_bugfix_refactor_share_claude_platform_resolution(self, tmp_path, monkeypatch):
|
|
1236
|
+
from generate_bugfix_prompt import build_replacements as bugfix_build_replacements
|
|
1237
|
+
|
|
1238
|
+
monkeypatch.delenv("PRIZMKIT_PLATFORM", raising=False)
|
|
1239
|
+
bug_project = tmp_path / "bugfix-replacements"
|
|
1240
|
+
bug_project.mkdir()
|
|
1241
|
+
(bug_project / ".prizmkit").mkdir()
|
|
1242
|
+
(bug_project / ".prizmkit" / "config.json").write_text(
|
|
1243
|
+
json.dumps({"platform": "claude", "ai_cli": "claude"}), encoding="utf-8"
|
|
1244
|
+
)
|
|
1245
|
+
_ensure_agent_files(bug_project)
|
|
1246
|
+
args = Namespace(
|
|
1247
|
+
bug_id="B-001", session_id="session-1", run_id="run-1",
|
|
1248
|
+
retry_count="0", resume_phase="null", state_dir=None,
|
|
1249
|
+
output="out.md", project_root=str(bug_project), template=None,
|
|
1250
|
+
mode=None, critic=None,
|
|
1251
|
+
)
|
|
1252
|
+
replacements = bugfix_build_replacements(
|
|
1253
|
+
args, {"id": "B-001", "title": "Broken"}, {}, str(Path("dev-pipeline/scripts").resolve())
|
|
1254
|
+
)
|
|
1255
|
+
refactor_prompt = _render_refactor_prompt(tmp_path / "refactor-mixed", platform="claude")
|
|
1256
|
+
|
|
1257
|
+
assert replacements["{{REVIEWER_SUBAGENT_PATH}}"].endswith(".claude/agents/prizm-dev-team-reviewer.md")
|
|
1258
|
+
assert ".claude/agents/prizm-dev-team-reviewer.md" in refactor_prompt
|
|
1259
|
+
assert ".codex/agents/prizm-dev-team-reviewer.toml" not in refactor_prompt
|
|
1260
|
+
|
|
1261
|
+
def test_bugfix_refactor_explicit_codex_override(self, tmp_path, monkeypatch):
|
|
1262
|
+
from generate_bugfix_prompt import build_replacements as bugfix_build_replacements
|
|
1263
|
+
|
|
1264
|
+
bug_project = tmp_path / "bugfix-codex-replacements"
|
|
1265
|
+
bug_project.mkdir()
|
|
1266
|
+
_ensure_agent_files(bug_project)
|
|
1267
|
+
monkeypatch.setenv("PRIZMKIT_PLATFORM", "codex")
|
|
1268
|
+
args = Namespace(
|
|
1269
|
+
bug_id="B-001", session_id="session-1", run_id="run-1",
|
|
1270
|
+
retry_count="0", resume_phase="null", state_dir=None,
|
|
1271
|
+
output="out.md", project_root=str(bug_project), template=None,
|
|
1272
|
+
mode=None, critic=None,
|
|
1273
|
+
)
|
|
1274
|
+
replacements = bugfix_build_replacements(
|
|
1275
|
+
args, {"id": "B-001", "title": "Broken"}, {}, str(Path("dev-pipeline/scripts").resolve())
|
|
1276
|
+
)
|
|
1277
|
+
refactor_prompt = _render_refactor_prompt(tmp_path / "refactor-codex", platform="claude", explicit_platform="codex")
|
|
1278
|
+
|
|
1279
|
+
assert replacements["{{REVIEWER_SUBAGENT_PATH}}"].endswith(".codex/agents/prizm-dev-team-reviewer.toml")
|
|
1280
|
+
assert ".codex/agents/prizm-dev-team-reviewer.toml" in refactor_prompt
|
|
1281
|
+
assert ".claude/agents/prizm-dev-team-reviewer.md" not in refactor_prompt
|
|
1282
|
+
|
|
1283
|
+
def test_explicit_codex_env_still_renders_codex_critic_path(self, tmp_path, monkeypatch):
|
|
1284
|
+
project = tmp_path / "codex"
|
|
1285
|
+
(project / ".claude" / "agents").mkdir(parents=True)
|
|
1286
|
+
(project / ".codex" / "agents").mkdir(parents=True)
|
|
1287
|
+
monkeypatch.setenv("PRIZMKIT_PLATFORM", "codex")
|
|
1288
|
+
|
|
1289
|
+
assert resolve_prompt_platform(str(project)) == "codex"
|