@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
@@ -5,7 +5,7 @@ The shipped skills write `PLAN.md`, `PLAN-REVIEW-LOG.md`, and `ANNAHMEN.md`
5
5
  into a session worktree, but `.gitignore` is a consumer file the kit does not
6
6
  own: `init` and `update` never touch it. This helper is the one place that
7
7
  closes that gap, and it closes it only when a user explicitly approves the
8
- offer inside `/setup-workflow` (ADR 0008).
8
+ offer inside `/setup-workflow`.
9
9
 
10
10
  Contract:
11
11
 
@@ -1,4 +1,21 @@
1
- """Worktree Lifecycle profile loading and low-level git operations."""
1
+ """Worktree Lifecycle profile loading and low-level git operations.
2
+
3
+ The profile carries **structural facts only** — worktree root, naming
4
+ templates, the protected branches, the setup sequence. Deletion policy has
5
+ exactly one configuration surface, the ignore mechanism, so no pattern list is
6
+ read here. Keys this loader does not know are ignored in silence: a profile
7
+ written for an older kit keeps working, and an obsolete key produces no warning
8
+ noise.
9
+
10
+ Two branch templates exist because two kinds of work land. `branchTemplate`
11
+ names the branch of an issue-anchored slice; `contentBranchTemplate` names the
12
+ issue-less branch a session cuts for durable content, so it renders `{type}`
13
+ and `{slug}` only and refuses `{issue}` outright rather than inventing a number.
14
+
15
+ `DEFAULT_MAIN_BRANCHES` is the single place in the kit that names an
16
+ integration branch at all; every command, test, and message resolves the name
17
+ through the profile instead of assuming it.
18
+ """
2
19
 
3
20
  from __future__ import annotations
4
21
 
@@ -9,6 +26,9 @@ from dataclasses import dataclass
9
26
  from pathlib import Path
10
27
  from typing import Any
11
28
 
29
+ DEFAULT_MAIN_BRANCHES = ("main", "master")
30
+ DEFAULT_CONTENT_BRANCH_TEMPLATE = "{type}/{slug}"
31
+
12
32
 
13
33
  class LifecycleError(RuntimeError):
14
34
  """A safe, user-visible lifecycle refusal."""
@@ -18,6 +38,7 @@ class LifecycleError(RuntimeError):
18
38
  class WorktreeProfile:
19
39
  root: str
20
40
  branch_template: str
41
+ content_branch_template: str
21
42
  path_template: str
22
43
  main_branches: tuple[str, ...]
23
44
  protected_branches: tuple[str, ...]
@@ -25,15 +46,16 @@ class WorktreeProfile:
25
46
  branch_regex: str
26
47
  setup_entry: str
27
48
  risky_command_patterns: tuple[str, ...]
28
- scratch_patterns: tuple[str, ...]
29
- landing_generated_artifact_policy_configured: bool
30
- landing_generated_artifact_patterns: tuple[str, ...]
31
49
 
32
50
  def branch_name(self, issue: str, slug: str, branch_type: str) -> str:
33
- return _render(self.branch_template, issue, slug, branch_type)
51
+ return _render(self.branch_template, issue=issue, slug=slug, type=branch_type)
52
+
53
+ def content_branch_name(self, slug: str, branch_type: str) -> str:
54
+ """Name the issue-less branch of a Content-route session."""
55
+ return render_content_branch(self.content_branch_template, slug, branch_type)
34
56
 
35
57
  def relative_path(self, issue: str, slug: str, branch_type: str) -> Path:
36
- name = _render(self.path_template, issue, slug, branch_type)
58
+ name = _render(self.path_template, issue=issue, slug=slug, type=branch_type)
37
59
  return Path(self.root) / name
38
60
 
39
61
  def issue_from_branch(self, branch: str) -> str | None:
@@ -41,14 +63,25 @@ class WorktreeProfile:
41
63
  return match.groupdict().get("issue") if match else None
42
64
 
43
65
 
44
- def _render(template: str, issue: str, slug: str, branch_type: str) -> str:
45
- values = {"issue": issue, "slug": slug, "type": branch_type}
66
+ def _render(template: str, **values: str) -> str:
67
+ """Render a profile template from exactly the placeholders it may use."""
46
68
  try:
47
69
  return template.format(**values)
48
- except (KeyError, ValueError) as error:
70
+ except (KeyError, IndexError, ValueError) as error:
49
71
  raise LifecycleError(f"invalid worktree template: {error}") from error
50
72
 
51
73
 
74
+ def render_content_branch(template: str, slug: str, branch_type: str) -> str:
75
+ """Render one issue-less content branch name — the placeholder policy's home.
76
+
77
+ A caller that reads the template out of a raw profile document (wrapup's
78
+ Content route does, because it must work whether or not the worktree
79
+ lifecycle itself is enabled) renders it here, so `{issue}` is refused in
80
+ exactly one place instead of two.
81
+ """
82
+ return _render(template, slug=slug, type=branch_type)
83
+
84
+
52
85
  def _load_profile_document(document: Any) -> WorktreeProfile:
53
86
  try:
54
87
  raw = document["worktreeLifecycle"]
@@ -56,26 +89,13 @@ def _load_profile_document(document: Any) -> WorktreeProfile:
56
89
  raise LifecycleError(f"cannot load worktree lifecycle profile: {error}") from error
57
90
  if raw.get("enabled") is not True:
58
91
  raise LifecycleError("worktree lifecycle is not enabled")
59
- wrapup = document.get("wrapup")
60
- if wrapup is None:
61
- wrapup = {}
62
- if not isinstance(wrapup, dict):
63
- raise LifecycleError("invalid wrapup profile")
64
- generated_policy_configured = "landingGeneratedArtifactPatterns" in wrapup
65
- generated_patterns = (
66
- wrapup["landingGeneratedArtifactPatterns"]
67
- if generated_policy_configured
68
- else ()
69
- )
70
- if (
71
- not isinstance(generated_patterns, (list, tuple))
72
- or not all(isinstance(pattern, str) and pattern for pattern in generated_patterns)
73
- ):
74
- raise LifecycleError("invalid wrapup landingGeneratedArtifactPatterns")
75
- main = tuple(raw.get("mainBranches") or ("main", "master"))
92
+ main = tuple(raw.get("mainBranches") or DEFAULT_MAIN_BRANCHES)
76
93
  return WorktreeProfile(
77
94
  root=raw.get("worktreeRoot", ".worktrees"),
78
95
  branch_template=raw.get("branchTemplate", "{type}/{issue}-{slug}"),
96
+ content_branch_template=raw.get(
97
+ "contentBranchTemplate", DEFAULT_CONTENT_BRANCH_TEMPLATE,
98
+ ),
79
99
  path_template=raw.get("pathTemplate", "{type}-{issue}-{slug}"),
80
100
  main_branches=main,
81
101
  protected_branches=tuple(raw.get("protectedBranches") or main),
@@ -92,9 +112,6 @@ def _load_profile_document(document: Any) -> WorktreeProfile:
92
112
  r"\b(?:npm|pnpm|yarn)\s+(?:run\s+)?(?:test|typecheck|build)\b",
93
113
  r"\bgit\s+(?:commit|push)\b",
94
114
  )),
95
- scratch_patterns=tuple(raw.get("scratchPatterns") or ()),
96
- landing_generated_artifact_policy_configured=generated_policy_configured,
97
- landing_generated_artifact_patterns=tuple(generated_patterns),
98
115
  )
99
116
 
100
117
 
@@ -10,9 +10,6 @@ import zlib
10
10
  from pathlib import Path
11
11
 
12
12
  from core import (
13
- BaselineBackfillDeferred,
14
- capture_artifact_baseline,
15
- ensure_artifact_baseline,
16
13
  LifecycleError,
17
14
  load_profile,
18
15
  local_branch_exists,
@@ -25,7 +22,9 @@ from core import (
25
22
  def parse_args() -> argparse.Namespace:
26
23
  parser = argparse.ArgumentParser()
27
24
  parser.add_argument("--profile", default="docs/agents/workflow-capabilities.json")
28
- parser.add_argument("--base", default="origin/main")
25
+ # Resolved from the consumer profile when omitted — the integration
26
+ # branch is never named inline.
27
+ parser.add_argument("--base")
29
28
  parser.add_argument("issue")
30
29
  parser.add_argument("slug")
31
30
  parser.add_argument("branch_type", nargs="?", default="feat")
@@ -133,34 +132,24 @@ def create(args: argparse.Namespace) -> Path:
133
132
  if not profile_path.is_absolute():
134
133
  profile_path = main / profile_path
135
134
  profile = load_profile(profile_path)
135
+ base = args.base or f"origin/{profile.main_branches[0]}"
136
136
  branch = profile.branch_name(args.issue, args.slug, args.branch_type)
137
137
  target = (main / profile.relative_path(args.issue, args.slug, args.branch_type)).resolve()
138
138
 
139
139
  if target in registered_worktrees(main):
140
140
  ensure_reusable_base(
141
- main, repo=target, rev="HEAD", base=args.base, label=f"worktree {target}"
141
+ main, repo=target, rev="HEAD", base=base, label=f"worktree {target}"
142
142
  )
143
- try:
144
- ensure_artifact_baseline(
145
- target,
146
- reject_ignored_patterns=profile.landing_generated_artifact_patterns,
147
- )
148
- except BaselineBackfillDeferred as error:
149
- print(
150
- "Baseline backfill deferred; preserve the worktree, remove generated "
151
- f"blockers or commit/stash tracked work, then retry: {error}",
152
- file=sys.stderr,
153
- )
154
143
  print(f"Worktree already exists: {target} ({branch})")
155
144
  return target
156
145
 
157
146
  branch_existed = local_branch_exists(main, branch)
158
147
  if branch_existed:
159
148
  ensure_reusable_base(
160
- main, repo=main, rev=branch, base=args.base, label=f"branch {branch}"
149
+ main, repo=main, rev=branch, base=base, label=f"branch {branch}"
161
150
  )
162
151
  command = ["git", "worktree", "add", str(target)]
163
- command += [branch] if branch_existed else ["-b", branch, args.base]
152
+ command += [branch] if branch_existed else ["-b", branch, base]
164
153
  run(command, cwd=main)
165
154
  try:
166
155
  for step in profile.setup_steps:
@@ -171,7 +160,6 @@ def create(args: argparse.Namespace) -> Path:
171
160
  issue=args.issue,
172
161
  branch=branch,
173
162
  )
174
- capture_artifact_baseline(target)
175
163
  except Exception:
176
164
  remove_failed_worktree(main, target, branch, not branch_existed)
177
165
  raise