prizmkit 1.1.107 → 1.1.109

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/bin/create-prizmkit.js +4 -0
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/dev-pipeline/prizmkit_runtime/cli.py +20 -0
  4. package/bundled/dev-pipeline/prizmkit_runtime/commands.py +1 -0
  5. package/bundled/dev-pipeline/prizmkit_runtime/config.py +81 -14
  6. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +21 -0
  7. package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +19 -8
  8. package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +1 -1
  9. package/bundled/dev-pipeline/prizmkit_runtime/launch_profiles.py +18 -0
  10. package/bundled/dev-pipeline/prizmkit_runtime/platform_detection.py +208 -0
  11. package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +22 -2
  12. package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +3 -1
  13. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +20 -1
  14. package/bundled/dev-pipeline/prizmkit_runtime/runtime_helper.py +508 -0
  15. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +151 -30
  16. package/bundled/dev-pipeline/scripts/continuation.py +0 -1
  17. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +8 -46
  18. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +9 -34
  19. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +42 -33
  20. package/bundled/dev-pipeline/scripts/prizmkit-runtime-helper.py +27 -0
  21. package/bundled/dev-pipeline/scripts/utils.py +94 -0
  22. package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +4 -3
  23. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
  24. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +39 -65
  25. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +58 -96
  26. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +54 -95
  27. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +6 -18
  28. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +5 -17
  29. package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +14 -48
  30. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +7 -13
  31. package/bundled/dev-pipeline/templates/sections/feature-context.md +0 -4
  32. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-auto.md +31 -61
  33. package/bundled/dev-pipeline/templates/sections/phase-browser-verification-opencli.md +21 -37
  34. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +22 -69
  35. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +0 -14
  36. package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -14
  37. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -7
  38. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-base.md +1 -3
  39. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -7
  40. package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +7 -9
  41. package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +4 -8
  42. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +0 -7
  43. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +0 -7
  44. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -7
  45. package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +3 -10
  46. package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +2 -9
  47. package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +15 -16
  48. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +1 -8
  49. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +1 -8
  50. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +9 -15
  51. package/bundled/dev-pipeline/templates/sections/phase0-init.md +1 -8
  52. package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +2 -15
  53. package/bundled/dev-pipeline/templates/sections/subagent-timeout-recovery.md +1 -1
  54. package/bundled/dev-pipeline/tests/conftest.py +0 -1
  55. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +392 -23
  56. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +37 -17
  57. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +118 -14
  58. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +79 -2
  59. package/bundled/dev-pipeline/tests/test_runtime_helper.py +211 -0
  60. package/bundled/dev-pipeline/tests/test_unified_cli.py +663 -13
  61. package/bundled/skills/_metadata.json +4 -4
  62. package/bundled/skills/app-planner/SKILL.md +1 -1
  63. package/bundled/skills/app-planner/references/architecture-decisions.md +1 -1
  64. package/bundled/skills/bug-fix-workflow/SKILL.md +174 -128
  65. package/bundled/skills/bug-planner/SKILL.md +101 -15
  66. package/bundled/skills/bug-planner/references/severity-rules.md +20 -8
  67. package/bundled/skills/feature-planner/SKILL.md +87 -8
  68. package/bundled/skills/feature-planner/assets/planning-guide.md +34 -10
  69. package/bundled/skills/feature-workflow/SKILL.md +100 -81
  70. package/bundled/skills/{prizm-kit → prizmkit}/SKILL.md +1 -1
  71. package/bundled/skills/prizmkit-code-review/SKILL.md +1 -1
  72. package/bundled/skills/refactor-planner/SKILL.md +88 -7
  73. package/bundled/skills/refactor-planner/references/fast-path.md +2 -1
  74. package/bundled/skills/refactor-planner/references/planning-phases.md +29 -11
  75. package/bundled/skills/refactor-workflow/SKILL.md +116 -57
  76. package/bundled/templates/project-memory-template.md +1 -1
  77. package/package.json +1 -1
  78. package/src/ai-cli-launch.js +194 -0
  79. package/src/config.js +26 -14
  80. package/src/index.js +11 -44
  81. package/src/platforms.js +10 -3
  82. package/src/prompts.js +60 -2
  83. package/src/scaffold.js +26 -14
  84. package/bundled/dev-pipeline/scripts/prizmkit-test-gate.py +0 -446
  85. package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +0 -20
  86. package/bundled/dev-pipeline/tests/test_prizmkit_test_gate.py +0 -107
@@ -19,7 +19,7 @@ import os
19
19
  import re
20
20
  import sys
21
21
 
22
- from utils import enrich_global_context, load_json_file, read_platform_conventions, setup_logging
22
+ from utils import enrich_global_context, helper_replacements, load_json_file, read_checkpoint_system_section, resolve_prompt_platform, setup_logging
23
23
  from continuation import add_continuation_args, append_continuation_handoff, is_continuation
24
24
 
25
25
 
@@ -134,6 +134,7 @@ def parse_args():
134
134
  parser.add_argument("--resume-phase", required=True, help='Phase to resume from, or "null" for fresh start')
135
135
  parser.add_argument("--state-dir", default=None, help="State directory (default: .prizmkit/state/refactor)")
136
136
  parser.add_argument("--output", required=True, help="Output path for the rendered prompt")
137
+ parser.add_argument("--project-root", default=None, help="AI-visible project root used for rendered prompt paths")
137
138
  parser.add_argument("--template", default=None, help="Custom template path. Defaults to {script_dir}/../templates/refactor-bootstrap-prompt.md")
138
139
  parser.add_argument("--mode", default=None, help="Pipeline execution mode override: lite, standard, full")
139
140
  parser.add_argument("--critic", default=None, help="Enable critic agent: true/false")
@@ -167,19 +168,6 @@ def _parse_positive_int_env(name, default):
167
168
  return parsed
168
169
 
169
170
 
170
- def load_log_size_section(script_dir):
171
- """Load passive checkpoint guidance for normal prompt generation."""
172
- section_path = os.path.join(
173
- script_dir, "..", "templates", "sections", "log-size-awareness.md",
174
- )
175
- if not os.path.isfile(section_path):
176
- return ""
177
-
178
- content, err = read_text_file(section_path)
179
- if err:
180
- return ""
181
- return content
182
-
183
171
  def find_refactor(refactors, refactor_id):
184
172
  """Find and return the refactor dict matching the given ID."""
185
173
  for refactor in refactors:
@@ -396,22 +384,39 @@ def resolve_project_root(script_dir):
396
384
  return os.path.abspath(pipeline_parent)
397
385
 
398
386
 
387
+ def _project_root_from_prizmkit_path(path):
388
+ """Infer project root from a path nested under .prizmkit/."""
389
+ if not path:
390
+ return ""
391
+ current = os.path.abspath(path)
392
+ if not os.path.isdir(current):
393
+ current = os.path.dirname(current)
394
+ while current and current != os.path.dirname(current):
395
+ if os.path.basename(current) == ".prizmkit":
396
+ return os.path.abspath(os.path.dirname(current))
397
+ current = os.path.dirname(current)
398
+ return ""
399
+
400
+
401
+ def _args_project_root(args, script_dir):
402
+ """Return explicit AI-visible project root, plan-path root, or script-layout default."""
403
+ explicit = getattr(args, "project_root", None)
404
+ if explicit:
405
+ return os.path.abspath(explicit)
406
+ plan_root = _project_root_from_prizmkit_path(getattr(args, "refactor_list", ""))
407
+ if plan_root:
408
+ return plan_root
409
+ return resolve_project_root(script_dir)
410
+
411
+
399
412
  def build_replacements(args, refactor, refactors, global_context, script_dir):
400
413
  """Build the full dict of placeholder -> replacement value."""
401
- project_root = resolve_project_root(script_dir)
414
+ project_root = _args_project_root(args, script_dir)
402
415
 
403
416
  # Platform-aware agent/team path resolution
404
- platform = os.environ.get("PRIZMKIT_PLATFORM", "")
417
+ platform = resolve_prompt_platform(project_root)
405
418
  home_dir = os.path.expanduser("~")
406
419
 
407
- if not platform:
408
- if os.path.isdir(os.path.join(project_root, ".codex", "agents")):
409
- platform = "codex"
410
- elif os.path.isdir(os.path.join(project_root, ".claude", "agents")):
411
- platform = "claude"
412
- else:
413
- platform = "codebuddy"
414
-
415
420
  if platform == "claude":
416
421
  agents_dir = os.path.join(project_root, ".claude", "agents")
417
422
  team_config_path = os.path.join(project_root, ".claude", "team-info.json")
@@ -428,10 +433,16 @@ def build_replacements(args, refactor, refactors, global_context, script_dir):
428
433
  dev_subagent = os.path.join(agents_dir, f"prizm-dev-team-dev{agent_ext}")
429
434
  reviewer_subagent = os.path.join(agents_dir, f"prizm-dev-team-reviewer{agent_ext}")
430
435
 
431
- # Session status path
436
+ # Session status is controlled by the main runner state dir, even when
437
+ # rendered project paths are AI-visible worktree paths.
438
+ state_dir = (
439
+ os.path.abspath(args.state_dir)
440
+ if args.state_dir
441
+ else os.path.join(project_root, ".prizmkit", "state", "refactor")
442
+ )
432
443
  session_status_path = os.path.join(
433
- project_root, ".prizmkit", "state", "refactor", args.refactor_id,
434
- "sessions", args.session_id, "session-status.json"
444
+ state_dir, args.refactor_id, "sessions", args.session_id,
445
+ "session-status.json",
435
446
  )
436
447
 
437
448
  # Scope
@@ -493,7 +504,6 @@ def build_replacements(args, refactor, refactors, global_context, script_dir):
493
504
  browser_verify_steps = " # (validate UI renders correctly and feature still works)"
494
505
 
495
506
  replacements = {
496
- "{{LOG_SIZE_AWARENESS}}": load_log_size_section(script_dir),
497
507
  "{{SESSION_LOG_PATH}}": os.path.join(
498
508
  ".prizmkit", "state", "refactor", args.refactor_id,
499
509
  "sessions", args.session_id, "logs", "session.log",
@@ -527,13 +537,15 @@ def build_replacements(args, refactor, refactors, global_context, script_dir):
527
537
  "{{CHECKPOINT_PATH}}": os.path.join(
528
538
  ".prizmkit", "refactor", args.refactor_id, "workflow-checkpoint.json",
529
539
  ),
540
+ "{{CHECKPOINT_SYSTEM}}": read_checkpoint_system_section(script_dir),
530
541
  "{{TIMESTAMP}}": "", # Placeholder — agent fills in timestamp
531
- "{{PLATFORM_CONVENTIONS}}": read_platform_conventions(project_root),
532
542
  "{{BROWSER_ENABLED}}": "true" if browser_enabled else "false",
533
543
  "{{BROWSER_TOOL}}": browser_tool,
534
544
  "{{BROWSER_VERIFY_STEPS}}": browser_verify_steps,
535
545
  }
536
546
 
547
+ replacements.update(helper_replacements(script_dir))
548
+
537
549
  return replacements
538
550
 
539
551
 
@@ -696,9 +708,6 @@ def main():
696
708
 
697
709
  # Build replacements
698
710
  replacements = build_replacements(args, refactor, refactors, global_context, script_dir)
699
- if is_continuation(args):
700
- replacements["{{LOG_SIZE_AWARENESS}}"] = ""
701
-
702
711
  # Render the template
703
712
  rendered = render_template(template_content, replacements, args.resume_phase, refactor)
704
713
 
@@ -708,7 +717,7 @@ def main():
708
717
  emit_failure(err)
709
718
 
710
719
  # Generate checkpoint file
711
- project_root = resolve_project_root(script_dir)
720
+ project_root = _args_project_root(args, script_dir)
712
721
  checkpoint_rel = os.path.join(
713
722
  ".prizmkit", "refactor", args.refactor_id, "workflow-checkpoint.json",
714
723
  )
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ """Thin entrypoint for the PrizmKit prompt runtime helper CLI."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import sys
7
+ from pathlib import Path
8
+
9
+
10
+ def _bootstrap_import_path() -> None:
11
+ """Ensure direct script execution can import the runtime package."""
12
+ pipeline_root = Path(__file__).resolve().parents[1]
13
+ pipeline_root_text = str(pipeline_root)
14
+ if pipeline_root_text not in sys.path:
15
+ sys.path.insert(0, pipeline_root_text)
16
+
17
+
18
+ def main(argv: list[str] | None = None) -> int:
19
+ """Run the runtime helper CLI and return its process exit code."""
20
+ _bootstrap_import_path()
21
+ from prizmkit_runtime.runtime_helper import main as helper_main
22
+
23
+ return helper_main(argv)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ raise SystemExit(main())
@@ -9,8 +9,50 @@ import json
9
9
  import logging
10
10
  import os
11
11
  import re
12
+ import shlex
12
13
  import sys
13
14
 
15
+ _PIPELINE_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
16
+ if _PIPELINE_ROOT not in sys.path:
17
+ sys.path.insert(0, _PIPELINE_ROOT)
18
+
19
+
20
+ def shell_quote(value):
21
+ """Return a shell-safe token for prompt command examples."""
22
+ return shlex.quote(str(value))
23
+
24
+
25
+ def runtime_python_command():
26
+ """Return the current Python executable for rendered prompt commands."""
27
+ return shell_quote(sys.executable or "python3")
28
+
29
+
30
+ def runtime_helper_command(script_dir):
31
+ """Return the installed-project helper command prefix for prompt templates."""
32
+ helper_path = os.path.join(
33
+ ".prizmkit", "dev-pipeline", "scripts", "prizmkit-runtime-helper.py"
34
+ )
35
+ return "{} {}".format(runtime_python_command(), helper_path)
36
+
37
+
38
+ def checkpoint_python_command():
39
+ """Return the checkpoint update Python command prefix for prompt templates."""
40
+ return "{} {}".format(
41
+ runtime_python_command(),
42
+ os.path.join(".prizmkit", "dev-pipeline", "scripts", "update-checkpoint.py"),
43
+ )
44
+
45
+
46
+ def helper_replacements(script_dir):
47
+ """Return common prompt placeholders for Python runtime helpers."""
48
+ return {
49
+ "{{PYTHON_CMD}}": runtime_python_command(),
50
+ "{{RUNTIME_HELPER_CMD}}": runtime_helper_command(script_dir),
51
+ "{{CHECKPOINT_PYTHON_CMD}}": checkpoint_python_command(),
52
+ }
53
+
54
+
55
+
14
56
 
15
57
  def load_json_file(path):
16
58
  """Load and return parsed JSON from a file.
@@ -79,6 +121,46 @@ def error_out(message, code=1):
79
121
  sys.exit(code)
80
122
 
81
123
 
124
+ def read_checkpoint_system_section(script_dir):
125
+ """Read the shared checkpoint prompt section for feature/bugfix/refactor prompts."""
126
+ path = os.path.join(
127
+ os.path.abspath(script_dir), "..", "templates", "sections", "checkpoint-system.md"
128
+ )
129
+ try:
130
+ with open(path, "r", encoding="utf-8") as f:
131
+ return f.read()
132
+ except IOError:
133
+ return """## Workflow Checkpoint System
134
+
135
+ A checkpoint file tracks your progress through this workflow:
136
+
137
+ **Path**: `{{CHECKPOINT_PATH}}`
138
+
139
+ ### Checkpoint Update Helper
140
+
141
+ Use this helper to update checkpoint status. Do not hand-edit `workflow-checkpoint.json` directly.
142
+
143
+ ```bash
144
+ {{CHECKPOINT_PYTHON_CMD}} \\
145
+ --checkpoint-path {{CHECKPOINT_PATH}} \\
146
+ --step <step-id-or-skill-name> \\
147
+ --status <in_progress|completed|failed|skipped> \\
148
+ --note "<optional note>"
149
+ ```
150
+
151
+ - Use the step `skill` value such as `prizmkit-implement`, or the step id such as `S04`.
152
+ - Omit `--note` when there is no useful failure or handoff note.
153
+
154
+ ### Rules
155
+
156
+ 1. **Before each skill**: Read `workflow-checkpoint.json`, verify the previous step has `status: "completed"` or `status: "skipped"`. If it is still `"pending"` or `"in_progress"`, complete it first before moving on.
157
+ 2. **Starting a skill**: Use the checkpoint update helper to mark the current step as `status: "in_progress"`.
158
+ 3. **After each skill completes**: Use the checkpoint update helper to mark the current step as `status: "completed"`.
159
+ 4. **On failure**: Use the checkpoint update helper to mark the step as `status: "failed"`, write `failure-log.md` with the reason, and continue only when the workflow rules allow it.
160
+ 5. **On session exit**: The checkpoint file reflects your actual progress. Do NOT manually set future steps to `"completed"`.
161
+ """
162
+
163
+
82
164
  def pad_right(text, width):
83
165
  """Pad text with spaces to fill width, accounting for ANSI escape codes."""
84
166
  i = 0
@@ -520,6 +602,18 @@ def enrich_global_context(global_context, project_root):
520
602
  return global_context
521
603
 
522
604
 
605
+ def resolve_prompt_platform(project_root):
606
+ """Resolve the platform whose agent paths should appear in prompts."""
607
+ from prizmkit_runtime.platform_detection import resolve_platform
608
+
609
+ resolution = resolve_platform(project_root)
610
+ if resolution.platform:
611
+ return resolution.platform
612
+ raise RuntimeError(
613
+ "PrizmKit agents not found. None of .claude/agents/, .codex/agents/, or .codebuddy/agents/ exists. "
614
+ "Run `npx prizmkit install` first, set .prizmkit/config.json ai_cli/platform, or set PRIZMKIT_PLATFORM=claude|codex|codebuddy explicitly."
615
+ )
616
+
523
617
  def read_platform_conventions(project_root):
524
618
  """Resolve the platform-specific project conventions file.
525
619
 
@@ -1,7 +1,8 @@
1
1
  "Read {{CRITIC_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
2
2
  **MODE: Plan Challenge**
3
3
  1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST — Section 3 has project context, Section 4 has file manifest.
4
- 2. Read `.prizmkit/prizm-docs/root.prizm` and relevant L1/L2 docs for affected modules.
5
- 3. Read existing source files in the modules this plan touches.
6
- 4. Challenge plan.md against the project's existing architecture, patterns, and style.
4
+ 2. Use context-snapshot.md as the shared source of truth. Do not create or enter AI tool-created `.claude/worktrees/...` subagent worktrees; use default/no worktree isolation and do not request worktree isolation.
5
+ 3. PrizmKit pipeline-managed linked git worktrees under `.prizmkit/state/worktrees/...` are a separate runner feature controlled by `USE_WORKTREE`; do not confuse them with AI tool-created `.claude/worktrees/...`.
6
+ 4. Read additional `.prizmkit/prizm-docs/` or source excerpts only when needed to verify a specific challenge.
7
+ 5. Challenge plan.md against the project's existing architecture, patterns, and style.
7
8
  Write `.prizmkit/specs/{{FEATURE_SLUG}}/challenge-report.md` with findings (or 'No significant challenges')."
@@ -44,7 +44,7 @@ Infer what needs to be done from the feature context above and follow the standa
44
44
  - Do NOT push to remote — the user will push manually.
45
45
  - Write all artifacts to `.prizmkit/specs/{{FEATURE_SLUG}}/`.
46
46
  - If a step fails after 3 attempts, write a status report and stop.
47
- - **Anti re-read**: once you read a file into context, do NOT read it again — use `grep -n`/`sed -n` for specific lines. 3 full Reads of same file report BLOCKED.
47
+ - **Never re-read unmodified files**: once you read a file into context, do NOT read it again unless it was modified by an Edit/Write after your last read — use `grep -n`/`sed -n` for specific lines. Before issuing a Read, ask: "Have I read this file before, and has it changed since?" If no — do NOT read it. Subagents (Critic, Reviewer) must rely on context-snapshot.md rather than re-reading files the orchestrator already read.
48
48
  - **Read offset safety**: if Read returns "shorter than offset"/"empty" — run `wc -l` then `sed -n`, do NOT retry same offset.
49
49
  - **Hard Round Cap**: after 6 total test-fix rounds, STOP trial-and-error. Switch to read-once-then-rewrite. Do NOT exceed 7 rounds.
50
50
  - **Layered test**: debug with single-file tests, only run full suite as gate when single-file is green.
@@ -46,21 +46,18 @@ You are running in **headless non-interactive mode** with a FINITE context windo
46
46
 
47
47
  1. **context-snapshot.md is your single source of truth** — After Phase 1 builds it, ALWAYS read context-snapshot.md instead of re-reading individual source files
48
48
  2. **Never re-read your own writes** — After you create/modify a file, do NOT read it back to verify. Trust your write was correct.
49
- 3. **Stay focused** — Do NOT explore code unrelated to this feature. No curiosity-driven reads.
49
+ 3. **Never re-read unmodified files** — Once you have read a file into context, do NOT read it again unless it was modified by an Edit/Write operation after your last read. Use `grep -n '<pattern>' <file>` or `sed -n '<start>,<end>p' <file>` for targeted line lookups instead of full-file Read. Before issuing a Read, ask yourself: "Have I read this file before, and has it changed since?" If the answer is "no, it hasn't changed" — do NOT read it. This applies to all files including those summarized in context-snapshot.md Section 4. Subagents (Critic, Reviewer) must receive context-snapshot.md and rely on it rather than independently re-reading the same files the orchestrator already read.
50
+ 4. **Stay focused** — Do NOT explore code unrelated to this feature. No curiosity-driven reads.
50
51
  4. **One task at a time** — In Phase 3 (implement), complete and test one task before starting the next.
51
52
  5. **Minimize tool output** — Never load full command output into context. First capture to a temp file (`cmd 2>&1 | tee /tmp/out.txt | tail -20`), then scan the head/tail to identify relevant fields, and use targeted filtering (`grep`, `sed`, `awk`) to extract only the information needed for the current task. Only read the filtered result — never the raw full output.
52
53
  6. **No intermediate commits** — Do NOT run `git add`/`git commit` during Phase 1-3. All changes are committed once at the end in Phase 4 via `/prizmkit-committer`.
53
54
  7. **Capture test output once** — When running test suites, always use `<test-command> 2>&1 | tee /tmp/test-out.txt | tail -20`. Then grep `/tmp/test-out.txt` for details. Never re-run the suite just to apply a different filter.
54
- 8. **Scaffold / generated file awareness** — Files created by scaffolding tools (`npm init`, `npx create-*`, etc.) are boilerplate. Tag them, record in context-snapshot.md, and NEVER re-read them. If you need to modify one, edit directly without reading first.
55
55
  9. **Package version verification (BLOCKING)** — Before writing ANY dependency version, verify it exists via registry query (`npm view <pkg> dist-tags.latest`, `pip index versions <pkg>`, etc.). NEVER guess version numbers.
56
56
  10. **Build artifact hygiene** — After build/compile, ensure output is in `.gitignore`. Never commit binaries/build output.
57
57
  11. **Read offset safety (BLOCKING)** — If Read returns "shorter than offset"/"File is empty"/"Wasted call" — do NOT retry same offset. Run `wc -l <file>` to get real line count, then `sed -n` for exact range. 2 consecutive offset errors → STOP Reading that file. Never guess offsets — `grep -n '<anchor>'` first.
58
58
 
59
59
  ---
60
60
 
61
- {{LOG_SIZE_AWARENESS}}
62
- ---
63
-
64
61
  ## PrizmKit Directory Convention
65
62
 
66
63
  ```
@@ -75,7 +72,7 @@ You are running in **headless non-interactive mode** with a FINITE context windo
75
72
  {{IF_INIT_NEEDED}}
76
73
  ### Phase 0: Project Bootstrap
77
74
  - Run `/prizmkit-init` (invoke the prizmkit-init skill)
78
- - Run `python3 {{INIT_SCRIPT_PATH}} --project-root {{PROJECT_ROOT}} --feature-id {{FEATURE_ID}} --feature-slug {{FEATURE_SLUG}}`
75
+ - Run `{{PYTHON_CMD}} {{INIT_SCRIPT_PATH}} --project-root {{PROJECT_ROOT}} --feature-id {{FEATURE_ID}} --feature-slug {{FEATURE_SLUG}}`
79
76
  - **CP-0**: Verify `.prizmkit/prizm-docs/root.prizm`, `.prizmkit/config.json` exist
80
77
  {{END_IF_INIT_NEEDED}}
81
78
  {{IF_INIT_DONE}}
@@ -85,16 +82,16 @@ You are running in **headless non-interactive mode** with a FINITE context windo
85
82
  ### Phase 1: Build Context Snapshot
86
83
 
87
84
  ```bash
88
- ls .prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md 2>/dev/null && echo "EXISTS" || echo "MISSING"
85
+ {{RUNTIME_HELPER_CMD}} artifact exists .prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md
89
86
  ```
90
87
 
91
88
  If MISSING — build it now:
92
89
  1. Read `.prizmkit/prizm-docs/root.prizm` and relevant L1 prizm docs
93
- 2. Detect source code directories: read KEY_FILES and STRUCTURE sections from `root.prizm` to identify where source code lives (e.g. `src/`, `app/`, `lib/`, `cmd/`, `packages/`, or project root). If `root.prizm` is missing, scan the project tree:
90
+ 2. Detect source code directories from KEY_FILES and STRUCTURE sections in `root.prizm`; if root docs are unavailable, use the helper to list likely source files:
94
91
  ```bash
95
- find . -maxdepth 2 -type f \( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.go" -o -name "*.java" -o -name "*.rb" -o -name "*.rs" \) -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/vendor/*' | head -30
92
+ {{RUNTIME_HELPER_CMD}} artifact source-files . --json
96
93
  ```
97
- Identify the top-level source directories from the results.
94
+ Identify the top-level source directories from the helper output.
98
95
  3. Scan the detected source directories for files related to this feature; read each one
99
96
  4. Write `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
100
97
  - **Section 1 — Feature Brief**: feature description + acceptance criteria (copy from above)
@@ -109,12 +106,12 @@ If MISSING — build it now:
109
106
  ### Phase 2: Plan & Tasks
110
107
 
111
108
  ```bash
112
- ls .prizmkit/specs/{{FEATURE_SLUG}}/ 2>/dev/null
109
+ {{RUNTIME_HELPER_CMD}} artifact exists .prizmkit/specs/{{FEATURE_SLUG}}
113
110
  ```
114
111
 
115
112
  If plan.md missing, run `/prizmkit-plan` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to generate `plan.md`:
116
113
  - The plan.md should include: key components, data flow, files to create/modify, and a Tasks section with `[ ]` checkboxes (each task = one implementable unit). Keep under 80 lines.
117
- - Resolve any `[NEEDS CLARIFICATION]` markers using the feature description do NOT pause for interactive input.
114
+ - Resolve uncertain requirements from the feature description, existing code, and conservative existing-project patterns.
118
115
 
119
116
  **Database Design Gate** (if feature involves data persistence — new tables, schema changes, new entities):
120
117
  Before proceeding past CP-1:
@@ -160,7 +157,7 @@ The skill runs an internal review-fix loop (Reviewer Agent → filter → orches
160
157
  **Gate Check — Review Report**:
161
158
  After `/prizmkit-code-review` returns, verify the review report:
162
159
  ```bash
163
- grep -q "## Verdict" .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md && echo "GATE:PASS" || echo "GATE:MISSING"
160
+ {{RUNTIME_HELPER_CMD}} text contains .prizmkit/specs/{{FEATURE_SLUG}}/review-report.md --pattern "## Verdict"
164
161
  ```
165
162
  If GATE:MISSING:
166
163
  - Do not re-run `/prizmkit-code-review` in an unbounded report-repair loop.
@@ -178,7 +175,11 @@ Read `review-report.md` and check the Verdict:
178
175
 
179
176
  Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after review and before commit.
180
177
 
181
- Before invoking the skill, create `.prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started` so stale reports are ignored.
178
+ Before invoking the skill, create a current-run marker so stale reports are ignored:
179
+ ```bash
180
+ {{RUNTIME_HELPER_CMD}} artifact ensure-dir .prizmkit/specs/{{FEATURE_SLUG}}
181
+ {{RUNTIME_HELPER_CMD}} artifact touch .prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started
182
+ ```
182
183
 
183
184
  Gate requirements:
184
185
  - Generate or update tests only for this feature's changed files, changed public interfaces, and acceptance criteria.
@@ -208,13 +209,13 @@ You MUST execute this phase. Do NOT skip it.
208
209
 
209
210
  0a. Check if `playwright-cli` is installed:
210
211
  ```bash
211
- which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
212
+ {{RUNTIME_HELPER_CMD}} executable version playwright-cli --arg=--version
212
213
  ```
213
214
  If output is `NOT_INSTALLED`, install it:
214
215
  ```bash
215
216
  npm install -g @playwright/cli@latest
216
217
  ```
217
- Then verify installation succeeded: `playwright-cli --version`. If installation fails, log `## Browser Verification: SKIPPED — playwright-cli installation failed` in context-snapshot.md and proceed to the next phase.
218
+ Then verify installation succeeded: `{{RUNTIME_HELPER_CMD}} executable version playwright-cli --arg=--version`. If installation fails, log `## Browser Verification: SKIPPED — playwright-cli installation failed` in context-snapshot.md and proceed to the next phase.
218
219
 
219
220
  0b. Learn playwright-cli usage (run once per session):
220
221
  ```bash
@@ -223,21 +224,9 @@ playwright-cli --help
223
224
 
224
225
  0c. Check if playwright-cli skill is installed for the current AI platform:
225
226
  ```bash
226
- CURRENT_PLATFORM=""
227
- if which claude >/dev/null 2>&1; then
228
- CURRENT_PLATFORM="claude"; SKILL_DIR="$HOME/.claude/skills"
229
- elif which cbc >/dev/null 2>&1; then
230
- CURRENT_PLATFORM="codebuddy"; SKILL_DIR="$HOME/.cbc/skills"
231
- else
232
- CURRENT_PLATFORM="unknown"
233
- fi
234
- if [ -d "$SKILL_DIR/playwright-cli" ] || ls "$SKILL_DIR"/playwright* 2>/dev/null | grep -q .; then
235
- echo "SKILL_EXISTS"
236
- else
237
- echo "SKILL_MISSING"
238
- fi
227
+ {{RUNTIME_HELPER_CMD}} platform skill playwright-cli --prefix
239
228
  ```
240
- If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform is NOT claude, copy installed skill from `$HOME/.claude/skills/playwright-cli` to `$SKILL_DIR/playwright-cli`.
229
+ If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform is NOT claude, copy installed skill from `$HOME/.claude/skills/playwright-cli` to the path shown by the helper output for the current platform.
241
230
 
242
231
  0d. Read the installed playwright-cli skill (SKILL.md) for workflow guidance. Use its recommended patterns to construct your verification flow.
243
232
 
@@ -246,28 +235,16 @@ If `SKILL_MISSING`: run `playwright-cli install --skills`. If current platform i
246
235
  You know this project's tech stack. Detect and start the dev server yourself:
247
236
 
248
237
  1. Identify the dev server start command from project config (`package.json` scripts, `Makefile`, `docker-compose.yml`, etc.)
249
- 2. **Detect the dev server port** use the pre-detected port from pipeline if available, otherwise extract from project config. Do NOT hardcode or guess the port:
250
- ```bash
251
- DEV_PORT={{DEV_PORT}}
252
- if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
253
- DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')")
254
- if [ -z "$DEV_PORT" ]; then
255
- DEV_PORT=$(echo "$NEXT_PUBLIC_SITE_URL" | sed -nE 's|.*:([0-9]+).*|\1|p')
256
- fi
257
- DEV_PORT=${DEV_PORT:-3000}
258
- fi
259
- echo "Detected DEV_PORT=$DEV_PORT"
260
- ```
238
+ 2. Determine the dev server port from the pre-detected pipeline value (`{{DEV_PORT}}`) or project config. Do NOT hardcode or guess the port. Record it as `DEV_PORT` in your notes.
261
239
  3. Verify the port is available:
262
240
  ```bash
263
- lsof -ti:$DEV_PORT 2>/dev/null && echo "PORT_IN_USE" || echo "PORT_FREE"
241
+ {{RUNTIME_HELPER_CMD}} port check $DEV_PORT
264
242
  ```
265
243
  4. Start the dev server in background, capture PID:
266
244
  ```bash
267
- <start-command> &
268
- DEV_SERVER_PID=$!
245
+ {{RUNTIME_HELPER_CMD}} process start --pid-file .prizmkit/state/browser-dev-server.pid -- <start-command tokens>
269
246
  ```
270
- 5. Wait for server to be ready: poll `http://localhost:$DEV_PORT` with `curl -s -o /dev/null -w "%{http_code}"` until it returns 200 or 302 (max 30 seconds, 2s interval)
247
+ 5. Wait for server to be ready: run `{{RUNTIME_HELPER_CMD}} web wait-ready --url http://localhost:$DEV_PORT --timeout 30 --interval 2`
271
248
  6. Open the app in playwright-cli: `playwright-cli open http://localhost:$DEV_PORT`
272
249
  7. If the page requires authentication, use playwright-cli to register a test user and log in first
273
250
 
@@ -281,8 +258,8 @@ Construct your verification workflow based on: (1) the playwright-cli skill docu
281
258
  **Step 3 — Cleanup (REQUIRED — you started it, you stop it)**:
282
259
 
283
260
  1. Close the playwright-cli browser: `playwright-cli close`
284
- 2. Kill the dev server process: `kill $DEV_SERVER_PID 2>/dev/null || true`
285
- 3. Verify port is released: `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
261
+ 2. Kill the dev server process: `{{RUNTIME_HELPER_CMD}} process cleanup-pid <pid-from-.prizmkit/state/browser-dev-server.pid>`
262
+ 3. Verify port is released: `{{RUNTIME_HELPER_CMD}} process cleanup-port $DEV_PORT`
286
263
  {{END_IF_BROWSER_TOOL_PLAYWRIGHT}}
287
264
  {{IF_BROWSER_TOOL_OPENCLI}}
288
265
  **Using: opencli** (reuses Chrome logged-in sessions)
@@ -295,45 +272,42 @@ Construct your verification workflow based on: (1) the playwright-cli skill docu
295
272
 
296
273
  0a. Check if `opencli` is installed:
297
274
  ```bash
298
- which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
275
+ {{RUNTIME_HELPER_CMD}} executable version opencli --arg=--version
299
276
  ```
300
277
  If `NOT_INSTALLED`: `npm install -g @jackwener/opencli@latest`. If installation fails, log `## Browser Verification: SKIPPED — opencli installation failed` and proceed.
301
278
 
302
279
  0b. Verify Browser Bridge: `opencli doctor`. If fails, log skip and proceed.
303
280
 
304
- 0c. Learn usage: `opencli browser --help 2>/dev/null || opencli --help`
281
+ 0c. Learn usage: `opencli browser --help`
305
282
 
306
- **Step 1 — Start Dev Server**: (same port detection as playwright path)
307
- ```bash
308
- DEV_PORT={{DEV_PORT}}
309
- if [ "$DEV_PORT" = "{{DEV_PORT}}" ]; then
310
- DEV_PORT=$(node -e "const s=require('./package.json').scripts.dev; const m=s.match(/-p\s+(\d+)/); console.log(m?m[1]:'')" 2>/dev/null)
311
- DEV_PORT=${DEV_PORT:-3000}
312
- fi
313
- ```
314
- Start server, wait for ready, then: `opencli browser open http://localhost:$DEV_PORT && opencli browser state`
283
+ **Step 1 — Start Dev Server**:
284
+ 1. Determine `DEV_PORT` from the pipeline value (`{{DEV_PORT}}`) or project config; do not guess.
285
+ 2. Verify port available: `{{RUNTIME_HELPER_CMD}} port check <DEV_PORT>`
286
+ 3. Start server: `{{RUNTIME_HELPER_CMD}} process start --pid-file .prizmkit/state/browser-dev-server.pid -- <start-command tokens>`
287
+ 4. Wait for ready: `{{RUNTIME_HELPER_CMD}} web wait-ready --url http://localhost:<DEV_PORT> --timeout 30 --interval 2`
288
+ 5. Open: `opencli browser open http://localhost:<DEV_PORT>`; then inspect: `opencli browser state`
315
289
 
316
290
  **Step 2 — Verification**:
317
291
 
318
292
  Use `opencli browser state` to discover elements with `[N]` indices, then verify:
319
293
  {{BROWSER_VERIFY_STEPS}}
320
294
 
321
- Chain commands: `opencli browser click <N> && opencli browser wait time 1 && opencli browser state`
295
+ Run page-changing commands sequentially, then run `opencli browser state` to refresh indices.
322
296
 
323
297
  **Step 3 — Cleanup**:
324
298
  1. `opencli browser close`
325
- 2. `kill $DEV_SERVER_PID 2>/dev/null || true`
326
- 3. `lsof -ti:$DEV_PORT | xargs kill -9 2>/dev/null || true`
299
+ 2. `{{RUNTIME_HELPER_CMD}} process cleanup-pid <pid-from-.prizmkit/state/browser-dev-server.pid>`
300
+ 3. `{{RUNTIME_HELPER_CMD}} process cleanup-port $DEV_PORT`
327
301
  {{END_IF_BROWSER_TOOL_OPENCLI}}
328
302
  {{IF_BROWSER_TOOL_AUTO}}
329
303
  **Tool Selection**: Choose the best browser tool at runtime.
330
304
 
331
305
  **Step 0 — Detect available tools**:
332
306
  ```bash
333
- echo "=== playwright-cli ===" && which playwright-cli 2>/dev/null && playwright-cli --version 2>/dev/null || echo "NOT_INSTALLED"
334
- echo "=== opencli ===" && which opencli 2>/dev/null && opencli --version 2>/dev/null || echo "NOT_INSTALLED"
307
+ {{RUNTIME_HELPER_CMD}} executable version playwright-cli --arg=--version
308
+ {{RUNTIME_HELPER_CMD}} executable version opencli --arg=--version
335
309
  ```
336
- If opencli installed: `opencli doctor 2>/dev/null || echo "OPENCLI_BRIDGE_FAILED"`
310
+ If opencli is installed, run `opencli doctor`. If it fails, mark OpenCLI unusable and choose playwright-cli or skip browser verification.
337
311
 
338
312
  **Decision table**:
339
313
  | Condition | Tool |