@ikon85/agent-workflow-kit 0.43.0 → 0.44.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 (126) 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/to-issues/SKILL.md +43 -0
  22. package/.claude/skills/wrapup/SKILL.md +98 -54
  23. package/README.md +249 -7
  24. package/agent-workflow-kit.package.json +42 -42
  25. package/package.json +16 -12
  26. package/scripts/marker_lib.py +3 -0
  27. package/scripts/profile_globs.py +26 -45
  28. package/scripts/release-delta-guard.mjs +26 -9
  29. package/scripts/worktree-lifecycle/README.md +57 -160
  30. package/scripts/worktree-lifecycle/capabilities.json +2 -3
  31. package/scripts/worktree-lifecycle/classify.py +480 -0
  32. package/scripts/worktree-lifecycle/cleanup.py +9 -29
  33. package/scripts/worktree-lifecycle/core.py +68 -1429
  34. package/scripts/worktree-lifecycle/ignore_seed.py +1 -1
  35. package/scripts/worktree-lifecycle/profile.py +46 -29
  36. package/scripts/worktree-lifecycle/setup.py +7 -19
  37. package/scripts/wrapup-land.py +1292 -545
  38. package/src/consumer-migrations.json +1 -16
  39. package/src/lib/bundle.mjs +31 -1
  40. package/docs/adr/0001-consumer-divergence-policy.md +0 -53
  41. package/docs/adr/0002-capability-gated-orchestration.md +0 -70
  42. package/docs/adr/0003-kit-core-and-project-extension-lifecycle.md +0 -63
  43. package/docs/adr/0004-release-intent-is-a-version-tag.md +0 -64
  44. package/docs/adr/0005-to-issues-is-the-planning-facade.md +0 -42
  45. package/docs/adr/0006-routing-knowledge-access-and-policy-are-separate.md +0 -95
  46. package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +0 -88
  47. package/docs/adr/0008-planning-ignore-rules-are-offered-never-installed.md +0 -84
  48. package/docs/adr/0009-teardown-authority-is-stateless-repository-classification.md +0 -101
  49. package/docs/adr/0010-model-roster-replaces-the-optimization-dial.md +0 -87
  50. package/docs/agents/board-sync.md +0 -74
  51. package/docs/agents/code-review.md +0 -14
  52. package/docs/agents/workflow-capabilities.json +0 -28
  53. package/docs/research/agent-task-taxonomy-benchmark-coverage.md +0 -451
  54. package/docs/research/benchlm-routing-source.md +0 -198
  55. package/docs/research/consumer-owned-protocol-files.md +0 -238
  56. package/docs/research/frontend-agent-benchmarks.md +0 -282
  57. package/docs/research/model-effort-routing-benchmarks.md +0 -261
  58. package/docs/research/provider-neutral-agent-routing.md +0 -207
  59. package/docs/research/wave-152-consumer-acceptance.md +0 -98
  60. package/docs/research/wave-43-script-hook-census.md +0 -128
  61. package/scripts/build-kit.mjs +0 -117
  62. package/scripts/build-kit.test.mjs +0 -207
  63. package/scripts/census/census.test.mjs +0 -252
  64. package/scripts/census/state.test.mjs +0 -15
  65. package/scripts/census/transaction.test.mjs +0 -103
  66. package/scripts/census-contract.test.mjs +0 -227
  67. package/scripts/check-kit-staleness.mjs +0 -45
  68. package/scripts/check-kit-staleness.test.mjs +0 -19
  69. package/scripts/codex-exec-scenarios/fake-codex.mjs +0 -165
  70. package/scripts/codex-exec.test.mjs +0 -871
  71. package/scripts/grill-census-wiring-guard.mjs +0 -87
  72. package/scripts/grill-census-wiring-guard.test.mjs +0 -107
  73. package/scripts/kit-release.test.mjs +0 -273
  74. package/scripts/kit-update-pr.test.mjs +0 -151
  75. package/scripts/lib/audit-refs.mjs +0 -146
  76. package/scripts/lib/scrub.mjs +0 -113
  77. package/scripts/lib/scrub.test.mjs +0 -187
  78. package/scripts/memory-lifecycle/memory-lifecycle.test.mjs +0 -170
  79. package/scripts/portability_profile_scan.py +0 -53
  80. package/scripts/release-delta-guard.test.mjs +0 -174
  81. package/scripts/release-parity.test.mjs +0 -90
  82. package/scripts/release-state.test.mjs +0 -360
  83. package/scripts/test_anchor_table.py +0 -69
  84. package/scripts/test_board_bootstrap.py +0 -348
  85. package/scripts/test_board_sync.py +0 -208
  86. package/scripts/test_board_sync_create_idempotency.py +0 -117
  87. package/scripts/test_board_sync_wave_title.py +0 -120
  88. package/scripts/test_census_backstop.py +0 -712
  89. package/scripts/test_census_forward_contract.py +0 -91
  90. package/scripts/test_census_update_contract.test.mjs +0 -454
  91. package/scripts/test_codex_adapter_sync_contract.py +0 -169
  92. package/scripts/test_dist_kit_smoke.py +0 -220
  93. package/scripts/test_drift_guard_diagnostics.py +0 -295
  94. package/scripts/test_issue_claim_contract.py +0 -169
  95. package/scripts/test_kit_docs_language_census.py +0 -178
  96. package/scripts/test_marker_lib.py +0 -162
  97. package/scripts/test_orchestrate_wave_contract.py +0 -381
  98. package/scripts/test_pr_body_check.py +0 -264
  99. package/scripts/test_profile_globs.py +0 -280
  100. package/scripts/test_program_planning_contract.py +0 -133
  101. package/scripts/test_release_authorization_contract.py +0 -101
  102. package/scripts/test_render_anchor.py +0 -267
  103. package/scripts/test_retro_wrapup_contract.py +0 -153
  104. package/scripts/test_skill_code_review_seed.py +0 -89
  105. package/scripts/test_skill_codex_exec_lifecycle.py +0 -123
  106. package/scripts/test_skill_frontmatter_lint.py +0 -234
  107. package/scripts/test_skill_gh_lint.py +0 -124
  108. package/scripts/test_skill_language_census.py +0 -254
  109. package/scripts/test_skill_optional_readiness.py +0 -171
  110. package/scripts/test_skill_portability_lint.py +0 -866
  111. package/scripts/test_skill_precommit_template.py +0 -30
  112. package/scripts/test_skill_publish_audit.py +0 -358
  113. package/scripts/test_skill_readiness_contract.py +0 -264
  114. package/scripts/test_skill_readiness_preflight.py +0 -180
  115. package/scripts/test_skill_required_readiness.py +0 -233
  116. package/scripts/test_skill_selfcontainment_lint.py +0 -255
  117. package/scripts/test_skill_setup_workflow_seeds.py +0 -691
  118. package/scripts/test_skill_stale_name_lint.py +0 -126
  119. package/scripts/test_skill_surface_refs.py +0 -300
  120. package/scripts/test_skill_trailing_artifact_lint.py +0 -71
  121. package/scripts/test_tdd_contract.py +0 -78
  122. package/scripts/test_worktree_ignore_seed.py +0 -320
  123. package/scripts/test_worktree_setup_base_guard.py +0 -140
  124. package/scripts/test_worktree_wrapup_contract.py +0 -1737
  125. package/scripts/test_wrapup_land.py +0 -428
  126. 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()