prizmkit 1.1.114 → 1.1.116

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 (77) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/.env.example +0 -1
  3. package/bundled/dev-pipeline/README.md +4 -6
  4. package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +40 -518
  5. package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +27 -99
  6. package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +283 -0
  7. package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +3 -13
  8. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +2 -0
  9. package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +0 -1
  10. package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +14 -2
  11. package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +25 -31
  12. package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -8
  13. package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +0 -3
  14. package/bundled/dev-pipeline/prizmkit_runtime/runners.py +13 -7
  15. package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +13 -1
  16. package/bundled/dev-pipeline/scripts/continuation.py +8 -40
  17. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +76 -261
  18. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +16 -35
  19. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +15 -34
  20. package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +6 -0
  21. package/bundled/dev-pipeline/scripts/init-pipeline.py +6 -0
  22. package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +6 -0
  23. package/bundled/dev-pipeline/scripts/parse-stream-progress.py +1 -1
  24. package/bundled/dev-pipeline/scripts/prompt_framework.py +114 -63
  25. package/bundled/dev-pipeline/scripts/update-bug-status.py +3 -7
  26. package/bundled/dev-pipeline/scripts/update-checkpoint.py +54 -22
  27. package/bundled/dev-pipeline/scripts/update-feature-status.py +3 -7
  28. package/bundled/dev-pipeline/scripts/update-refactor-status.py +3 -7
  29. package/bundled/dev-pipeline/scripts/utils.py +6 -37
  30. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
  31. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +1 -1
  32. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +9 -91
  33. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +9 -66
  34. package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +10 -16
  35. package/bundled/dev-pipeline/templates/feature-list-schema.json +32 -17
  36. package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +0 -16
  37. package/bundled/dev-pipeline/templates/refactor-list-schema.json +10 -16
  38. package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +1 -1
  39. package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
  40. package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
  41. package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -1
  42. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +1 -1
  43. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +1 -1
  44. package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +1 -1
  45. package/bundled/dev-pipeline/tests/conftest.py +1 -0
  46. package/bundled/dev-pipeline/tests/test_checkpoint_state.py +164 -0
  47. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +48 -76
  48. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +25 -3
  49. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +25 -5
  50. package/bundled/dev-pipeline/tests/test_python_runner_parity.py +329 -16
  51. package/bundled/dev-pipeline/tests/test_unified_cli.py +40 -9
  52. package/bundled/skills/_metadata.json +1 -1
  53. package/bundled/skills/bug-planner/SKILL.md +5 -4
  54. package/bundled/skills/bug-planner/references/verification.md +29 -0
  55. package/bundled/skills/bug-planner/scripts/validate-bug-list.py +8 -0
  56. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +2 -2
  57. package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +1 -6
  58. package/bundled/skills/feature-pipeline-launcher/SKILL.md +6 -12
  59. package/bundled/skills/feature-pipeline-launcher/references/configuration.md +0 -1
  60. package/bundled/skills/feature-planner/SKILL.md +13 -12
  61. package/bundled/skills/feature-planner/assets/planning-guide.md +2 -2
  62. package/bundled/skills/feature-planner/scripts/validate-and-generate.py +8 -11
  63. package/bundled/skills/prizmkit-plan/SKILL.md +15 -1
  64. package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +101 -0
  65. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +5 -5
  66. package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +2 -7
  67. package/bundled/skills/refactor-planner/SKILL.md +10 -8
  68. package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +9 -0
  69. package/bundled/team/prizm-dev-team.json +2 -9
  70. package/package.json +1 -1
  71. package/bundled/agents/prizm-dev-team-critic.md +0 -179
  72. package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +0 -8
  73. package/bundled/dev-pipeline/templates/sections/bugfix-phase-critic.md +0 -22
  74. package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +0 -61
  75. package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +0 -38
  76. package/bundled/dev-pipeline/templates/sections/refactor-phase-critic.md +0 -22
  77. package/bundled/skills/bug-planner/references/critic-and-verification.md +0 -44
@@ -82,7 +82,6 @@ class RunnerInvocation:
82
82
  max_retries: int | None = None
83
83
  max_infra_retries: int = 3
84
84
  mode: str | None = None
85
- critic: bool | None = None
86
85
  dry_run: bool = False
87
86
  clean: bool = False
88
87
  no_reset: bool = False
@@ -100,7 +99,6 @@ class PromptGenerationResult:
100
99
  model: str = ""
101
100
  pipeline_mode: str = ""
102
101
  agent_count: int = 0
103
- critic_enabled: bool = False
104
102
  checkpoint_path: Path | None = None
105
103
  artifact_path: Path | None = None
106
104
  raw: Mapping[str, object] = field(default_factory=dict)
@@ -234,7 +232,6 @@ def parse_invocation(
234
232
  max_retries: int | None = None
235
233
  max_infra_retries = 3
236
234
  mode: str | None = None
237
- critic: bool | None = None
238
235
  dry_run = False
239
236
  clean = False
240
237
  no_reset = False
@@ -254,10 +251,6 @@ def parse_invocation(
254
251
  clean = True
255
252
  elif arg == "--no-reset":
256
253
  no_reset = True
257
- elif arg == "--critic":
258
- critic = True
259
- elif arg == "--no-critic":
260
- critic = False
261
254
  elif arg == "--features" and index + 1 < len(args):
262
255
  index += 1
263
256
  item_filter = args[index]
@@ -305,7 +298,6 @@ def parse_invocation(
305
298
  max_retries=max_retries,
306
299
  max_infra_retries=max_infra_retries,
307
300
  mode=mode,
308
- critic=critic,
309
301
  dry_run=dry_run,
310
302
  clean=clean,
311
303
  no_reset=no_reset,
@@ -49,8 +49,6 @@ def generate_prompt(
49
49
  ]
50
50
  if invocation.mode:
51
51
  command.extend(["--mode", invocation.mode])
52
- if invocation.critic is not None:
53
- command.extend(["--critic", "true" if invocation.critic else "false"])
54
52
  if continuation:
55
53
  command.extend(["--continuation-mode", "context_overflow"])
56
54
  for flag, key in (
@@ -90,7 +88,6 @@ def generate_prompt(
90
88
  model=str(data.get("model") or ""),
91
89
  pipeline_mode=str(data.get("pipeline_mode") or ""),
92
90
  agent_count=int(data.get("agent_count") or 0),
93
- critic_enabled=_truthy(data.get("critic_enabled")),
94
91
  checkpoint_path=Path(str(checkpoint)) if checkpoint else None,
95
92
  artifact_path=_artifact_path(family, visible_root, item_id, data),
96
93
  raw=data,
@@ -48,6 +48,14 @@ def run_pipeline_command(kind: str, action: str, legacy_args: tuple[str, ...], p
48
48
  invocation = _resolve_invocation_paths(invocation, paths.project_root)
49
49
  if invocation.help_requested:
50
50
  return CommandResult(0, f"Python {kind} runner", _help_text(family))
51
+ if invocation.unknown_args:
52
+ return CommandResult(
53
+ 2,
54
+ f"Python {kind} runner",
55
+ "Unsupported option(s): {}".format(
56
+ ", ".join(invocation.unknown_args)
57
+ ),
58
+ )
51
59
  if action == "status":
52
60
  status = status_text(family, invocation, paths.project_root)
53
61
  return CommandResult(status.return_code, f"Python {kind} status", status.stdout.strip() or status.stderr.strip())
@@ -332,16 +340,15 @@ def _emit_prompt_summary(prompt: PromptGenerationResult, session_id: str) -> Non
332
340
  if prompt.pipeline_mode:
333
341
  _emit_info(f"Pipeline mode: {_pipeline_mode_label(prompt.pipeline_mode)}")
334
342
  if prompt.agent_count:
335
- critic = "enabled" if prompt.critic_enabled else "disabled"
336
- _emit_info(f"Agents: {prompt.agent_count} (critic: {critic})")
343
+ _emit_info(f"Agents: {prompt.agent_count}")
337
344
  _emit_info(f"Spawning AI CLI session: {session_id}")
338
345
 
339
346
 
340
347
  def _pipeline_mode_label(mode: str) -> str:
341
348
  labels = {
342
349
  "lite": "lite (Tier 1 — Single Agent)",
343
- "standard": "standard (Tier 2 — Orchestrator + Critic/Reviewer)",
344
- "full": "full (Tier 3 — Orchestrator + Critic/Reviewer)",
350
+ "standard": "standard (Tier 2 — Orchestrator + Reviewer)",
351
+ "full": "full (Tier 3 — Orchestrator + Reviewer)",
345
352
  }
346
353
  return labels.get(mode, mode)
347
354
 
@@ -527,6 +534,7 @@ def _process_item(
527
534
  cwd=execution_root,
528
535
  log_path=session_paths.session_log,
529
536
  progress_path=session_paths.progress_json,
537
+ checkpoint_path=prompt.checkpoint_path,
530
538
  heartbeat_path=session_paths.heartbeat_json,
531
539
  effort=config.effort,
532
540
  verbose=env.verbose,
@@ -864,7 +872,6 @@ def _invocation_for_execution_family(invocation: RunnerInvocation, family: Runne
864
872
  max_retries=invocation.max_retries,
865
873
  max_infra_retries=invocation.max_infra_retries,
866
874
  mode=invocation.mode,
867
- critic=invocation.critic,
868
875
  dry_run=invocation.dry_run,
869
876
  clean=invocation.clean,
870
877
  no_reset=invocation.no_reset,
@@ -985,7 +992,6 @@ def _resolve_invocation_paths(invocation: RunnerInvocation, project_root: Path)
985
992
  max_retries=invocation.max_retries,
986
993
  max_infra_retries=invocation.max_infra_retries,
987
994
  mode=invocation.mode,
988
- critic=invocation.critic,
989
995
  dry_run=invocation.dry_run,
990
996
  clean=invocation.clean,
991
997
  no_reset=invocation.no_reset,
@@ -1000,5 +1006,5 @@ def _help_text(family: RunnerFamily) -> str:
1000
1006
  return (
1001
1007
  f"Python foreground runner for {family.kind}.\n"
1002
1008
  "Supported legacy options include plan list path, item id, --features for feature, "
1003
- "--max-retries, --max-infra-retries, --mode, --critic/--no-critic, --resume-phase, and --dry-run."
1009
+ "--max-retries, --max-infra-retries, --mode, --resume-phase, and --dry-run."
1004
1010
  )
@@ -17,6 +17,7 @@ from collections.abc import Callable, Mapping, Sequence
17
17
  from dataclasses import dataclass, field
18
18
  from pathlib import Path
19
19
 
20
+ from .checkpoint_state import load_checkpoint_state
20
21
  from .heartbeat import HeartbeatConfig, HeartbeatMonitor, HeartbeatState, observe_heartbeat_state, write_stale_marker
21
22
  from .launch_profiles import HeadlessLaunchProfile
22
23
  from .processes import ProcessHandle, ProcessSpec, launch_process, terminate_process_tree
@@ -45,6 +46,7 @@ class AISessionConfig:
45
46
  log_path: Path | None = None
46
47
  backup_log_path: Path | None = None
47
48
  progress_path: Path | None = None
49
+ checkpoint_path: Path | None = None
48
50
  heartbeat_path: Path | None = None
49
51
  effort: str | None = None
50
52
  verbose: bool = False
@@ -513,12 +515,18 @@ def _display_heartbeat_state(
513
515
  )
514
516
 
515
517
 
518
+ def _checkpoint_phase_label(checkpoint_path: Path | None) -> str:
519
+ state = load_checkpoint_state(checkpoint_path)
520
+ return state.current_step_name
521
+
522
+
516
523
  def _compact_progress_line(
517
524
  started_epoch: float,
518
525
  session_log: Path,
519
526
  progress_path: Path | None,
520
527
  heartbeat_state: HeartbeatState | None = None,
521
528
  *,
529
+ checkpoint_path: Path | None = None,
522
530
  stale_threshold_seconds: float = 0,
523
531
  ) -> str:
524
532
  data = _read_json_object(progress_path)
@@ -547,7 +555,7 @@ def _compact_progress_line(
547
555
  if subagents:
548
556
  child = f"{child}/{subagents}"
549
557
  parts.append(f"child: {child}")
550
- phase = str(data.get("current_phase") or "").strip()
558
+ phase = _checkpoint_phase_label(checkpoint_path)
551
559
  if phase:
552
560
  parts.append(f"phase: {phase}")
553
561
  tool = str(data.get("current_tool") or "").strip()
@@ -571,6 +579,7 @@ def _emit_progress_tick(
571
579
  progress_path: Path | None,
572
580
  last_line: str,
573
581
  *,
582
+ checkpoint_path: Path | None = None,
574
583
  monitor_state: HeartbeatState | None = None,
575
584
  fallback_state: HeartbeatState | None = None,
576
585
  interval_seconds: float = 30,
@@ -589,6 +598,7 @@ def _emit_progress_tick(
589
598
  session_log,
590
599
  progress_path,
591
600
  heartbeat_state,
601
+ checkpoint_path=checkpoint_path,
592
602
  stale_threshold_seconds=stale_threshold_seconds,
593
603
  )
594
604
  if line != last_line:
@@ -828,6 +838,7 @@ class AISessionLauncher:
828
838
  session_log,
829
839
  self.config.progress_path,
830
840
  last_progress_line,
841
+ checkpoint_path=self.config.checkpoint_path,
831
842
  monitor_state=heartbeat.state if heartbeat is not None else None,
832
843
  fallback_state=display_heartbeat_state,
833
844
  interval_seconds=live_progress_interval,
@@ -853,6 +864,7 @@ class AISessionLauncher:
853
864
  session_log,
854
865
  self.config.progress_path,
855
866
  final_heartbeat_state,
867
+ checkpoint_path=self.config.checkpoint_path,
856
868
  stale_threshold_seconds=stale_threshold_seconds,
857
869
  )
858
870
  if final_line != last_progress_line:
@@ -1,6 +1,13 @@
1
1
  """Continuation prompt and durable handoff helpers for pipeline prompt generators."""
2
2
 
3
3
  import os
4
+ import sys
5
+
6
+ _PIPELINE_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
7
+ if _PIPELINE_ROOT not in sys.path:
8
+ sys.path.insert(0, _PIPELINE_ROOT)
9
+
10
+ from prizmkit_runtime.checkpoint_state import checkpoint_cursor as shared_checkpoint_cursor # noqa: E402
4
11
 
5
12
  SUPPORTED_CONTINUATION_MODES = {"context_overflow"}
6
13
  TASK_TYPES = {"feature", "bugfix", "refactor"}
@@ -166,46 +173,7 @@ def runtime_paths(args, project_root, task_type, task_id, previous_session_id):
166
173
 
167
174
  def checkpoint_cursor(checkpoint):
168
175
  """Summarize current checkpoint state and cursor."""
169
- steps = checkpoint.get("steps", []) if isinstance(checkpoint, dict) else []
170
- completed = []
171
- skipped = []
172
- in_progress = []
173
- pending = []
174
- failed = []
175
- first_cursor = None
176
-
177
- for step in steps:
178
- skill = step.get("skill", "unknown")
179
- label = "{} ({})".format(step.get("id", "?"), skill)
180
- status = step.get("status", "pending")
181
- if status == "completed":
182
- completed.append(label)
183
- elif status == "skipped":
184
- skipped.append(label)
185
- elif status == "in_progress":
186
- in_progress.append(label)
187
- if first_cursor is None:
188
- first_cursor = label
189
- elif status == "failed":
190
- failed.append(label)
191
- if first_cursor is None:
192
- first_cursor = label
193
- else:
194
- pending.append(label)
195
- if first_cursor is None:
196
- first_cursor = label
197
-
198
- if first_cursor is None:
199
- first_cursor = "(all checkpoint steps completed or skipped)"
200
-
201
- return {
202
- "completed": completed,
203
- "skipped": skipped,
204
- "in_progress": in_progress,
205
- "pending": pending,
206
- "failed": failed,
207
- "first_cursor": first_cursor,
208
- }
176
+ return shared_checkpoint_cursor(checkpoint)
209
177
 
210
178
 
211
179
  def _list_or_none(values):