@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.
- package/.agents/skills/kit-update/SKILL.md +33 -1
- package/.agents/skills/orchestrate-wave/SKILL.md +5 -5
- package/.agents/skills/setup-workflow/SKILL.md +42 -4
- package/.agents/skills/setup-workflow/board-sync.md +6 -2
- package/.agents/skills/setup-workflow/workflow-advisories.md +34 -0
- package/.agents/skills/setup-workflow/worktree-lifecycle.md +47 -1
- package/.agents/skills/wrapup/SKILL.md +46 -0
- package/.claude/hooks/drift-guard.py +212 -21
- package/.claude/skills/kit-update/SKILL.md +33 -1
- package/.claude/skills/orchestrate-wave/SKILL.md +5 -5
- package/.claude/skills/setup-workflow/SKILL.md +42 -4
- package/.claude/skills/setup-workflow/board-sync.md +6 -2
- package/.claude/skills/setup-workflow/workflow-advisories.md +34 -0
- package/.claude/skills/setup-workflow/worktree-lifecycle.md +47 -1
- package/.claude/skills/wrapup/SKILL.md +46 -0
- package/README.md +73 -0
- package/agent-workflow-kit.package.json +49 -25
- package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +88 -0
- package/docs/agents/workflow-capabilities.json +11 -1
- package/package.json +1 -1
- package/scripts/board_bootstrap.py +367 -0
- package/scripts/kit-update-pr.mjs +20 -7
- package/scripts/kit-update-pr.test.mjs +29 -0
- package/scripts/profile_globs.py +347 -0
- package/scripts/test_board_bootstrap.py +348 -0
- package/scripts/test_drift_guard_diagnostics.py +295 -0
- package/scripts/test_orchestrate_wave_contract.py +9 -0
- package/scripts/test_profile_globs.py +280 -0
- package/scripts/test_skill_setup_workflow_seeds.py +87 -0
- package/scripts/test_worktree_wrapup_contract.py +1592 -3
- package/scripts/workflow-advisories/core.py +29 -4
- package/scripts/worktree-lifecycle/README.md +139 -0
- package/scripts/worktree-lifecycle/capabilities.json +9 -1
- package/scripts/worktree-lifecycle/cleanup.py +22 -51
- package/scripts/worktree-lifecycle/core.py +1206 -5
- package/scripts/worktree-lifecycle/profile.py +38 -3
- package/scripts/worktree-lifecycle/session.py +1857 -0
- package/scripts/worktree-lifecycle/setup.py +15 -0
- package/scripts/wrapup-land.py +461 -14
- package/src/cli.mjs +32 -1
- package/src/commands/update.mjs +30 -21
- package/src/consumer-migrations.json +19 -0
- package/src/lib/bundle.mjs +11 -0
- 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
|
|