@ikon85/agent-workflow-kit 0.37.0 → 0.39.0

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 (44) hide show
  1. package/.agents/skills/kit-update/SKILL.md +33 -1
  2. package/.agents/skills/orchestrate-wave/SKILL.md +5 -5
  3. package/.agents/skills/setup-workflow/SKILL.md +42 -4
  4. package/.agents/skills/setup-workflow/board-sync.md +6 -2
  5. package/.agents/skills/setup-workflow/workflow-advisories.md +34 -0
  6. package/.agents/skills/setup-workflow/worktree-lifecycle.md +47 -1
  7. package/.agents/skills/wrapup/SKILL.md +46 -0
  8. package/.claude/hooks/drift-guard.py +212 -21
  9. package/.claude/skills/kit-update/SKILL.md +33 -1
  10. package/.claude/skills/orchestrate-wave/SKILL.md +5 -5
  11. package/.claude/skills/setup-workflow/SKILL.md +42 -4
  12. package/.claude/skills/setup-workflow/board-sync.md +6 -2
  13. package/.claude/skills/setup-workflow/workflow-advisories.md +34 -0
  14. package/.claude/skills/setup-workflow/worktree-lifecycle.md +47 -1
  15. package/.claude/skills/wrapup/SKILL.md +46 -0
  16. package/README.md +73 -0
  17. package/agent-workflow-kit.package.json +49 -25
  18. package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +88 -0
  19. package/docs/agents/workflow-capabilities.json +11 -1
  20. package/package.json +1 -1
  21. package/scripts/board_bootstrap.py +367 -0
  22. package/scripts/kit-update-pr.mjs +20 -7
  23. package/scripts/kit-update-pr.test.mjs +29 -0
  24. package/scripts/profile_globs.py +347 -0
  25. package/scripts/test_board_bootstrap.py +348 -0
  26. package/scripts/test_drift_guard_diagnostics.py +295 -0
  27. package/scripts/test_orchestrate_wave_contract.py +9 -0
  28. package/scripts/test_profile_globs.py +280 -0
  29. package/scripts/test_skill_setup_workflow_seeds.py +87 -0
  30. package/scripts/test_worktree_wrapup_contract.py +1592 -3
  31. package/scripts/workflow-advisories/core.py +29 -4
  32. package/scripts/worktree-lifecycle/README.md +139 -0
  33. package/scripts/worktree-lifecycle/capabilities.json +9 -1
  34. package/scripts/worktree-lifecycle/cleanup.py +22 -51
  35. package/scripts/worktree-lifecycle/core.py +1206 -5
  36. package/scripts/worktree-lifecycle/profile.py +38 -3
  37. package/scripts/worktree-lifecycle/session.py +1857 -0
  38. package/scripts/worktree-lifecycle/setup.py +15 -0
  39. package/scripts/wrapup-land.py +461 -14
  40. package/src/cli.mjs +32 -1
  41. package/src/commands/update.mjs +30 -21
  42. package/src/consumer-migrations.json +19 -0
  43. package/src/lib/bundle.mjs +11 -0
  44. package/src/lib/consumerMigrations.mjs +161 -0
@@ -57,6 +57,31 @@ def update_workflow_action(
57
57
  return "create" if pull_requests_allowed else "skip"
58
58
 
59
59
 
60
+ def board_branch_action(tracker, boards_found, project_scope, user_choice):
61
+ """Reference decision table for Section D's board branch (#24).
62
+
63
+ tracker: the Section A choice.
64
+ boards_found: how many owner projects the discovery read found, or None when
65
+ the read itself failed.
66
+ project_scope: does `gh` carry the write scope board creation needs?
67
+ user_choice: the answer to the creation offer ("yes" / "no" / None).
68
+
69
+ "discover" fills the profile from an existing board, "create" runs the
70
+ bootstrap helper after an explicit yes, "stub" is the retryable stub path.
71
+ Creation is offered on exactly one branch — no board, with the scope — and a
72
+ decline, a missing scope, ambiguity, or a failed read all stay on the stub.
73
+ """
74
+ if tracker != "github":
75
+ return "not-applicable"
76
+ if boards_found is None or boards_found > 1:
77
+ return "stub"
78
+ if boards_found == 1:
79
+ return "discover"
80
+ if not project_scope:
81
+ return "stub"
82
+ return "create" if user_choice == "yes" else "stub"
83
+
84
+
60
85
  def load_census_setup_effects():
61
86
  """Parse the shipped seed's executable census transition contract."""
62
87
  seed = (SKILL / "census.md").read_text(encoding="utf-8")
@@ -559,6 +584,68 @@ class SeedTemplatesValid(unittest.TestCase):
559
584
  self.assertIn("Board status is authoritative", triage_skill)
560
585
 
561
586
 
587
+ class BoardCreationOffer(unittest.TestCase):
588
+ """Section D offers board creation instead of refusing it (#24).
589
+
590
+ The mechanics live in `scripts/board_bootstrap.py` (spec:
591
+ `scripts/test_board_bootstrap.py`); what is pinned here is the prose
592
+ contract: an explicit user gate, one creation path, and every other branch
593
+ landing on the unchanged stub.
594
+ """
595
+
596
+ FIXTURES = [
597
+ # tracker, boards, scope, choice, expected
598
+ ("github", 0, True, "yes", "create"),
599
+ ("github", 0, True, "no", "stub"),
600
+ ("github", 0, True, None, "stub"),
601
+ ("github", 0, False, "yes", "stub"),
602
+ ("github", 1, True, None, "discover"),
603
+ ("github", 2, True, "yes", "stub"),
604
+ ("github", None, True, "yes", "stub"),
605
+ ("gitlab", 0, True, "yes", "not-applicable"),
606
+ ("local", 0, True, "yes", "not-applicable"),
607
+ ]
608
+
609
+ def test_decision_table(self):
610
+ for tracker, boards, scope, choice, expected in self.FIXTURES:
611
+ self.assertEqual(
612
+ board_branch_action(tracker, boards, scope, choice), expected,
613
+ f"{tracker}/{boards}/{scope}/{choice}",
614
+ )
615
+
616
+ def test_skill_offers_creation_on_both_surfaces(self):
617
+ for surface in (".claude", ".agents"):
618
+ skill = (REPO / surface / "skills/setup-workflow/SKILL.md").read_text(
619
+ encoding="utf-8")
620
+ for token in (
621
+ "python3 scripts/board_bootstrap.py create",
622
+ "--dry-run",
623
+ "never create a board without an explicit yes",
624
+ "Create it now",
625
+ "Not now",
626
+ "gh auth refresh -s project,read:project",
627
+ "state=filled",
628
+ ):
629
+ self.assertIn(token, skill, f"{surface} missing {token!r}")
630
+ # The refuted rationale must be gone: the CLI *can* provision the
631
+ # Status options via `--single-select-options`.
632
+ self.assertNotIn("cannot provision the Status options", skill)
633
+
634
+ def test_skill_routes_every_other_branch_to_the_unchanged_stub(self):
635
+ skill = (SKILL / "SKILL.md").read_text(encoding="utf-8")
636
+ fallback = skill.split("**Fallback", 1)
637
+ self.assertEqual(len(fallback), 2, "the stub fallback must survive")
638
+ for token in ("declined", "scope", "read failure", "state=stub", "Retryable"):
639
+ self.assertIn(token, fallback[1][:1200], f"stub path missing {token!r}")
640
+ self.assertIn("never hand-write a `state=filled` profile", skill)
641
+
642
+ def test_seed_documents_the_offer_and_keeps_the_manual_path(self):
643
+ seed = (SKILL / "board-sync.md").read_text(encoding="utf-8")
644
+ self.assertIn("board_bootstrap.py", seed)
645
+ self.assertIn("gh auth refresh -s project,read:project", seed)
646
+ self.assertIn("Re-run `/setup-workflow`", seed)
647
+
648
+
562
649
  class SentinelProtectsFilledProfile(unittest.TestCase):
563
650
  """A consumer's filled board profile must never be rewritten on rerun."""
564
651