@ikon85/agent-workflow-kit 0.42.1 → 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 (133) 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 +268 -7
  24. package/agent-workflow-kit.package.json +42 -42
  25. package/package.json +16 -2
  26. package/scripts/marker_lib.py +3 -0
  27. package/scripts/profile_globs.py +26 -45
  28. package/scripts/release-delta-guard.mjs +29 -4
  29. package/scripts/worktree-lifecycle/README.md +57 -154
  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 -1289
  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/domain.md +0 -7
  53. package/docs/agents/issue-tracker.md +0 -23
  54. package/docs/agents/skills/local-ci.md +0 -90
  55. package/docs/agents/skills/orchestrate-wave.md +0 -166
  56. package/docs/agents/skills/spec-self-critique.md +0 -18
  57. package/docs/agents/triage-labels.md +0 -10
  58. package/docs/agents/workflow-capabilities.json +0 -28
  59. package/docs/conventions/spec-completeness.md +0 -23
  60. package/docs/research/agent-task-taxonomy-benchmark-coverage.md +0 -451
  61. package/docs/research/benchlm-routing-source.md +0 -198
  62. package/docs/research/consumer-owned-protocol-files.md +0 -238
  63. package/docs/research/frontend-agent-benchmarks.md +0 -282
  64. package/docs/research/model-effort-routing-benchmarks.md +0 -261
  65. package/docs/research/provider-neutral-agent-routing.md +0 -207
  66. package/docs/research/wave-152-consumer-acceptance.md +0 -98
  67. package/docs/research/wave-43-script-hook-census.md +0 -128
  68. package/scripts/build-kit.mjs +0 -117
  69. package/scripts/build-kit.test.mjs +0 -204
  70. package/scripts/census/census.test.mjs +0 -252
  71. package/scripts/census/state.test.mjs +0 -15
  72. package/scripts/census/transaction.test.mjs +0 -103
  73. package/scripts/census-contract.test.mjs +0 -227
  74. package/scripts/check-kit-staleness.mjs +0 -45
  75. package/scripts/check-kit-staleness.test.mjs +0 -19
  76. package/scripts/codex-exec-scenarios/fake-codex.mjs +0 -152
  77. package/scripts/codex-exec.test.mjs +0 -871
  78. package/scripts/grill-census-wiring-guard.mjs +0 -87
  79. package/scripts/grill-census-wiring-guard.test.mjs +0 -107
  80. package/scripts/kit-release.test.mjs +0 -273
  81. package/scripts/kit-update-pr.test.mjs +0 -151
  82. package/scripts/lib/audit-refs.mjs +0 -146
  83. package/scripts/lib/scrub.mjs +0 -113
  84. package/scripts/lib/scrub.test.mjs +0 -187
  85. package/scripts/memory-lifecycle/memory-lifecycle.test.mjs +0 -170
  86. package/scripts/portability_profile_scan.py +0 -53
  87. package/scripts/release-delta-guard.test.mjs +0 -151
  88. package/scripts/release-parity.test.mjs +0 -90
  89. package/scripts/release-state.test.mjs +0 -360
  90. package/scripts/test_anchor_table.py +0 -69
  91. package/scripts/test_board_bootstrap.py +0 -348
  92. package/scripts/test_board_sync.py +0 -208
  93. package/scripts/test_board_sync_create_idempotency.py +0 -117
  94. package/scripts/test_board_sync_wave_title.py +0 -120
  95. package/scripts/test_census_backstop.py +0 -712
  96. package/scripts/test_census_forward_contract.py +0 -91
  97. package/scripts/test_census_update_contract.test.mjs +0 -454
  98. package/scripts/test_codex_adapter_sync_contract.py +0 -169
  99. package/scripts/test_dist_kit_smoke.py +0 -220
  100. package/scripts/test_drift_guard_diagnostics.py +0 -295
  101. package/scripts/test_issue_claim_contract.py +0 -169
  102. package/scripts/test_kit_docs_language_census.py +0 -178
  103. package/scripts/test_marker_lib.py +0 -162
  104. package/scripts/test_orchestrate_wave_contract.py +0 -381
  105. package/scripts/test_pr_body_check.py +0 -264
  106. package/scripts/test_profile_globs.py +0 -280
  107. package/scripts/test_program_planning_contract.py +0 -133
  108. package/scripts/test_release_authorization_contract.py +0 -101
  109. package/scripts/test_render_anchor.py +0 -267
  110. package/scripts/test_retro_wrapup_contract.py +0 -153
  111. package/scripts/test_skill_code_review_seed.py +0 -89
  112. package/scripts/test_skill_codex_exec_lifecycle.py +0 -123
  113. package/scripts/test_skill_frontmatter_lint.py +0 -234
  114. package/scripts/test_skill_gh_lint.py +0 -124
  115. package/scripts/test_skill_language_census.py +0 -254
  116. package/scripts/test_skill_optional_readiness.py +0 -171
  117. package/scripts/test_skill_portability_lint.py +0 -866
  118. package/scripts/test_skill_precommit_template.py +0 -30
  119. package/scripts/test_skill_publish_audit.py +0 -358
  120. package/scripts/test_skill_readiness_contract.py +0 -264
  121. package/scripts/test_skill_readiness_preflight.py +0 -180
  122. package/scripts/test_skill_required_readiness.py +0 -233
  123. package/scripts/test_skill_selfcontainment_lint.py +0 -255
  124. package/scripts/test_skill_setup_workflow_seeds.py +0 -691
  125. package/scripts/test_skill_stale_name_lint.py +0 -126
  126. package/scripts/test_skill_surface_refs.py +0 -300
  127. package/scripts/test_skill_trailing_artifact_lint.py +0 -71
  128. package/scripts/test_tdd_contract.py +0 -78
  129. package/scripts/test_worktree_ignore_seed.py +0 -320
  130. package/scripts/test_worktree_setup_base_guard.py +0 -140
  131. package/scripts/test_worktree_wrapup_contract.py +0 -1648
  132. package/scripts/test_wrapup_land.py +0 -428
  133. 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()