prizmkit 1.1.101 → 1.1.104
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/prizmkit_runtime/daemon.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +14 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +9 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +5 -1
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +62 -4
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +13 -13
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +1 -1
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +6 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +7 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +8 -17
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +1 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +1 -3
- package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +3 -8
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +2 -2
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +1 -1
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +11 -7
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +107 -11
- package/bundled/dev-pipeline/tests/test_unified_cli.py +76 -0
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
- package/src/config.js +9 -7
- package/src/external-skills.js +14 -14
- package/src/manifest.js +8 -3
- package/src/platforms.js +25 -0
- package/src/scaffold.js +11 -6
- package/src/upgrade.js +11 -2
package/bundled/VERSION.json
CHANGED
|
@@ -320,7 +320,7 @@ def _payload_command(family: RunnerFamily, paths, list_path: Path, options: Daem
|
|
|
320
320
|
|
|
321
321
|
|
|
322
322
|
def _daemon_env(options: DaemonStartOptions) -> dict[str, str]:
|
|
323
|
-
env: dict[str, str] = {}
|
|
323
|
+
env: dict[str, str] = {"PRIZMKIT_LIVE_OUTPUT": "0"}
|
|
324
324
|
for token in shlex.split(options.env_overrides):
|
|
325
325
|
if "=" in token:
|
|
326
326
|
key, value = token.split("=", 1)
|
|
@@ -37,14 +37,16 @@ class RunnerEnvironment:
|
|
|
37
37
|
|
|
38
38
|
stop_on_failure: bool = False
|
|
39
39
|
auto_push: bool = False
|
|
40
|
-
use_worktree: bool =
|
|
40
|
+
use_worktree: bool = False
|
|
41
41
|
dev_branch: str = ""
|
|
42
42
|
enable_deploy: bool = False
|
|
43
43
|
verbose: bool = False
|
|
44
|
+
live_output: bool = True
|
|
44
45
|
heartbeat_interval_seconds: int = 30
|
|
45
46
|
heartbeat_stale_threshold_seconds: int = 600
|
|
46
47
|
stale_kill_threshold_seconds: int = 600
|
|
47
48
|
max_log_size: int | None = None
|
|
49
|
+
max_retries: int = 3
|
|
48
50
|
strict_behavior_check: bool = True
|
|
49
51
|
|
|
50
52
|
@classmethod
|
|
@@ -53,10 +55,11 @@ class RunnerEnvironment:
|
|
|
53
55
|
return cls(
|
|
54
56
|
stop_on_failure=_truthy(values.get("STOP_ON_FAILURE")),
|
|
55
57
|
auto_push=_truthy(values.get("AUTO_PUSH")),
|
|
56
|
-
use_worktree=
|
|
58
|
+
use_worktree=_truthy(values.get("USE_WORKTREE")),
|
|
57
59
|
dev_branch=values.get("DEV_BRANCH", ""),
|
|
58
60
|
enable_deploy=_truthy(values.get("ENABLE_DEPLOY")),
|
|
59
61
|
verbose=_truthy(values.get("VERBOSE")),
|
|
62
|
+
live_output=not _falsey(values.get("PRIZMKIT_LIVE_OUTPUT")),
|
|
60
63
|
heartbeat_interval_seconds=_int_value(values, "HEARTBEAT_INTERVAL", 30),
|
|
61
64
|
heartbeat_stale_threshold_seconds=_int_value(
|
|
62
65
|
values,
|
|
@@ -65,6 +68,7 @@ class RunnerEnvironment:
|
|
|
65
68
|
),
|
|
66
69
|
stale_kill_threshold_seconds=_int_value(values, "STALE_KILL_THRESHOLD", 600),
|
|
67
70
|
max_log_size=_optional_int(values.get("MAX_LOG_SIZE")),
|
|
71
|
+
max_retries=max(0, _int_value(values, "MAX_RETRIES", 3)),
|
|
68
72
|
strict_behavior_check=not _falsey(values.get("STRICT_BEHAVIOR_CHECK")),
|
|
69
73
|
)
|
|
70
74
|
|
|
@@ -77,6 +81,7 @@ class RunnerInvocation:
|
|
|
77
81
|
list_path: Path
|
|
78
82
|
item_id: str = ""
|
|
79
83
|
item_filter: str = ""
|
|
84
|
+
max_retries: int | None = None
|
|
80
85
|
max_infra_retries: int = 3
|
|
81
86
|
mode: str | None = None
|
|
82
87
|
critic: bool | None = None
|
|
@@ -228,6 +233,7 @@ def parse_invocation(
|
|
|
228
233
|
list_path = family.plan_path
|
|
229
234
|
item_id = ""
|
|
230
235
|
item_filter = ""
|
|
236
|
+
max_retries: int | None = None
|
|
231
237
|
max_infra_retries = 3
|
|
232
238
|
mode: str | None = None
|
|
233
239
|
critic: bool | None = None
|
|
@@ -259,6 +265,11 @@ def parse_invocation(
|
|
|
259
265
|
item_filter = args[index]
|
|
260
266
|
elif arg.startswith("--features="):
|
|
261
267
|
item_filter = arg.split("=", 1)[1]
|
|
268
|
+
elif arg == "--max-retries" and index + 1 < len(args):
|
|
269
|
+
index += 1
|
|
270
|
+
max_retries = max(0, _safe_int(args[index], 3))
|
|
271
|
+
elif arg.startswith("--max-retries="):
|
|
272
|
+
max_retries = max(0, _safe_int(arg.split("=", 1)[1], 3))
|
|
262
273
|
elif arg == "--max-infra-retries" and index + 1 < len(args):
|
|
263
274
|
index += 1
|
|
264
275
|
max_infra_retries = _safe_int(args[index], 3)
|
|
@@ -293,6 +304,7 @@ def parse_invocation(
|
|
|
293
304
|
list_path=list_path,
|
|
294
305
|
item_id=item_id,
|
|
295
306
|
item_filter=item_filter,
|
|
307
|
+
max_retries=max_retries,
|
|
296
308
|
max_infra_retries=max_infra_retries,
|
|
297
309
|
mode=mode,
|
|
298
310
|
critic=critic,
|
|
@@ -8,7 +8,7 @@ import sys
|
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
|
-
from .runner_models import RunnerFamily, RunnerInvocation
|
|
11
|
+
from .runner_models import RunnerEnvironment, RunnerFamily, RunnerInvocation
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@dataclass(frozen=True)
|
|
@@ -30,6 +30,12 @@ class StatusCommandResult:
|
|
|
30
30
|
return self.stdout.strip() or self.stderr.strip()
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
def _resolved_max_retries(invocation: RunnerInvocation) -> int:
|
|
34
|
+
if invocation.max_retries is not None:
|
|
35
|
+
return max(0, invocation.max_retries)
|
|
36
|
+
return RunnerEnvironment.from_env().max_retries
|
|
37
|
+
|
|
38
|
+
|
|
33
39
|
def run_status_action(
|
|
34
40
|
family: RunnerFamily,
|
|
35
41
|
action: str,
|
|
@@ -38,7 +44,7 @@ def run_status_action(
|
|
|
38
44
|
item_id: str = "",
|
|
39
45
|
session_status: str = "",
|
|
40
46
|
session_id: str = "",
|
|
41
|
-
max_retries: int =
|
|
47
|
+
max_retries: int | None = None,
|
|
42
48
|
active_dev_branch: str = "",
|
|
43
49
|
base_branch: str = "",
|
|
44
50
|
last_fatal_error_code: str = "",
|
|
@@ -47,7 +53,7 @@ def run_status_action(
|
|
|
47
53
|
progress_fingerprint: object | None = None,
|
|
48
54
|
project_root: Path | None = None,
|
|
49
55
|
) -> StatusCommandResult:
|
|
50
|
-
|
|
56
|
+
max_retries = _resolved_max_retries(invocation) if max_retries is None else max(0, max_retries)
|
|
51
57
|
command = [
|
|
52
58
|
sys.executable,
|
|
53
59
|
str(family.updater_script),
|
|
@@ -114,6 +114,8 @@ def _run_pipeline(family: RunnerFamily, invocation: RunnerInvocation, paths) ->
|
|
|
114
114
|
details.append(f"{item_id}:{final_status}")
|
|
115
115
|
if final_status == "completed":
|
|
116
116
|
continue
|
|
117
|
+
if final_status == "pending":
|
|
118
|
+
continue
|
|
117
119
|
if RunnerEnvironment.from_env().stop_on_failure:
|
|
118
120
|
return PipelineRunResult(False, processed, "stop_on_failure", final_status, tuple(details))
|
|
119
121
|
if final_status in {"failed", "needs_info"}:
|
|
@@ -218,6 +220,7 @@ def _process_item(
|
|
|
218
220
|
heartbeat_path=session_paths.heartbeat_json,
|
|
219
221
|
effort=config.effort,
|
|
220
222
|
verbose=env.verbose,
|
|
223
|
+
live_output=env.live_output,
|
|
221
224
|
use_stream_json=stream_json,
|
|
222
225
|
stale_kill_threshold_seconds=env.stale_kill_threshold_seconds,
|
|
223
226
|
)
|
|
@@ -401,6 +404,7 @@ def _resolve_invocation_paths(invocation: RunnerInvocation, project_root: Path)
|
|
|
401
404
|
list_path=(project_root / invocation.list_path).resolve(),
|
|
402
405
|
item_id=invocation.item_id,
|
|
403
406
|
item_filter=invocation.item_filter,
|
|
407
|
+
max_retries=invocation.max_retries,
|
|
404
408
|
max_infra_retries=invocation.max_infra_retries,
|
|
405
409
|
mode=invocation.mode,
|
|
406
410
|
critic=invocation.critic,
|
|
@@ -418,5 +422,5 @@ def _help_text(family: RunnerFamily) -> str:
|
|
|
418
422
|
return (
|
|
419
423
|
f"Python foreground runner for {family.kind}.\n"
|
|
420
424
|
"Supported legacy options include plan list path, item id, --features for feature, "
|
|
421
|
-
"--max-infra-retries, --mode, --critic/--no-critic, --resume-phase, and --dry-run."
|
|
425
|
+
"--max-retries, --max-infra-retries, --mode, --critic/--no-critic, --resume-phase, and --dry-run."
|
|
422
426
|
)
|
|
@@ -8,6 +8,7 @@ import os
|
|
|
8
8
|
import queue
|
|
9
9
|
import shutil
|
|
10
10
|
import subprocess
|
|
11
|
+
import sys
|
|
11
12
|
import threading
|
|
12
13
|
import time
|
|
13
14
|
from collections import Counter
|
|
@@ -45,6 +46,7 @@ class AISessionConfig:
|
|
|
45
46
|
heartbeat_path: Path | None = None
|
|
46
47
|
effort: str | None = None
|
|
47
48
|
verbose: bool = False
|
|
49
|
+
live_output: bool = False
|
|
48
50
|
use_stream_json: bool = False
|
|
49
51
|
stream_json_format: str = ""
|
|
50
52
|
permission_mode: str = "dangerously-skip-permissions"
|
|
@@ -152,7 +154,14 @@ def build_ai_session_command(config: AISessionConfig) -> AISessionCommand:
|
|
|
152
154
|
platform = _normalize_platform(config.platform)
|
|
153
155
|
prompt = _prompt_text(config.prompt_path)
|
|
154
156
|
if platform == "claude":
|
|
155
|
-
argv = [
|
|
157
|
+
argv = [
|
|
158
|
+
config.cli_command,
|
|
159
|
+
"-p",
|
|
160
|
+
prompt,
|
|
161
|
+
"--dangerously-skip-permissions",
|
|
162
|
+
"--disallowedTools",
|
|
163
|
+
"EnterWorktree",
|
|
164
|
+
]
|
|
156
165
|
if config.verbose or config.use_stream_json:
|
|
157
166
|
argv.append("--verbose")
|
|
158
167
|
if config.use_stream_json:
|
|
@@ -175,6 +184,7 @@ def build_ai_session_command(config: AISessionConfig) -> AISessionCommand:
|
|
|
175
184
|
timeout = _codex_subagent_timeout(config)
|
|
176
185
|
if timeout > 0:
|
|
177
186
|
argv.extend(["--config", f"agents.job_max_runtime_seconds={timeout}"])
|
|
187
|
+
argv.extend(["--profile", "no-worktree"])
|
|
178
188
|
argv.extend(["exec", "--cd", str(config.cwd), "--skip-git-repo-check"])
|
|
179
189
|
if config.use_stream_json:
|
|
180
190
|
argv.append("--json")
|
|
@@ -186,7 +196,7 @@ def build_ai_session_command(config: AISessionConfig) -> AISessionCommand:
|
|
|
186
196
|
argv.append("-")
|
|
187
197
|
return AISessionCommand(tuple(argv), prompt, "codex", "stdin")
|
|
188
198
|
|
|
189
|
-
argv = [config.cli_command, "--print", "-y"]
|
|
199
|
+
argv = [config.cli_command, "--print", "-y", "--disallowedTools", "EnterWorktree"]
|
|
190
200
|
if config.verbose:
|
|
191
201
|
argv.append("--verbose")
|
|
192
202
|
if config.use_stream_json:
|
|
@@ -355,12 +365,45 @@ def _write_progress_summary(progress_path: Path | None, summary: ProgressSummary
|
|
|
355
365
|
progress_path.write_text(json.dumps(summary.to_dict(), indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
356
366
|
|
|
357
367
|
|
|
368
|
+
def _emit_live_line(message: str) -> None:
|
|
369
|
+
"""Print foreground runner status without interfering with file logging."""
|
|
370
|
+
print(message, file=sys.stderr, flush=True)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def _emit_live_output(line: str) -> None:
|
|
374
|
+
"""Forward AI CLI output for verbose foreground runs."""
|
|
375
|
+
sys.stdout.write(line)
|
|
376
|
+
sys.stdout.flush()
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _emit_session_start(config: AISessionConfig, command: AISessionCommand, session_log: Path, backup_log: Path) -> None:
|
|
380
|
+
_emit_live_line("[prizmkit] AI session started")
|
|
381
|
+
_emit_live_line(f"[prizmkit] Provider: {command.provider}")
|
|
382
|
+
_emit_live_line(f"[prizmkit] Prompt: {config.prompt_path}")
|
|
383
|
+
_emit_live_line(f"[prizmkit] Session log: {session_log}")
|
|
384
|
+
_emit_live_line(f"[prizmkit] Backup log: {backup_log}")
|
|
385
|
+
if config.progress_path is not None:
|
|
386
|
+
_emit_live_line(f"[prizmkit] Progress: {config.progress_path}")
|
|
387
|
+
if config.heartbeat_path is not None:
|
|
388
|
+
_emit_live_line(f"[prizmkit] Heartbeat: {config.heartbeat_path}")
|
|
389
|
+
if config.verbose:
|
|
390
|
+
_emit_live_line("[prizmkit] VERBOSE=1: forwarding live AI CLI output below")
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _emit_session_finish(result: AISessionResult) -> None:
|
|
394
|
+
duration = max(0.0, result.ended_epoch - result.started_epoch)
|
|
395
|
+
status = result.termination_reason or f"exit_code={result.exit_code}"
|
|
396
|
+
_emit_live_line(f"[prizmkit] AI session finished ({status}, {duration:.1f}s)")
|
|
397
|
+
_emit_live_line(f"[prizmkit] Session log: {result.session_log}")
|
|
398
|
+
|
|
399
|
+
|
|
358
400
|
def _reader_thread(
|
|
359
401
|
pipe,
|
|
360
402
|
session_log: Path,
|
|
361
403
|
backup_log: Path,
|
|
362
404
|
output_queue: "queue.Queue[str]",
|
|
363
405
|
progress_path: Path | None = None,
|
|
406
|
+
live_output: bool = False,
|
|
364
407
|
) -> None:
|
|
365
408
|
lines: list[str] = []
|
|
366
409
|
tracker = None
|
|
@@ -379,6 +422,8 @@ def _reader_thread(
|
|
|
379
422
|
with backup_log.open("a", encoding="utf-8") as backup_fh:
|
|
380
423
|
backup_fh.write(line)
|
|
381
424
|
output_queue.put(line)
|
|
425
|
+
if live_output:
|
|
426
|
+
_emit_live_output(line)
|
|
382
427
|
lines.append(line)
|
|
383
428
|
if progress_path is not None:
|
|
384
429
|
if tracker is not None:
|
|
@@ -464,12 +509,22 @@ class AISessionLauncher:
|
|
|
464
509
|
environment_unsets=("CLAUDECODE",),
|
|
465
510
|
stdin_text=command.stdin_text,
|
|
466
511
|
)
|
|
512
|
+
if self.config.live_output:
|
|
513
|
+
_emit_session_start(self.config, command, session_log, backup_log)
|
|
514
|
+
|
|
467
515
|
handle = launch_process(spec, stderr=subprocess.STDOUT)
|
|
468
516
|
assert handle.popen is not None
|
|
469
517
|
output_queue: queue.Queue[str] = queue.Queue()
|
|
470
518
|
reader = threading.Thread(
|
|
471
519
|
target=_reader_thread,
|
|
472
|
-
args=(
|
|
520
|
+
args=(
|
|
521
|
+
handle.popen.stdout,
|
|
522
|
+
session_log,
|
|
523
|
+
backup_log,
|
|
524
|
+
output_queue,
|
|
525
|
+
self.config.progress_path,
|
|
526
|
+
self.config.live_output and self.config.verbose,
|
|
527
|
+
),
|
|
473
528
|
daemon=True,
|
|
474
529
|
)
|
|
475
530
|
reader.start()
|
|
@@ -536,7 +591,7 @@ class AISessionLauncher:
|
|
|
536
591
|
self.config.progress_path.write_text(json.dumps(merged_progress, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
537
592
|
final_summary = _summary_from_progress_dict(merged_progress, summary)
|
|
538
593
|
ended = time.time()
|
|
539
|
-
|
|
594
|
+
result = AISessionResult(
|
|
540
595
|
command=command,
|
|
541
596
|
exit_code=handle.popen.returncode,
|
|
542
597
|
timed_out=timed_out,
|
|
@@ -550,3 +605,6 @@ class AISessionLauncher:
|
|
|
550
605
|
started_epoch=started,
|
|
551
606
|
ended_epoch=ended,
|
|
552
607
|
)
|
|
608
|
+
if self.config.live_output:
|
|
609
|
+
_emit_session_finish(result)
|
|
610
|
+
return result
|
|
@@ -676,7 +676,7 @@ def determine_pipeline_mode(complexity):
|
|
|
676
676
|
SECTION_TO_SKILL = {
|
|
677
677
|
"phase0-init": ("prizmkit-init", "Project Bootstrap",
|
|
678
678
|
[".prizmkit/prizm-docs/root.prizm", ".prizmkit/config.json"]),
|
|
679
|
-
"phase0-test-baseline": ("test-baseline", "Test
|
|
679
|
+
"phase0-test-baseline": ("test-baseline", "Detect Test Commands", []),
|
|
680
680
|
"phase-context-snapshot": ("context-snapshot", "Build Context Snapshot",
|
|
681
681
|
[".prizmkit/specs/{slug}/context-snapshot.md"]),
|
|
682
682
|
"phase-specify-plan": ("context-snapshot-and-plan", "Specify & Plan",
|
|
@@ -1559,6 +1559,18 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
|
|
|
1559
1559
|
load_section(sections_dir,
|
|
1560
1560
|
"phase-implement-agent.md")))
|
|
1561
1561
|
|
|
1562
|
+
# Verification Gates are included in Task Contract. Keep AC in one place so
|
|
1563
|
+
# background context and implementation prompts cannot redefine scope.
|
|
1564
|
+
# --- Review ---
|
|
1565
|
+
if pipeline_mode == "full":
|
|
1566
|
+
sections.append(("phase-review",
|
|
1567
|
+
load_section(sections_dir,
|
|
1568
|
+
"phase-review-full.md")))
|
|
1569
|
+
else:
|
|
1570
|
+
sections.append(("phase-review",
|
|
1571
|
+
load_section(sections_dir,
|
|
1572
|
+
"phase-review-agent.md")))
|
|
1573
|
+
|
|
1562
1574
|
# --- Test Failure Recovery Protocol (tier-specific) ---
|
|
1563
1575
|
if pipeline_mode == "lite":
|
|
1564
1576
|
sections.append(("test-failure-recovery",
|
|
@@ -1574,18 +1586,6 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
|
|
|
1574
1586
|
load_section(sections_dir,
|
|
1575
1587
|
"phase-prizmkit-test.md")))
|
|
1576
1588
|
|
|
1577
|
-
# Verification Gates are included in Task Contract. Keep AC in one place so
|
|
1578
|
-
# background context and implementation prompts cannot redefine scope.
|
|
1579
|
-
# --- Review (only for agent tiers) ---
|
|
1580
|
-
if pipeline_mode == "full":
|
|
1581
|
-
sections.append(("phase-review",
|
|
1582
|
-
load_section(sections_dir,
|
|
1583
|
-
"phase-review-full.md")))
|
|
1584
|
-
elif pipeline_mode == "standard":
|
|
1585
|
-
sections.append(("phase-review",
|
|
1586
|
-
load_section(sections_dir,
|
|
1587
|
-
"phase-review-agent.md")))
|
|
1588
|
-
|
|
1589
1589
|
# --- Browser Verification (conditional, tool-aware) ---
|
|
1590
1590
|
if browser_enabled:
|
|
1591
1591
|
if browser_tool == "opencli":
|
|
@@ -61,7 +61,7 @@ Before returning, append `## Implementation Log` to `context-snapshot.md` with:
|
|
|
61
61
|
- Do not run git commands; staging and commit are handled by the orchestrator.
|
|
62
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
63
|
- **Read safety**: If 3 consecutive Reads to the same file return 'shorter than offset' or 'Wasted call', STOP and report BLOCKED.
|
|
64
|
-
- **Test
|
|
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
65
|
|
|
66
66
|
Do not return success unless:
|
|
67
67
|
1. implementation tasks are complete;
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` (if it exists) for goals and Verification Gates; if spec.md does not exist, read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` Section 1 Task Contract instead
|
|
3
3
|
2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
|
|
4
4
|
3. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/. The skill will run its internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and write review-report.md.
|
|
5
|
-
4.
|
|
5
|
+
4. Do not run test suites here. The orchestrator runs `/prizmkit-test` after review completes and then fixes code/tests until the scoped gate passes.
|
|
6
6
|
5. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
|
|
7
7
|
Report: verdict (PASS/NEEDS_FIXES), number of rounds, findings fixed/rejected."
|
|
@@ -30,9 +30,9 @@ Infer what needs to be done from the feature context above and follow the standa
|
|
|
30
30
|
|
|
31
31
|
3. **Implement**: Run `/prizmkit-implement` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to execute the plan using TDD (write tests first, then implement).
|
|
32
32
|
|
|
33
|
-
4. **
|
|
33
|
+
4. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to review and auto-fix changes against the spec (internal review-fix loop, max 3 rounds).
|
|
34
34
|
|
|
35
|
-
5. **
|
|
35
|
+
5. **Test**: Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to generate and verify tests only for this feature's changed scope after review. Do not use bugfix/refactor artifact directories for this gate.
|
|
36
36
|
|
|
37
37
|
6. **Retrospective**: Run `/prizmkit-retrospective` to sync `.prizmkit/prizm-docs/` with code changes.
|
|
38
38
|
|
|
@@ -145,9 +145,9 @@ You know this project's tech stack. Identify ALL test commands that apply (e.g.,
|
|
|
145
145
|
**3b.** Run `/prizmkit-implement` — this handles the full implementation cycle:
|
|
146
146
|
- Reads plan.md Tasks section from `.prizmkit/specs/{{FEATURE_SLUG}}/`
|
|
147
147
|
- Reads context from `context-snapshot.md` (Prizm docs, TRAPS, file manifest)
|
|
148
|
-
- Implements task-by-task
|
|
148
|
+
- Implements task-by-task, marking each `[x]` immediately
|
|
149
149
|
- Creates/updates L2 `.prizm` docs when creating new modules or significantly modifying existing ones — AI selectively decides which modules warrant L2 based on complexity and importance
|
|
150
|
-
-
|
|
150
|
+
- Defers scoped/full test execution until after review
|
|
151
151
|
- Writes '## Implementation Log' to `context-snapshot.md`
|
|
152
152
|
|
|
153
153
|
**3b-checkpoint.** Context management — if plan.md has more than 5 tasks, update durable checkpoints/artifacts after every 3 tasks, minimize output, and continue. If context overflow occurs in a headless run, the runner starts a fresh continuation session from those checkpoints and artifacts. In an interactive Claude Code session operated manually outside the headless pipeline, `/compact` may be used as an optional convenience only.
|
|
@@ -155,10 +155,9 @@ You know this project's tech stack. Identify ALL test commands that apply (e.g.,
|
|
|
155
155
|
**3c.** After implement completes, verify:
|
|
156
156
|
1. All tasks in plan.md are `[x]`
|
|
157
157
|
2. **Verification Gate Self-Check**: for each acceptance criterion, write one line of evidence (test name / file:line / fixture path). Any gate without evidence is BLOCKED, not success.
|
|
158
|
-
3. **Layered test strategy**:
|
|
159
|
-
4.
|
|
160
|
-
5.
|
|
161
|
-
6. If any criterion is not met, fix it now using the convergence-based recovery loop below
|
|
158
|
+
3. **Layered test strategy**: do not run mandatory periodic/full-suite tests during implementation. Use only tiny targeted checks when needed for local debugging; the scoped feature test gate runs after review.
|
|
159
|
+
4. Verify each acceptance criterion from Section 1 of context-snapshot.md is met — check mentally, do NOT re-read files you already wrote
|
|
160
|
+
5. If any criterion is not met, fix it now using the convergence-based recovery loop below
|
|
162
161
|
|
|
163
162
|
**CP-2**: All acceptance criteria met, all tests pass.
|
|
164
163
|
|
|
@@ -177,7 +176,7 @@ When tests fail, use convergence recovery — keep fixing while progress is bein
|
|
|
177
176
|
|
|
178
177
|
### Scoped Feature Test Gate — PrizmKit Test
|
|
179
178
|
|
|
180
|
-
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after
|
|
179
|
+
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after review and before commit.
|
|
181
180
|
|
|
182
181
|
Before invoking the skill, create `.prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started` so stale reports are ignored.
|
|
183
182
|
|
|
@@ -302,7 +302,7 @@ If GATE:MISSING — send message to Dev (re-spawn if needed): "Write the '## Imp
|
|
|
302
302
|
|
|
303
303
|
### Scoped Feature Test Gate — PrizmKit Test
|
|
304
304
|
|
|
305
|
-
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after
|
|
305
|
+
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after review and before commit.
|
|
306
306
|
|
|
307
307
|
Before invoking the skill, create `.prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started` so stale reports are ignored.
|
|
308
308
|
|
|
@@ -320,7 +320,7 @@ All tasks `[x]`, tests pass.
|
|
|
320
320
|
|
|
321
321
|
### Scoped Feature Test Gate — PrizmKit Test
|
|
322
322
|
|
|
323
|
-
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after
|
|
323
|
+
Run `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` after review and before commit.
|
|
324
324
|
|
|
325
325
|
Before invoking the skill, create `.prizmkit/specs/{{FEATURE_SLUG}}/.prizmkit-test-started` so stale reports are ignored.
|
|
326
326
|
|
|
@@ -19,15 +19,15 @@ grep -c '^\- \[ \]' .prizmkit/specs/{{FEATURE_SLUG}}/plan.md 2>/dev/null || true
|
|
|
19
19
|
**3b.** Run `/prizmkit-implement` directly — you (the orchestrator) execute the full cycle:
|
|
20
20
|
- Read plan.md Tasks from `.prizmkit/specs/{{FEATURE_SLUG}}/`
|
|
21
21
|
- Use context-snapshot.md Section 4 File Manifest for targeted reads — do NOT re-read files already summarized there
|
|
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
25
|
- If plan.md has >5 tasks: update checkpoints after every 3 tasks
|
|
26
26
|
|
|
27
|
-
**3c.
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
27
|
+
**3c. Focused checks only (no test gate here)**:
|
|
28
|
+
- During implementation, do not run mandatory periodic or full-suite tests.
|
|
29
|
+
- If a tiny targeted check is needed to understand a local failure, run only the smallest relevant command and capture output to `/tmp/test-out.txt`.
|
|
30
|
+
- The scoped feature test gate runs after code review; do not declare implementation success based on an early full-suite run.
|
|
31
31
|
|
|
32
32
|
**3d. Verification Gate Self-Check (BLOCKING — before declaring implement done)**:
|
|
33
33
|
For each Verification Gate from the Task Contract, write one evidence line to Implementation Log:
|
|
@@ -45,7 +45,7 @@ For each Verification Gate from the Task Contract, write one evidence line to Im
|
|
|
45
45
|
- Gate Evidence section
|
|
46
46
|
- unresolved blockers
|
|
47
47
|
|
|
48
|
-
**CP-2**: All tasks `[x]`, Implementation Log written with Gate Evidence,
|
|
48
|
+
**CP-2**: All tasks `[x]`, Implementation Log written with Gate Evidence, and blocked gates documented in `failure-log.md`. Test execution is deferred until after code review.
|
|
49
49
|
|
|
50
50
|
**Checkpoint update**:
|
|
51
51
|
```bash
|
|
@@ -20,15 +20,15 @@ Save pre-existing failing tests as `BASELINE_FAILURES`.
|
|
|
20
20
|
**3b.** Run `/prizmkit-implement` directly — you (the orchestrator) execute the full cycle:
|
|
21
21
|
- Read plan.md Tasks from `.prizmkit/specs/{{FEATURE_SLUG}}/`
|
|
22
22
|
- Use context-snapshot.md Section 4 File Manifest for targeted reads — do NOT re-read files already summarized there
|
|
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
26
|
- If plan.md has >5 tasks: update checkpoints after every 3 tasks
|
|
27
27
|
|
|
28
|
-
**3c.
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
28
|
+
**3c. Focused checks only (no test gate here)**:
|
|
29
|
+
- During implementation, do not run mandatory periodic or full-suite tests.
|
|
30
|
+
- If a tiny targeted check is needed to understand a local failure, run only the smallest relevant command and capture output to `/tmp/test-out.txt`.
|
|
31
|
+
- The scoped feature test gate runs after code review; do not declare implementation success based on an early full-suite run.
|
|
32
32
|
|
|
33
33
|
**3d. Verification Gate Self-Check (BLOCKING — before declaring implement done)**:
|
|
34
34
|
For each Verification Gate from the Task Contract, write one evidence line to Implementation Log:
|
|
@@ -46,7 +46,7 @@ For each Verification Gate from the Task Contract, write one evidence line to Im
|
|
|
46
46
|
- Gate Evidence section
|
|
47
47
|
- unresolved blockers
|
|
48
48
|
|
|
49
|
-
**CP-2**: All tasks `[x]`, Implementation Log written with Gate Evidence,
|
|
49
|
+
**CP-2**: All tasks `[x]`, Implementation Log written with Gate Evidence, and blocked gates documented in `failure-log.md`. Test execution is deferred until after code review.
|
|
50
50
|
|
|
51
51
|
**Checkpoint update**:
|
|
52
52
|
```bash
|
|
@@ -1,33 +1,24 @@
|
|
|
1
|
-
### Implement
|
|
1
|
+
### Implement
|
|
2
2
|
|
|
3
3
|
**Protocol references**:
|
|
4
4
|
- Follow Context Budget Rules §8 for scaffold/generated files.
|
|
5
5
|
- Follow Context Budget Rules §9 before package install/build commands that resolve dependencies.
|
|
6
6
|
- Follow Context Budget Rules §10 after build/compile commands.
|
|
7
7
|
|
|
8
|
-
**3a.**
|
|
9
|
-
|
|
10
|
-
You know this project's tech stack. Identify ALL test commands that apply (e.g., `go test ./...`, `npm test`, `cargo test`, `pytest`, `make test`, etc.). Record them as `TEST_CMDS`. Then record baseline:
|
|
11
|
-
```bash
|
|
12
|
-
# Run each test command, capture output
|
|
13
|
-
($TEST_CMD) 2>&1 | tee /tmp/test-baseline.txt | tail -20
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
**3b.** Run `/prizmkit-implement` — this handles the full implementation cycle:
|
|
8
|
+
**3a.** Run `/prizmkit-implement` — this handles the implementation cycle:
|
|
17
9
|
- Reads plan.md Tasks section from `.prizmkit/specs/{{FEATURE_SLUG}}/`
|
|
18
10
|
- Reads context from `context-snapshot.md` (Prizm docs, TRAPS, file manifest)
|
|
19
|
-
- Implements task-by-task
|
|
11
|
+
- Implements task-by-task, marking each `[x]` immediately
|
|
20
12
|
- Creates/updates L2 `.prizm` docs when creating new modules or significantly modifying existing ones — AI selectively decides which modules warrant L2 based on complexity and importance
|
|
21
|
-
-
|
|
13
|
+
- Does not run the scoped/full test gate; testing happens after code review in the PrizmKit Test phase
|
|
22
14
|
- Writes '## Implementation Log' to `context-snapshot.md`
|
|
23
15
|
|
|
24
|
-
**
|
|
16
|
+
**3b.** After implement completes, verify:
|
|
25
17
|
1. All tasks in plan.md are `[x]`
|
|
26
|
-
2.
|
|
27
|
-
3.
|
|
28
|
-
4. If any gate is unmet or blocked, follow the Test Failure Recovery Protocol
|
|
18
|
+
2. Verify each Verification Gate from the Task Contract using code/file evidence already in context — do NOT re-read files you already wrote
|
|
19
|
+
3. If any gate is unmet or blocked, write `failure-log.md` and stop for recovery
|
|
29
20
|
|
|
30
|
-
**CP-2**: Implementation may proceed only when all tasks are `[x]` and
|
|
21
|
+
**CP-2**: Implementation may proceed only when all tasks are `[x]` and blocked gates are documented in `failure-log.md`. Test execution is deferred until after code review.
|
|
31
22
|
|
|
32
23
|
|
|
33
24
|
**Checkpoint update**: Run the update script to set step `prizmkit-implement` to `"completed"`:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
### Scoped Feature Test Gate — PrizmKit Test
|
|
2
2
|
|
|
3
|
-
**Goal**:
|
|
3
|
+
**Goal**: After code review completes, generate and verify tests for this feature's changed scope without embedding the full gate implementation in this prompt.
|
|
4
4
|
|
|
5
5
|
Create a start marker immediately before invoking the skill so the gate can reject stale reports from older sessions:
|
|
6
6
|
|
|
@@ -34,6 +34,6 @@ python3 "$PIPELINE_DIR/scripts/prizmkit-test-gate.py" check \
|
|
|
34
34
|
|
|
35
35
|
Gate outcomes:
|
|
36
36
|
- `GATE:PASS` → append the report path and a 3-5 bullet summary to `context-snapshot.md` under `## PrizmKit Test Gate`, then proceed to the next checkpoint step. The gate script already wrote `test-report-path.txt` and marked `prizmkit-test` completed.
|
|
37
|
-
- `GATE:FAIL` with `NEEDS_FIXES` → read the report's `In-Scope Failures`, fix the feature implementation or generated tests within this feature scope, rerun `/prizmkit-test`, and repeat the gate check. Do not proceed to
|
|
37
|
+
- `GATE:FAIL` with `NEEDS_FIXES` → read the report's `In-Scope Failures`, fix the feature implementation or generated tests within this feature scope, rerun `/prizmkit-test`, and repeat the gate check. Do not proceed to retrospective/commit while the verdict is not `PASS`.
|
|
38
38
|
- `GATE:FAIL` with `BLOCKED`, wrong mode, wrong artifact dir, unreadable report, stale scope, boundary failure, validator failure, or checkpoint update failure → write `.prizmkit/specs/{{FEATURE_SLUG}}/failure-log.md` with the scoped test failure and stop for recovery.
|
|
39
39
|
- `GATE:MISSING` → perform one bounded status check: inspect `/prizmkit-test` output and `.prizmkit/test/` for a report directory. If no current-run report exists, write `failure-log.md` and stop for recovery.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
### Review — Code Review
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Before invoking review, read `.prizmkit/specs/{{FEATURE_SLUG}}/test-report-path.txt`, read the referenced `/prizmkit-test` report, and confirm the summary in `context-snapshot.md` under `## PrizmKit Test Gate` matches it. The code-review skill must receive this context through `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` and the Reviewer must assess generated/updated test quality, `In-Scope Failures`, `Baseline Failures`, `Out of Scope Gaps`, boundary coverage if present, and the scoped report verdict.
|
|
3
|
+
Review the completed implementation before the scoped feature test gate runs. Use `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` so the code-review skill can read spec, plan, context snapshot, implementation log, and current diff artifacts. Do not require or read a prior `/prizmkit-test` report here; test generation and test-fix looping happen in the next phase.
|
|
6
4
|
|
|
7
5
|
Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
8
6
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
### Review — Code Review
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Before invoking review, read `.prizmkit/specs/{{FEATURE_SLUG}}/test-report-path.txt`, read the referenced `/prizmkit-test` report, and confirm the summary in `context-snapshot.md` under `## PrizmKit Test Gate` matches it. The code-review skill must receive this context through `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` and the Reviewer must assess generated/updated test quality, `In-Scope Failures`, `Baseline Failures`, `Out of Scope Gaps`, boundary coverage if present, and the scoped report verdict.
|
|
3
|
+
Review the completed implementation before the scoped feature test gate runs. Use `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` so the code-review skill can read spec, plan, context snapshot, implementation log, and current diff artifacts. Do not require or read a prior `/prizmkit-test` report here; test generation and test-fix looping happen in the next phase.
|
|
6
4
|
|
|
7
5
|
Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
8
6
|
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
### Phase 0:
|
|
1
|
+
### Phase 0: Detect Test Commands
|
|
2
2
|
|
|
3
3
|
**Step 1 — Detect test commands**: You know this project's tech stack. Identify ALL test commands that apply (e.g., `go test ./...`, `npm test`, `cargo test`, `pytest`, `make test`, etc.). Record them as `TEST_CMDS`.
|
|
4
4
|
|
|
5
|
-
**Step 2 —
|
|
6
|
-
```bash
|
|
7
|
-
# Run each test command, capture output
|
|
8
|
-
($TEST_CMD) 2>&1 | tee /tmp/test-baseline.txt | tail -20
|
|
9
|
-
```
|
|
10
|
-
Save the list of **pre-existing failing tests** (if any) as `BASELINE_FAILURES`. These are known failures that existed before this session — Dev must NOT be blamed for them, but must list them in COMPLETION_SIGNAL.
|
|
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.
|
|
11
6
|
|
|
12
|
-
> **Test Output Rule**:
|
|
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.
|
|
13
8
|
|
|
14
9
|
|
|
15
10
|
**Checkpoint update**: Run the update script to set step `test-baseline` to `"completed"`:
|