@ikon85/agent-workflow-kit 0.43.0 → 0.44.1

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 (127) hide show
  1. package/.agents/skills/grill-me/SKILL.md +3 -1
  2. package/.agents/skills/grill-with-docs/SKILL.md +3 -1
  3. package/.agents/skills/kit-update/SKILL.md +9 -11
  4. package/.agents/skills/orchestrate-wave/SKILL.md +8 -8
  5. package/.agents/skills/setup-workflow/SKILL.md +20 -18
  6. package/.agents/skills/setup-workflow/board-sync.md +4 -1
  7. package/.agents/skills/setup-workflow/workflow-advisories.md +3 -2
  8. package/.agents/skills/setup-workflow/worktree-lifecycle.md +36 -31
  9. package/.agents/skills/to-issues/SKILL.md +43 -0
  10. package/.agents/skills/wrapup/SKILL.md +98 -54
  11. package/.claude/skills/grill-me/SKILL.md +3 -1
  12. package/.claude/skills/grill-me-codex/SKILL.md +3 -1
  13. package/.claude/skills/grill-with-docs/SKILL.md +3 -1
  14. package/.claude/skills/grill-with-docs-codex/SKILL.md +3 -1
  15. package/.claude/skills/kit-update/SKILL.md +9 -11
  16. package/.claude/skills/orchestrate-wave/SKILL.md +8 -8
  17. package/.claude/skills/setup-workflow/SKILL.md +20 -18
  18. package/.claude/skills/setup-workflow/board-sync.md +4 -1
  19. package/.claude/skills/setup-workflow/workflow-advisories.md +3 -2
  20. package/.claude/skills/setup-workflow/worktree-lifecycle.md +36 -31
  21. package/.claude/skills/skill-manifest.json +1 -1
  22. package/.claude/skills/to-issues/SKILL.md +43 -0
  23. package/.claude/skills/wrapup/SKILL.md +98 -54
  24. package/README.md +254 -7
  25. package/agent-workflow-kit.package.json +43 -43
  26. package/package.json +16 -12
  27. package/scripts/marker_lib.py +3 -0
  28. package/scripts/profile_globs.py +26 -45
  29. package/scripts/release-delta-guard.mjs +26 -9
  30. package/scripts/worktree-lifecycle/README.md +57 -160
  31. package/scripts/worktree-lifecycle/capabilities.json +2 -3
  32. package/scripts/worktree-lifecycle/classify.py +480 -0
  33. package/scripts/worktree-lifecycle/cleanup.py +9 -29
  34. package/scripts/worktree-lifecycle/core.py +68 -1429
  35. package/scripts/worktree-lifecycle/ignore_seed.py +1 -1
  36. package/scripts/worktree-lifecycle/profile.py +46 -29
  37. package/scripts/worktree-lifecycle/setup.py +7 -19
  38. package/scripts/wrapup-land.py +1292 -545
  39. package/src/consumer-migrations.json +1 -16
  40. package/src/lib/bundle.mjs +31 -1
  41. package/docs/adr/0001-consumer-divergence-policy.md +0 -53
  42. package/docs/adr/0002-capability-gated-orchestration.md +0 -70
  43. package/docs/adr/0003-kit-core-and-project-extension-lifecycle.md +0 -63
  44. package/docs/adr/0004-release-intent-is-a-version-tag.md +0 -64
  45. package/docs/adr/0005-to-issues-is-the-planning-facade.md +0 -42
  46. package/docs/adr/0006-routing-knowledge-access-and-policy-are-separate.md +0 -95
  47. package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +0 -88
  48. package/docs/adr/0008-planning-ignore-rules-are-offered-never-installed.md +0 -84
  49. package/docs/adr/0009-teardown-authority-is-stateless-repository-classification.md +0 -101
  50. package/docs/adr/0010-model-roster-replaces-the-optimization-dial.md +0 -87
  51. package/docs/agents/board-sync.md +0 -74
  52. package/docs/agents/code-review.md +0 -14
  53. package/docs/agents/workflow-capabilities.json +0 -28
  54. package/docs/research/agent-task-taxonomy-benchmark-coverage.md +0 -451
  55. package/docs/research/benchlm-routing-source.md +0 -198
  56. package/docs/research/consumer-owned-protocol-files.md +0 -238
  57. package/docs/research/frontend-agent-benchmarks.md +0 -282
  58. package/docs/research/model-effort-routing-benchmarks.md +0 -261
  59. package/docs/research/provider-neutral-agent-routing.md +0 -207
  60. package/docs/research/wave-152-consumer-acceptance.md +0 -98
  61. package/docs/research/wave-43-script-hook-census.md +0 -128
  62. package/scripts/build-kit.mjs +0 -117
  63. package/scripts/build-kit.test.mjs +0 -207
  64. package/scripts/census/census.test.mjs +0 -252
  65. package/scripts/census/state.test.mjs +0 -15
  66. package/scripts/census/transaction.test.mjs +0 -103
  67. package/scripts/census-contract.test.mjs +0 -227
  68. package/scripts/check-kit-staleness.mjs +0 -45
  69. package/scripts/check-kit-staleness.test.mjs +0 -19
  70. package/scripts/codex-exec-scenarios/fake-codex.mjs +0 -165
  71. package/scripts/codex-exec.test.mjs +0 -871
  72. package/scripts/grill-census-wiring-guard.mjs +0 -87
  73. package/scripts/grill-census-wiring-guard.test.mjs +0 -107
  74. package/scripts/kit-release.test.mjs +0 -273
  75. package/scripts/kit-update-pr.test.mjs +0 -151
  76. package/scripts/lib/audit-refs.mjs +0 -146
  77. package/scripts/lib/scrub.mjs +0 -113
  78. package/scripts/lib/scrub.test.mjs +0 -187
  79. package/scripts/memory-lifecycle/memory-lifecycle.test.mjs +0 -170
  80. package/scripts/portability_profile_scan.py +0 -53
  81. package/scripts/release-delta-guard.test.mjs +0 -174
  82. package/scripts/release-parity.test.mjs +0 -90
  83. package/scripts/release-state.test.mjs +0 -360
  84. package/scripts/test_anchor_table.py +0 -69
  85. package/scripts/test_board_bootstrap.py +0 -348
  86. package/scripts/test_board_sync.py +0 -208
  87. package/scripts/test_board_sync_create_idempotency.py +0 -117
  88. package/scripts/test_board_sync_wave_title.py +0 -120
  89. package/scripts/test_census_backstop.py +0 -712
  90. package/scripts/test_census_forward_contract.py +0 -91
  91. package/scripts/test_census_update_contract.test.mjs +0 -454
  92. package/scripts/test_codex_adapter_sync_contract.py +0 -169
  93. package/scripts/test_dist_kit_smoke.py +0 -220
  94. package/scripts/test_drift_guard_diagnostics.py +0 -295
  95. package/scripts/test_issue_claim_contract.py +0 -169
  96. package/scripts/test_kit_docs_language_census.py +0 -178
  97. package/scripts/test_marker_lib.py +0 -162
  98. package/scripts/test_orchestrate_wave_contract.py +0 -381
  99. package/scripts/test_pr_body_check.py +0 -264
  100. package/scripts/test_profile_globs.py +0 -280
  101. package/scripts/test_program_planning_contract.py +0 -133
  102. package/scripts/test_release_authorization_contract.py +0 -101
  103. package/scripts/test_render_anchor.py +0 -267
  104. package/scripts/test_retro_wrapup_contract.py +0 -153
  105. package/scripts/test_skill_code_review_seed.py +0 -89
  106. package/scripts/test_skill_codex_exec_lifecycle.py +0 -123
  107. package/scripts/test_skill_frontmatter_lint.py +0 -234
  108. package/scripts/test_skill_gh_lint.py +0 -124
  109. package/scripts/test_skill_language_census.py +0 -254
  110. package/scripts/test_skill_optional_readiness.py +0 -171
  111. package/scripts/test_skill_portability_lint.py +0 -866
  112. package/scripts/test_skill_precommit_template.py +0 -30
  113. package/scripts/test_skill_publish_audit.py +0 -358
  114. package/scripts/test_skill_readiness_contract.py +0 -264
  115. package/scripts/test_skill_readiness_preflight.py +0 -180
  116. package/scripts/test_skill_required_readiness.py +0 -233
  117. package/scripts/test_skill_selfcontainment_lint.py +0 -255
  118. package/scripts/test_skill_setup_workflow_seeds.py +0 -691
  119. package/scripts/test_skill_stale_name_lint.py +0 -126
  120. package/scripts/test_skill_surface_refs.py +0 -300
  121. package/scripts/test_skill_trailing_artifact_lint.py +0 -71
  122. package/scripts/test_tdd_contract.py +0 -78
  123. package/scripts/test_worktree_ignore_seed.py +0 -320
  124. package/scripts/test_worktree_setup_base_guard.py +0 -140
  125. package/scripts/test_worktree_wrapup_contract.py +0 -1737
  126. package/scripts/test_wrapup_land.py +0 -428
  127. package/scripts/worktree-lifecycle/session.py +0 -1857
@@ -1,117 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Regression test for marker-aware board issue creation."""
3
-
4
- from __future__ import annotations
5
-
6
- import importlib.util
7
- import json
8
- import os
9
- import tempfile
10
- import unittest
11
- from pathlib import Path
12
-
13
-
14
- PROFILE = {
15
- "repo": "example/kit",
16
- "project": {"number": 1, "owner": "example", "nodeId": "PVT_test"},
17
- "fields": {
18
- "status": {"id": "STATUS", "options": {}},
19
- "wave": "WAVE",
20
- "cluster": "CLUSTER",
21
- "specPath": "SPEC",
22
- "planPath": "PLAN",
23
- },
24
- "labels": {
25
- "readyForAgent": "ready-for-agent",
26
- "typePrefix": "type:",
27
- "clusterType": "type:cluster",
28
- "waveStub": "wave-stub",
29
- },
30
- "branchPrefixes": ["feat", "fix"],
31
- "prMarkers": {"partOf": "Part of", "retroMarker": "Retro", "retroValues": []},
32
- "headings": {"vorBau": "Clarify Before Build"},
33
- }
34
-
35
-
36
- def load_board_sync():
37
- previous_profile = os.environ.get("BOARD_SYNC_PROFILE")
38
- with tempfile.NamedTemporaryFile("w", suffix=".md", delete=False) as profile:
39
- profile.write("<!-- board-sync:profile -->\n```json\n")
40
- json.dump(PROFILE, profile)
41
- profile.write("\n```\n")
42
- profile_path = profile.name
43
- os.environ["BOARD_SYNC_PROFILE"] = profile_path
44
- spec = importlib.util.spec_from_file_location(
45
- "board_sync_create_test", Path(__file__).with_name("board-sync.py")
46
- )
47
- module = importlib.util.module_from_spec(spec)
48
- assert spec.loader is not None
49
- try:
50
- spec.loader.exec_module(module)
51
- finally:
52
- Path(profile_path).unlink()
53
- if previous_profile is None:
54
- os.environ.pop("BOARD_SYNC_PROFILE", None)
55
- else:
56
- os.environ["BOARD_SYNC_PROFILE"] = previous_profile
57
- return module
58
-
59
-
60
- PROFILE_BEFORE_LOAD = os.environ.get("BOARD_SYNC_PROFILE")
61
- bs = load_board_sync()
62
-
63
-
64
- class FakeGh:
65
- def __init__(self, marker: str):
66
- self.marker = marker
67
- self.created = False
68
- self.calls: list[list[str]] = []
69
-
70
- def __call__(self, args: list[str]) -> str:
71
- self.calls.append(args)
72
- joined = " ".join(args)
73
- if "issue list" in joined:
74
- if not self.created:
75
- return "[]"
76
- return json.dumps([
77
- {
78
- "number": 101,
79
- "url": "https://github.com/example/kit/issues/101",
80
- "body": self.marker,
81
- }
82
- ])
83
- if "issue create" in joined:
84
- self.created = True
85
- return "https://github.com/example/kit/issues/101\n"
86
- if "project item-add" in joined:
87
- return '{"id":"PVTI_test"}'
88
- return ""
89
-
90
-
91
- class BoardSyncImportIsolationTest(unittest.TestCase):
92
- def test_loading_board_sync_restores_the_caller_profile(self):
93
- self.assertEqual(os.environ.get("BOARD_SYNC_PROFILE"), PROFILE_BEFORE_LOAD)
94
-
95
-
96
- class MarkerAwareCreateTest(unittest.TestCase):
97
- def test_identical_program_leaf_retry_reuses_existing_issue(self):
98
- marker = "<!-- program-leaf-source: program-x/1a -->"
99
- fake = FakeGh(marker)
100
- original = bs._gh
101
- bs._gh = fake
102
- try:
103
- with tempfile.NamedTemporaryFile("w", suffix=".md") as body:
104
- body.write(marker + "\nOutcome: test\n")
105
- body.flush()
106
- argv = ["create", "--title", "Slice 1a", "--body-file", body.name]
107
- self.assertEqual(bs.main(argv), 0)
108
- self.assertEqual(bs.main(argv), 0)
109
- finally:
110
- bs._gh = original
111
-
112
- creates = [call for call in fake.calls if "issue create" in " ".join(call)]
113
- self.assertEqual(len(creates), 1)
114
-
115
-
116
- if __name__ == "__main__":
117
- unittest.main()
@@ -1,120 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Wave anchor titles take their prefix from the board profile, not a hardcoded
3
- German literal — an optional `titles.wavePrefix` key with the literal default
4
- `"Welle"` so every existing profile keeps working unchanged."""
5
-
6
- from __future__ import annotations
7
-
8
- import copy
9
- import importlib.util
10
- import json
11
- import os
12
- import tempfile
13
- import unittest
14
- from pathlib import Path
15
-
16
-
17
- BASE_PROFILE = {
18
- "repo": "example/kit",
19
- "project": {"number": 1, "owner": "example", "nodeId": "PVT_test"},
20
- "fields": {
21
- "status": {"id": "STATUS", "options": {}},
22
- "wave": "WAVE",
23
- "cluster": "CLUSTER",
24
- "specPath": "SPEC",
25
- "planPath": "PLAN",
26
- },
27
- "labels": {
28
- "readyForAgent": "ready-for-agent",
29
- "typePrefix": "type:",
30
- "clusterType": "type:cluster",
31
- "waveStub": "wave-stub",
32
- },
33
- "branchPrefixes": ["feat", "fix"],
34
- "prMarkers": {"partOf": "Part of", "retroMarker": "Retro", "retroValues": []},
35
- "headings": {"vorBau": "Clarify Before Build"},
36
- }
37
-
38
-
39
- def load_board_sync(profile_dict: dict, module_name: str):
40
- previous_profile = os.environ.get("BOARD_SYNC_PROFILE")
41
- with tempfile.NamedTemporaryFile("w", suffix=".md", delete=False) as profile:
42
- profile.write("<!-- board-sync:profile -->\n```json\n")
43
- json.dump(profile_dict, profile)
44
- profile.write("\n```\n")
45
- profile_path = profile.name
46
- os.environ["BOARD_SYNC_PROFILE"] = profile_path
47
- spec = importlib.util.spec_from_file_location(
48
- module_name, Path(__file__).with_name("board-sync.py")
49
- )
50
- module = importlib.util.module_from_spec(spec)
51
- assert spec.loader is not None
52
- try:
53
- spec.loader.exec_module(module)
54
- finally:
55
- Path(profile_path).unlink()
56
- if previous_profile is None:
57
- os.environ.pop("BOARD_SYNC_PROFILE", None)
58
- else:
59
- os.environ["BOARD_SYNC_PROFILE"] = previous_profile
60
- return module
61
-
62
-
63
- class WaveTitleDefaultPrefix(unittest.TestCase):
64
- """A profile without `titles.wavePrefix` keeps the historical `Welle` prefix."""
65
-
66
- @classmethod
67
- def setUpClass(cls):
68
- cls.bs = load_board_sync(copy.deepcopy(BASE_PROFILE), "board_sync_wave_default")
69
-
70
- def test_default_prefix_is_welle(self):
71
- self.assertEqual(self.bs.wave_title("Auth hardening", 7), "Welle 7 — Auth hardening")
72
-
73
- def test_repromote_is_idempotent(self):
74
- self.assertEqual(
75
- self.bs.wave_title("Welle 7 — Auth hardening", 9),
76
- "Welle 9 — Auth hardening",
77
- )
78
-
79
- def test_conventional_prefix_stripped_before_wave(self):
80
- self.assertEqual(
81
- self.bs.wave_title("fix: Welle 7 — Auth hardening", 29),
82
- "Welle 29 — Auth hardening",
83
- )
84
-
85
- def test_loading_board_sync_restores_the_caller_profile(self):
86
- before = os.environ.get("BOARD_SYNC_PROFILE")
87
- load_board_sync(copy.deepcopy(BASE_PROFILE), "board_sync_wave_isolation")
88
- self.assertEqual(os.environ.get("BOARD_SYNC_PROFILE"), before)
89
-
90
-
91
- class WaveTitleProfilePrefix(unittest.TestCase):
92
- """A profile with `titles.wavePrefix` drives the anchor title language."""
93
-
94
- @classmethod
95
- def setUpClass(cls):
96
- profile = copy.deepcopy(BASE_PROFILE)
97
- profile["titles"] = {"wavePrefix": "Wave"}
98
- cls.bs = load_board_sync(profile, "board_sync_wave_custom")
99
-
100
- def test_configured_prefix_is_used(self):
101
- self.assertEqual(self.bs.wave_title("Auth hardening", 7), "Wave 7 — Auth hardening")
102
-
103
- def test_repromote_is_idempotent_for_configured_prefix(self):
104
- self.assertEqual(
105
- self.bs.wave_title("Wave 7 — Auth hardening", 9),
106
- "Wave 9 — Auth hardening",
107
- )
108
-
109
- def test_regex_metacharacters_in_prefix_are_literal(self):
110
- profile = copy.deepcopy(BASE_PROFILE)
111
- profile["titles"] = {"wavePrefix": "W+A"}
112
- bs = load_board_sync(profile, "board_sync_wave_meta")
113
- self.assertEqual(
114
- bs.wave_title("W+A 3 — Auth hardening", 4),
115
- "W+A 4 — Auth hardening",
116
- )
117
-
118
-
119
- if __name__ == "__main__":
120
- unittest.main()