prizmkit 1.1.3 → 1.1.5

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 (57) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/run-bugfix.sh +35 -0
  3. package/bundled/dev-pipeline/run-feature.sh +33 -0
  4. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +221 -0
  5. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +124 -0
  6. package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +2 -1
  7. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +4 -0
  8. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +5 -2
  9. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +5 -2
  10. package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +20 -1
  11. package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +36 -0
  12. package/bundled/dev-pipeline/templates/sections/failure-log-check.md +2 -1
  13. package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +3 -0
  14. package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +3 -0
  15. package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +3 -0
  16. package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +3 -0
  17. package/bundled/dev-pipeline/templates/sections/phase-commit.md +3 -0
  18. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +3 -0
  19. package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +3 -0
  20. package/bundled/dev-pipeline/templates/sections/phase-critic-code.md +3 -0
  21. package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +3 -0
  22. package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +3 -0
  23. package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +3 -0
  24. package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +3 -0
  25. package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +3 -0
  26. package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +3 -0
  27. package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +3 -0
  28. package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +3 -0
  29. package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +3 -0
  30. package/bundled/dev-pipeline/templates/sections/phase-review-full.md +3 -0
  31. package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -0
  32. package/bundled/dev-pipeline/templates/sections/phase0-init.md +3 -0
  33. package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +3 -0
  34. package/bundled/dev-pipeline/templates/sections/resume-header.md +4 -1
  35. package/bundled/rules/prizm/prizm-commit-workflow.md +1 -0
  36. package/bundled/rules/prizm/prizm-documentation.md +15 -15
  37. package/bundled/rules/prizm/prizm-progressive-loading.md +2 -1
  38. package/bundled/skills/_metadata.json +1 -1
  39. package/bundled/skills/prizm-kit/assets/project-memory-template.md +4 -2
  40. package/bundled/skills/prizmkit-committer/SKILL.md +28 -0
  41. package/bundled/skills/prizmkit-implement/SKILL.md +2 -1
  42. package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +69 -0
  43. package/bundled/skills/prizmkit-init/SKILL.md +2 -1
  44. package/bundled/skills/prizmkit-init/references/config-schema.md +64 -0
  45. package/bundled/skills/prizmkit-init/references/tech-stack-catalog.md +13 -0
  46. package/bundled/skills/prizmkit-init/references/update-supplement.md +9 -0
  47. package/bundled/skills/prizmkit-plan/assets/spec-template.md +56 -0
  48. package/bundled/skills/prizmkit-plan/references/clarify-guide.md +67 -0
  49. package/bundled/skills/prizmkit-prizm-docs/SKILL.md +7 -4
  50. package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +31 -1
  51. package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +49 -0
  52. package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +63 -0
  53. package/bundled/skills/recovery-workflow/SKILL.md +4 -2
  54. package/bundled/team/prizm-dev-team.json +1 -1
  55. package/package.json +1 -1
  56. package/src/config.js +504 -0
  57. package/src/prompts.js +210 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.3",
3
- "bundledAt": "2026-04-04T02:47:27.664Z",
4
- "bundledFrom": "f15da00"
2
+ "frameworkVersion": "1.1.5",
3
+ "bundledAt": "2026-04-04T15:56:26.382Z",
4
+ "bundledFrom": "902d4ef"
5
5
  }
@@ -224,6 +224,41 @@ spawn_and_wait_session() {
224
224
 
225
225
  log_info "Session result: $session_status"
226
226
 
227
+ # Validate checkpoint completeness after successful session
228
+ if [[ "$session_status" == "success" ]]; then
229
+ local _ckpt_root
230
+ _ckpt_root="$(cd "$SCRIPT_DIR/.." && pwd)"
231
+ local checkpoint_file="$_ckpt_root/.prizmkit/bugfix/${bug_id}/workflow-checkpoint.json"
232
+ if [[ -f "$checkpoint_file" ]]; then
233
+ local checkpoint_result
234
+ checkpoint_result=$(python3 -c "
235
+ import json, sys
236
+ try:
237
+ with open(sys.argv[1]) as f:
238
+ data = json.load(f)
239
+ except json.JSONDecodeError as e:
240
+ print('CORRUPTED: {}'.format(e))
241
+ sys.exit(2)
242
+ incomplete = [s for s in data['steps'] if s['status'] not in ('completed', 'skipped')]
243
+ if incomplete:
244
+ for s in incomplete:
245
+ print('INCOMPLETE: {} {} = {}'.format(s['id'], s['skill'], s['status']))
246
+ sys.exit(1)
247
+ print('ALL_COMPLETE')
248
+ sys.exit(0)
249
+ " "$checkpoint_file" 2>&1)
250
+ local check_exit=$?
251
+ if [[ $check_exit -eq 2 ]]; then
252
+ log_warn "CHECKPOINT_CORRUPTED: workflow-checkpoint.json is not valid JSON"
253
+ elif [[ $check_exit -eq 1 ]]; then
254
+ log_warn "CHECKPOINT_INCOMPLETE: Not all workflow steps completed:"
255
+ echo "$checkpoint_result" | while read -r line; do log_warn " $line"; done
256
+ else
257
+ log_info "CHECKPOINT: All workflow steps completed"
258
+ fi
259
+ fi
260
+ fi
261
+
227
262
  # Subagent detection
228
263
  prizm_detect_subagents "$session_log"
229
264
 
@@ -287,6 +287,39 @@ sys.exit(1)
287
287
  if [[ ! -f "$plan_file" ]]; then
288
288
  log_warn "ARTIFACT_MISSING: plan.md not found at $plan_file"
289
289
  fi
290
+
291
+ # Validate checkpoint completeness
292
+ local checkpoint_file="$project_root_for_artifacts/.prizmkit/specs/${feature_slug}/workflow-checkpoint.json"
293
+ if [[ -f "$checkpoint_file" ]]; then
294
+ local checkpoint_result
295
+ checkpoint_result=$(python3 -c "
296
+ import json, sys
297
+ try:
298
+ with open(sys.argv[1]) as f:
299
+ data = json.load(f)
300
+ except json.JSONDecodeError as e:
301
+ print('CORRUPTED: {}'.format(e))
302
+ sys.exit(2)
303
+ incomplete = [s for s in data['steps'] if s['status'] not in ('completed', 'skipped')]
304
+ if incomplete:
305
+ for s in incomplete:
306
+ print('INCOMPLETE: {} {} = {}'.format(s['id'], s['skill'], s['status']))
307
+ sys.exit(1)
308
+ print('ALL_COMPLETE')
309
+ sys.exit(0)
310
+ " "$checkpoint_file" 2>&1)
311
+ local check_exit=$?
312
+ if [[ $check_exit -eq 2 ]]; then
313
+ log_warn "CHECKPOINT_CORRUPTED: workflow-checkpoint.json is not valid JSON"
314
+ elif [[ $check_exit -eq 1 ]]; then
315
+ log_warn "CHECKPOINT_INCOMPLETE: Not all workflow steps completed:"
316
+ echo "$checkpoint_result" | while read -r line; do log_warn " $line"; done
317
+ else
318
+ log_info "CHECKPOINT: All workflow steps completed"
319
+ fi
320
+ else
321
+ log_info "CHECKPOINT: No workflow-checkpoint.json found (checkpoint system not active)"
322
+ fi
290
323
  fi
291
324
 
292
325
  # Check if session produced a failure-log for future retries
@@ -530,6 +530,171 @@ def determine_pipeline_mode(complexity):
530
530
  return mapping.get(complexity, "lite")
531
531
 
532
532
 
533
+ # ============================================================
534
+ # Checkpoint generation
535
+ # ============================================================
536
+
537
+ # Mapping: section name -> (skill_key, display_name, required_artifacts)
538
+ # skill_key is a unique identifier in the checkpoint, not necessarily the
539
+ # prizmkit skill name. This ensures each section has a distinct key so
540
+ # merge_checkpoint_state() never collides.
541
+ SECTION_TO_SKILL = {
542
+ "phase0-init": ("prizmkit-init", "Project Bootstrap",
543
+ [".prizm-docs/root.prizm", ".prizmkit/config.json"]),
544
+ "phase0-test-baseline": ("test-baseline", "Test Baseline", []),
545
+ "phase-context-snapshot": ("context-snapshot", "Build Context Snapshot",
546
+ [".prizmkit/specs/{slug}/context-snapshot.md"]),
547
+ "phase-specify-plan": ("context-snapshot-and-plan", "Specify & Plan",
548
+ [".prizmkit/specs/{slug}/context-snapshot.md",
549
+ ".prizmkit/specs/{slug}/plan.md"]),
550
+ "phase-plan": ("prizmkit-plan", "Plan & Tasks",
551
+ [".prizmkit/specs/{slug}/plan.md"]),
552
+ "phase-analyze": ("prizmkit-analyze", "Analyze", []),
553
+ "phase-critic-plan": ("critic-plan-review", "Critic: Plan Review", []),
554
+ "phase-implement": ("prizmkit-implement", "Implement + Test", []),
555
+ "phase-critic-code": ("critic-code-review", "Critic: Code Review", []),
556
+ "phase-review": ("prizmkit-code-review", "Code Review", []),
557
+ "phase-browser": ("browser-verification", "Browser Verification", []),
558
+ "phase-deploy": ("deploy-verification", "Deploy Verification", []),
559
+ "phase-commit": None, # special: split into retrospective + committer
560
+ }
561
+
562
+ # phase-commit is split into two steps
563
+ _COMMIT_STEPS = [
564
+ ("prizmkit-retrospective", "Retrospective", []),
565
+ ("prizmkit-committer", "Commit", []),
566
+ ]
567
+
568
+
569
+ def _resolve_artifacts(artifact_templates, slug):
570
+ """Replace {slug} placeholder with the actual feature slug."""
571
+ return [a.replace("{slug}", slug) for a in artifact_templates]
572
+
573
+
574
+ def generate_checkpoint_definition(sections, pipeline_mode, workflow_type,
575
+ item_id, item_slug, session_id,
576
+ init_done=False):
577
+ """Derive checkpoint step definitions from the assembled sections list.
578
+
579
+ Args:
580
+ sections: list of (name, content) tuples from assemble_sections()
581
+ pipeline_mode: "lite" | "standard" | "full"
582
+ workflow_type: "feature-pipeline"
583
+ item_id: feature ID (e.g. "F-001")
584
+ item_slug: feature slug (e.g. "001-user-auth")
585
+ session_id: current session ID
586
+ init_done: whether project is already initialized (Phase 0 skip)
587
+
588
+ Returns:
589
+ dict suitable for writing as workflow-checkpoint.json
590
+ """
591
+ steps = []
592
+ step_counter = 1
593
+ prev_step_id = None
594
+
595
+ for section_name, _content in sections:
596
+ if section_name not in SECTION_TO_SKILL:
597
+ continue
598
+
599
+ mapping = SECTION_TO_SKILL[section_name]
600
+
601
+ if mapping is None:
602
+ # phase-commit -> split into retrospective + committer
603
+ for skill, name, artifacts in _COMMIT_STEPS:
604
+ step_id = "S{:02d}".format(step_counter)
605
+ steps.append({
606
+ "id": step_id,
607
+ "skill": skill,
608
+ "name": name,
609
+ "status": "pending",
610
+ "required_artifacts": _resolve_artifacts(artifacts, item_slug),
611
+ "depends_on": prev_step_id,
612
+ })
613
+ prev_step_id = step_id
614
+ step_counter += 1
615
+ continue
616
+
617
+ skill, name, artifacts = mapping
618
+ step_id = "S{:02d}".format(step_counter)
619
+
620
+ status = "pending"
621
+ if init_done and section_name in ("phase0-init", "phase0-test-baseline"):
622
+ status = "skipped"
623
+
624
+ steps.append({
625
+ "id": step_id,
626
+ "skill": skill,
627
+ "name": name,
628
+ "status": status,
629
+ "required_artifacts": _resolve_artifacts(artifacts, item_slug),
630
+ "depends_on": prev_step_id,
631
+ })
632
+
633
+ prev_step_id = step_id
634
+ step_counter += 1
635
+
636
+ return {
637
+ "version": 1,
638
+ "workflow_type": workflow_type,
639
+ "pipeline_mode": pipeline_mode,
640
+ "item_id": item_id,
641
+ "item_slug": item_slug,
642
+ "session_id": session_id,
643
+ "steps": steps,
644
+ }
645
+
646
+
647
+ def merge_checkpoint_state(existing, fresh, project_root):
648
+ """Merge existing checkpoint state into a freshly generated definition.
649
+
650
+ Matching is by skill_key (not step ID), since tier changes across retries
651
+ may shift step IDs.
652
+
653
+ Merge rules:
654
+ 1. Only keep completed steps whose required_artifacts all exist on disk
655
+ 2. Keep skipped steps unconditionally
656
+ 3. Once a step is NOT completed/skipped, break the dependency chain:
657
+ all subsequent steps reset to pending
658
+ """
659
+ existing_status = {}
660
+ existing_artifacts = {}
661
+ for step in existing.get("steps", []):
662
+ existing_status[step["skill"]] = step["status"]
663
+ existing_artifacts[step["skill"]] = step.get("required_artifacts", [])
664
+
665
+ # Determine which completed steps have valid artifacts
666
+ valid_completed = set()
667
+ for skill_key, status in existing_status.items():
668
+ if status == "completed":
669
+ artifacts = existing_artifacts.get(skill_key, [])
670
+ if all(os.path.exists(os.path.join(project_root, a))
671
+ for a in artifacts):
672
+ valid_completed.add(skill_key)
673
+ else:
674
+ LOGGER.warning(
675
+ "Step '%s' was completed but artifacts missing — "
676
+ "resetting to pending", skill_key
677
+ )
678
+ elif status == "skipped":
679
+ valid_completed.add(skill_key)
680
+
681
+ # Apply to fresh steps; break chain on first non-valid step
682
+ chain_broken = False
683
+ for step in fresh["steps"]:
684
+ if chain_broken:
685
+ step["status"] = "pending"
686
+ continue
687
+
688
+ prev = existing_status.get(step["skill"])
689
+ if step["skill"] in valid_completed:
690
+ step["status"] = prev # completed or skipped
691
+ else:
692
+ chain_broken = True
693
+ step["status"] = "pending"
694
+
695
+ return fresh
696
+
697
+
533
698
  # ============================================================
534
699
  # Section Assembly (new modular approach)
535
700
  # ============================================================
@@ -721,6 +886,12 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
721
886
  load_section(sections_dir,
722
887
  "subagent-timeout-recovery.md")))
723
888
 
889
+ # --- Checkpoint System ---
890
+ checkpoint_section_path = os.path.join(sections_dir, "checkpoint-system.md")
891
+ if os.path.isfile(checkpoint_section_path):
892
+ sections.append(("checkpoint-system",
893
+ load_section(sections_dir, "checkpoint-system.md")))
894
+
724
895
  # --- Execution header ---
725
896
  sections.append(("execution-header", "---\n\n## Execution\n"))
726
897
 
@@ -1143,6 +1314,9 @@ def build_replacements(args, feature, features, global_context, script_dir):
1143
1314
  "{{SESSION_STATUS_PATH}}": session_status_abs,
1144
1315
  "{{PROJECT_ROOT}}": project_root,
1145
1316
  "{{FEATURE_SLUG}}": feature_slug,
1317
+ "{{CHECKPOINT_PATH}}": os.path.join(
1318
+ ".prizmkit", "specs", feature_slug, "workflow-checkpoint.json",
1319
+ ),
1146
1320
  "{{PIPELINE_MODE}}": pipeline_mode,
1147
1321
  "{{COMPLEXITY}}": complexity,
1148
1322
  "{{CRITIC_ENABLED}}": "true" if critic_enabled else "false",
@@ -1314,6 +1488,52 @@ def main():
1314
1488
  if err:
1315
1489
  emit_failure(err)
1316
1490
 
1491
+ # ── Generate checkpoint file ──────────────────────────────────────
1492
+ project_root = resolve_project_root(
1493
+ os.path.dirname(os.path.abspath(__file__))
1494
+ )
1495
+ feature_slug = replacements.get("{{FEATURE_SLUG}}", "")
1496
+ checkpoint_path = ""
1497
+
1498
+ if use_sections and feature_slug:
1499
+ checkpoint = generate_checkpoint_definition(
1500
+ sections=sections,
1501
+ pipeline_mode=pipeline_mode,
1502
+ workflow_type="feature-pipeline",
1503
+ item_id=args.feature_id,
1504
+ item_slug=feature_slug,
1505
+ session_id=args.session_id,
1506
+ init_done=init_done,
1507
+ )
1508
+
1509
+ checkpoint_dir = os.path.join(
1510
+ project_root, ".prizmkit", "specs", feature_slug,
1511
+ )
1512
+ os.makedirs(checkpoint_dir, exist_ok=True)
1513
+ checkpoint_path = os.path.join(
1514
+ checkpoint_dir, "workflow-checkpoint.json",
1515
+ )
1516
+
1517
+ # On resume, merge existing completed state (with artifact validation)
1518
+ if is_resume and os.path.exists(checkpoint_path):
1519
+ try:
1520
+ with open(checkpoint_path, "r", encoding="utf-8") as f:
1521
+ existing = json.load(f)
1522
+ checkpoint = merge_checkpoint_state(
1523
+ existing, checkpoint, project_root,
1524
+ )
1525
+ LOGGER.info("Merged existing checkpoint state from %s",
1526
+ checkpoint_path)
1527
+ except (json.JSONDecodeError, KeyError) as exc:
1528
+ LOGGER.warning(
1529
+ "Existing checkpoint corrupted (%s) — generating fresh",
1530
+ exc,
1531
+ )
1532
+
1533
+ with open(checkpoint_path, "w", encoding="utf-8") as f:
1534
+ json.dump(checkpoint, f, indent=2, ensure_ascii=False)
1535
+ LOGGER.info("Wrote checkpoint to %s", checkpoint_path)
1536
+
1317
1537
  # ── Success JSON ───────────────────────────────────────────────────
1318
1538
  feature_model = feature.get("model", "")
1319
1539
  mode_agent_counts = {"lite": 1, "standard": 3, "full": 3}
@@ -1331,6 +1551,7 @@ def main():
1331
1551
  "render_mode": "sections" if use_sections else "legacy",
1332
1552
  "validation_warnings": len(warnings),
1333
1553
  "validation_errors": len(errors),
1554
+ "checkpoint_path": checkpoint_path,
1334
1555
  }
1335
1556
  print(json.dumps(output, indent=2, ensure_ascii=False))
1336
1557
  sys.exit(0)
@@ -324,6 +324,95 @@ def emit_failure(message):
324
324
  sys.exit(1)
325
325
 
326
326
 
327
+ # ============================================================
328
+ # Checkpoint generation for bugfix pipeline
329
+ # ============================================================
330
+
331
+ BUGFIX_STEPS = [
332
+ ("prizmkit-init", "Initialize", []),
333
+ ("bug-diagnosis", "Bug Diagnosis & Fix Plan",
334
+ [".prizmkit/bugfix/{slug}/fix-plan.md"]),
335
+ ("bug-reproduce", "Write Reproduction Test", []),
336
+ ("bug-fix", "Implement Fix", []),
337
+ ("prizmkit-code-review", "Code Review", []),
338
+ ("prizmkit-committer", "Commit", []),
339
+ ("bug-report", "Generate Fix Report & Update TRAPS",
340
+ [".prizmkit/bugfix/{slug}/fix-report.md"]),
341
+ ]
342
+
343
+
344
+ def generate_bugfix_checkpoint(bug_id, session_id):
345
+ """Generate a checkpoint definition for bugfix pipeline.
346
+
347
+ Returns a dict suitable for writing as workflow-checkpoint.json.
348
+ """
349
+ steps = []
350
+ prev_id = None
351
+ for i, (skill, name, artifacts) in enumerate(BUGFIX_STEPS, 1):
352
+ step_id = "S{:02d}".format(i)
353
+ steps.append({
354
+ "id": step_id,
355
+ "skill": skill,
356
+ "name": name,
357
+ "status": "pending",
358
+ "required_artifacts": [a.replace("{slug}", bug_id) for a in artifacts],
359
+ "depends_on": prev_id,
360
+ })
361
+ prev_id = step_id
362
+
363
+ return {
364
+ "version": 1,
365
+ "workflow_type": "bugfix-pipeline",
366
+ "pipeline_mode": "single",
367
+ "item_id": bug_id,
368
+ "item_slug": bug_id,
369
+ "session_id": session_id,
370
+ "steps": steps,
371
+ }
372
+
373
+
374
+ def merge_bugfix_checkpoint_state(existing, fresh, project_root):
375
+ """Merge existing bugfix checkpoint state into fresh definition.
376
+
377
+ Same logic as feature pipeline: validate artifacts, break chain on
378
+ first invalid step.
379
+ """
380
+ existing_status = {}
381
+ existing_artifacts = {}
382
+ for step in existing.get("steps", []):
383
+ existing_status[step["skill"]] = step["status"]
384
+ existing_artifacts[step["skill"]] = step.get("required_artifacts", [])
385
+
386
+ valid_completed = set()
387
+ for skill_key, status in existing_status.items():
388
+ if status == "completed":
389
+ artifacts = existing_artifacts.get(skill_key, [])
390
+ if all(os.path.exists(os.path.join(project_root, a))
391
+ for a in artifacts):
392
+ valid_completed.add(skill_key)
393
+ else:
394
+ LOGGER.warning(
395
+ "Step '%s' was completed but artifacts missing — "
396
+ "resetting to pending", skill_key
397
+ )
398
+ elif status == "skipped":
399
+ valid_completed.add(skill_key)
400
+
401
+ chain_broken = False
402
+ for step in fresh["steps"]:
403
+ if chain_broken:
404
+ step["status"] = "pending"
405
+ continue
406
+ prev = existing_status.get(step["skill"])
407
+ if step["skill"] in valid_completed:
408
+ step["status"] = prev
409
+ else:
410
+ chain_broken = True
411
+ step["status"] = "pending"
412
+
413
+ return fresh
414
+
415
+
327
416
  def main():
328
417
  args = parse_args()
329
418
 
@@ -366,6 +455,12 @@ def main():
366
455
  # Build replacements
367
456
  replacements = build_replacements(args, bug, global_context, script_dir)
368
457
 
458
+ # Add checkpoint path to replacements
459
+ checkpoint_rel = os.path.join(
460
+ ".prizmkit", "bugfix", args.bug_id, "workflow-checkpoint.json",
461
+ )
462
+ replacements["{{CHECKPOINT_PATH}}"] = checkpoint_rel
463
+
369
464
  # Render the template
370
465
  rendered = render_template(template_content, replacements, bug)
371
466
 
@@ -374,10 +469,39 @@ def main():
374
469
  if err:
375
470
  emit_failure(err)
376
471
 
472
+ # Generate checkpoint file
473
+ project_root = resolve_project_root(script_dir)
474
+ checkpoint_path = os.path.join(project_root, checkpoint_rel)
475
+ checkpoint_dir = os.path.dirname(checkpoint_path)
476
+ os.makedirs(checkpoint_dir, exist_ok=True)
477
+
478
+ checkpoint = generate_bugfix_checkpoint(args.bug_id, args.session_id)
479
+
480
+ is_resume = args.resume_phase != "null"
481
+ if is_resume and os.path.exists(checkpoint_path):
482
+ try:
483
+ with open(checkpoint_path, "r", encoding="utf-8") as f:
484
+ existing = json.load(f)
485
+ checkpoint = merge_bugfix_checkpoint_state(
486
+ existing, checkpoint, project_root,
487
+ )
488
+ LOGGER.info("Merged existing bugfix checkpoint from %s",
489
+ checkpoint_path)
490
+ except (json.JSONDecodeError, KeyError) as exc:
491
+ LOGGER.warning(
492
+ "Existing bugfix checkpoint corrupted (%s) — generating fresh",
493
+ exc,
494
+ )
495
+
496
+ with open(checkpoint_path, "w", encoding="utf-8") as f:
497
+ json.dump(checkpoint, f, indent=2, ensure_ascii=False)
498
+ LOGGER.info("Wrote bugfix checkpoint to %s", checkpoint_path)
499
+
377
500
  # Success
378
501
  output = {
379
502
  "success": True,
380
503
  "output_path": os.path.abspath(args.output),
504
+ "checkpoint_path": checkpoint_path,
381
505
  }
382
506
  print(json.dumps(output, indent=2, ensure_ascii=False))
383
507
  sys.exit(0)
@@ -3,7 +3,8 @@
3
3
  ⚠️ DO NOT re-read source files already listed in Section 4 File Manifest unless you need implementation detail beyond the interface summary.
4
4
  1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` for full context.
5
5
  2. Run `/prizmkit-implement` to execute the tasks in plan.md. Run tests with: `{{TEST_CMD}}`. Known baseline failures (pre-existing, not your fault): `{{BASELINE_FAILURES}}`.
6
- 3. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
6
+ 3. If plan.md has more than 5 tasks: run `/compact` after completing every 3 tasks to manage context budget. If `/compact` is unavailable, continue without it.
7
+ 4. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
7
8
 
8
9
  ## Acceptance Criteria Verification
9
10
 
@@ -152,6 +152,8 @@ $TEST_CMD 2>&1 | tee /tmp/test-baseline.txt | tail -20
152
152
  - Runs tests using `TEST_CMD` after each task
153
153
  - Writes '## Implementation Log' to `context-snapshot.md`
154
154
 
155
+ **3b-compact.** Context management — if plan.md has more than 5 tasks, run `/compact` after completing every 3 tasks during implementation. This prevents context window exhaustion in long sessions. If `/compact` is not available (non-Claude CLI), skip this step.
156
+
155
157
  **3c.** After implement completes, verify:
156
158
  1. All tasks in plan.md are `[x]`
157
159
  2. Run the full test suite to ensure nothing is broken
@@ -285,6 +287,8 @@ git status --short
285
287
  ```
286
288
  Working tree MUST be clean after this step. If any feature-related files remain, stage them into the SAME commit via `git add <file> && git commit --amend --no-edit`, do NOT create a separate commit.
287
289
 
290
+ **Exception**: `session-summary.md` in the artifact directory is a local cross-session artifact generated by `/prizmkit-committer` — it is NOT committed to git. Ignore it in the clean-tree check.
291
+
288
292
  ## Critical Paths
289
293
 
290
294
  | Resource | Path |
@@ -215,8 +215,9 @@ Prompt:
215
215
  > ⚠️ DO NOT re-read source files already listed in Section 4 File Manifest unless you need implementation detail beyond the interface summary.
216
216
  > 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` for full context.
217
217
  > 2. Run `/prizmkit-implement` to execute the tasks in plan.md. Run tests with: `{{TEST_CMD}}`. Known baseline failures (pre-existing, not your fault): `{{BASELINE_FAILURES}}`.
218
- > 3. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
219
- > 4. Do NOT execute any git commands (no git add/commit/reset/push).
218
+ > 3. If plan.md has more than 5 tasks: run `/compact` after completing every 3 tasks to manage context budget. If `/compact` is unavailable, continue without it.
219
+ > 4. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
220
+ > 5. Do NOT execute any git commands (no git add/commit/reset/push).
220
221
  > Do NOT exit until all tasks are [x] and the '## Implementation Log' section is written in context-snapshot.md."
221
222
 
222
223
  Wait for Dev to return. All tasks must be `[x]`, tests pass.
@@ -383,6 +384,8 @@ git status --short
383
384
  ```
384
385
  Working tree MUST be clean after this step. If any feature-related files remain, stage them into the SAME commit via `git add <file> && git commit --amend --no-edit`, do NOT create a separate commit.
385
386
 
387
+ **Exception**: `session-summary.md` in the artifact directory is a local cross-session artifact generated by `/prizmkit-committer` — it is NOT committed to git. Ignore it in the clean-tree check.
388
+
386
389
  ## Critical Paths
387
390
 
388
391
  | Resource | Path |
@@ -280,8 +280,9 @@ Prompt:
280
280
  > ⚠️ DO NOT re-read source files already listed in Section 4 File Manifest unless you need implementation detail beyond the interface summary.
281
281
  > 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` for full context.
282
282
  > 2. Run `/prizmkit-implement` to execute the tasks in plan.md. Run tests with: `{{TEST_CMD}}`. Known baseline failures (pre-existing, not your fault): `{{BASELINE_FAILURES}}`.
283
- > 3. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
284
- > 4. Do NOT execute any git commands (no git add/commit/reset/push).
283
+ > 3. If plan.md has more than 5 tasks: run `/compact` after completing every 3 tasks to manage context budget. If `/compact` is unavailable, continue without it.
284
+ > 4. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
285
+ > 5. Do NOT execute any git commands (no git add/commit/reset/push).
285
286
  > Do NOT exit until all tasks are [x] and the '## Implementation Log' section is written in context-snapshot.md."
286
287
 
287
288
  **Gate Check — Implementation Log**:
@@ -476,6 +477,8 @@ git status --short
476
477
  ```
477
478
  Working tree MUST be clean after this step. If any feature-related files remain, stage them into the SAME commit via `git add <file> && git commit --amend --no-edit`, do NOT create a separate commit.
478
479
 
480
+ **Exception**: `session-summary.md` in the artifact directory is a local cross-session artifact generated by `/prizmkit-committer` — it is NOT committed to git. Ignore it in the clean-tree check.
481
+
479
482
  ## Critical Paths
480
483
 
481
484
  | Resource | Path |
@@ -67,6 +67,19 @@ You are the **bug fix session orchestrator**. Fix Bug {{BUG_ID}}: "{{BUG_TITLE}}
67
67
 
68
68
  **IMPORTANT**: Only 2 artifact files per bug, NEVER more. This is a fixed convention.
69
69
 
70
+ ## Workflow Checkpoint System
71
+
72
+ A checkpoint file tracks your progress through this workflow:
73
+
74
+ **Path**: `{{CHECKPOINT_PATH}}`
75
+
76
+ **Rules**:
77
+ 1. **Before each step**: Read `workflow-checkpoint.json`, verify the previous step has `status: "completed"` or `status: "skipped"`. If not, complete it first.
78
+ 2. **Starting a step**: Update the current step to `status: "in_progress"`.
79
+ 3. **After each step completes**: Update the step to `status: "completed"`. Verify JSON is valid after writing.
80
+ 4. **On failure**: Set the step to `status: "failed"` and halt.
81
+ 5. **On resume**: Steps already `"completed"` are skipped. Start from the first `"pending"` or `"in_progress"` step.
82
+
70
83
  ## Execution Instructions
71
84
 
72
85
  **YOU are the orchestrator. Execute each phase by spawning the appropriate team agent with run_in_background=false.**
@@ -109,6 +122,7 @@ Reference `{{TEAM_CONFIG_PATH}}` for agent definitions:
109
122
  "
110
123
  - **Wait for Dev to return**
111
124
  - **CP-BF-1**: `.prizmkit/bugfix/{{BUG_ID}}/fix-plan.md` exists
125
+ - **Checkpoint update**: set step `bug-diagnosis` to `"completed"` in `{{CHECKPOINT_PATH}}`
112
126
 
113
127
  **DECISION GATE — Fast Path Check**:
114
128
  - If severity is LOW or MEDIUM, AND root cause is obvious (high confidence), AND fix is < 10 lines:
@@ -141,6 +155,7 @@ Reference `{{TEAM_CONFIG_PATH}}` for agent definitions:
141
155
  - Write session-status.json with status="partial", errors=["reproduction_failed"]
142
156
  - Set bug status to `needs_info` and STOP
143
157
  - **CP-BF-2**: Reproduction test exists and FAILS
158
+ - **Checkpoint update**: set step `bug-reproduce` to `"completed"` in `{{CHECKPOINT_PATH}}`
144
159
 
145
160
  ---
146
161
 
@@ -158,11 +173,13 @@ Reference `{{TEAM_CONFIG_PATH}}` for agent definitions:
158
173
  - Do NOT refactor — fix the bug only
159
174
  4. Run the reproduction test → MUST PASS
160
175
  5. Run the module's test suite → MUST PASS (no regression)
161
- 6. If fix fails after 3 rounds, report detailed analysis
176
+ 6. If the fix involves multiple files or steps: run `/compact` after completing the core fix and before running the full test suite, to free context budget. If `/compact` is unavailable, continue without it.
177
+ 7. If fix fails after 3 rounds, report detailed analysis
162
178
  "
163
179
  - **Wait for Dev to return**
164
180
  - If fix fails after 3 rounds: escalate to user, write status="failed"
165
181
  - **CP-BF-3**: Reproduction test passes, module tests pass
182
+ - **Checkpoint update**: set step `bug-fix` to `"completed"` in `{{CHECKPOINT_PATH}}`
166
183
 
167
184
  ---
168
185
 
@@ -185,6 +202,7 @@ Reference `{{TEAM_CONFIG_PATH}}` for agent definitions:
185
202
  - **Wait for Reviewer to return**
186
203
  - If NEEDS_FIXES: return to Phase 3 for refinement following Fix Instructions (max 2 review rounds)
187
204
  - **CP-BF-4**: Code review passes, all tests green
205
+ - **Checkpoint update**: set step `prizmkit-code-review` to `"completed"` in `{{CHECKPOINT_PATH}}`
188
206
 
189
207
  {{IF_VERIFICATION_MANUAL_OR_HYBRID}}
190
208
  **MANUAL VERIFICATION GATE**:
@@ -222,6 +240,7 @@ Reference `{{TEAM_CONFIG_PATH}}` for agent definitions:
222
240
  - Acceptance Criteria Verification (checklist with pass/fail for each criterion)
223
241
 
224
242
  - **CP-BF-5**: Commit recorded, fix-report.md written, TRAPS updated (if applicable)
243
+ - **Checkpoint update**: set steps `prizmkit-committer` and `bug-report` to `"completed"` in `{{CHECKPOINT_PATH}}`
225
244
 
226
245
  ### Step 3: Report Session Status
227
246