@ikon85/agent-workflow-kit 0.36.5 → 0.38.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 (46) hide show
  1. package/.agents/skills/orchestrate-wave/SKILL.md +20 -12
  2. package/.agents/skills/setup-workflow/SKILL.md +24 -3
  3. package/.agents/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
  4. package/.agents/skills/setup-workflow/worktree-lifecycle.md +29 -1
  5. package/.agents/skills/wrapup/SKILL.md +42 -9
  6. package/.claude/hooks/migration-snapshot-reminder.py +1 -1
  7. package/.claude/skills/orchestrate-wave/SKILL.md +11 -11
  8. package/.claude/skills/setup-workflow/SKILL.md +24 -3
  9. package/.claude/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
  10. package/.claude/skills/setup-workflow/worktree-lifecycle.md +29 -1
  11. package/.claude/skills/skill-manifest.json +1 -1
  12. package/.claude/skills/wrapup/SKILL.md +33 -10
  13. package/README.md +88 -1
  14. package/agent-workflow-kit.package.json +36 -28
  15. package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +88 -0
  16. package/docs/agents/workflow-capabilities.json +11 -0
  17. package/package.json +1 -1
  18. package/scripts/anchor_table.py +14 -8
  19. package/scripts/project-skill-extension.mjs +21 -2
  20. package/scripts/readiness.mjs +32 -4
  21. package/scripts/release-state.mjs +19 -9
  22. package/scripts/release-state.test.mjs +71 -8
  23. package/scripts/test_anchor_table.py +69 -0
  24. package/scripts/test_board_sync_create_idempotency.py +15 -2
  25. package/scripts/test_board_sync_wave_title.py +14 -2
  26. package/scripts/test_census_backstop.py +33 -0
  27. package/scripts/test_orchestrate_wave_contract.py +44 -0
  28. package/scripts/test_retro_wrapup_contract.py +19 -2
  29. package/scripts/test_worktree_wrapup_contract.py +1004 -3
  30. package/scripts/test_wrapup_land.py +428 -0
  31. package/scripts/workflow-advisories/core.py +44 -2
  32. package/scripts/worktree-lifecycle/README.md +126 -4
  33. package/scripts/worktree-lifecycle/capabilities.json +9 -1
  34. package/scripts/worktree-lifecycle/cleanup.py +143 -5
  35. package/scripts/worktree-lifecycle/core.py +1383 -20
  36. package/scripts/worktree-lifecycle/profile.py +40 -3
  37. package/scripts/worktree-lifecycle/session.py +1857 -0
  38. package/scripts/worktree-lifecycle/setup.py +15 -0
  39. package/scripts/wrapup-land.py +650 -27
  40. package/src/cli.mjs +60 -27
  41. package/src/lib/bundle.mjs +1 -0
  42. package/src/lib/manifest.mjs +173 -3
  43. package/src/lib/projectSkillExtension.mjs +78 -1
  44. package/src/lib/updateCandidate.mjs +3 -1
  45. package/src/lib/updateDecisions.mjs +2 -2
  46. package/src/lib/verifyUpdateCandidateProtocol.mjs +15 -0
@@ -1,6 +1,14 @@
1
1
  ---
2
2
  name: orchestrate-wave
3
- "description": "Use when the user hands you a whole WAVE / cluster of pre-planned, file-disjoint slices and wants you to ORCHESTRATE building, verifying AND landing it end-to-end — often AFK / \"ultracode\". Triggers: \"orchestriere Welle #N\" (or any wording that delegates wave-landing responsibility to you), \"ultracode diese Welle / diesen Cluster\", or a wave-anchor issue (a cluster/umbrella issue with file-disjoint sub-issues whose specs are already locked) handed over to land. NOT for a single slice (just `implement` it), NOT for finding/clustering a wave (that's `board-to-waves`), NOT for planning specs (that's `grill-with-docs`/`to-issues`)."
3
+ description: >-
4
+ Use when the user hands you a whole WAVE / cluster of pre-planned, file-disjoint
5
+ slices and wants you to ORCHESTRATE building, verifying AND landing it end-to-end —
6
+ often AFK / "ultracode". Triggers: "orchestriere Welle #N" (or any wording that
7
+ delegates wave-landing responsibility to you), "ultracode diese Welle / diesen
8
+ Cluster", or a wave-anchor issue (a cluster/umbrella issue with file-disjoint
9
+ sub-issues whose specs are already locked) handed over to land. NOT for a single
10
+ slice (just `implement` it), NOT for finding/clustering a wave (that's `board-to-waves`),
11
+ NOT for planning specs (that's `grill-with-docs`/`to-issues`).
4
12
  ---
5
13
 
6
14
  # Orchestrate Wave
@@ -25,9 +33,8 @@ node scripts/readiness.mjs check --skill orchestrate-wave --json
25
33
 
26
34
  - `ready`: continue silently with the required tracker/board context and the
27
35
  active `projectRecipe` block.
28
- - `degraded`: required tracker and managed-board evidence is ready, so keep the
29
- complete generic orchestration fallback active, omit only `projectRecipe`,
30
- and emit exactly one concise summary: `Readiness degraded — inactive block
36
+ - `degraded`: use generic fallback without `projectRecipe`, and emit exactly one
37
+ concise summary: `Readiness degraded inactive block
31
38
  projectRecipe (orchestrateWaveRecipe: <state>); using the generic
32
39
  orchestration fallback. Run /setup-workflow, configure
33
40
  docs/agents/skills/orchestrate-wave.md, then rerun this skill.`
@@ -134,7 +141,7 @@ replace the ~30-second heartbeat; otherwise the standing heartbeat remains requi
134
141
  LOCAL annotated tag, so two sessions racing one wave cannot both win. Either
135
142
  `acquired: false` or a work signal you did not create means another session
136
143
  owns the wave — **STOP**, report the returned `claim.owner` plus the exact
137
- branch/worktree, touch nothing. Local coordination state — never push the tag.
144
+ branch/worktree, touch nothing. After acquisition, begin the claim-bound teardown receipt with `python3 scripts/worktree-lifecycle/session.py begin --anchor <anchor> --owner <claim-owner> --base <wave-HEAD>`; claim and receipt stay local — never push them.
138
145
  4. **Wave worktree**: reuse the planning worktree (never re-create; the handoff
139
146
  points there). Bring its branch to current `main`:
140
147
  `git -C <wave> merge --ff-only origin/main` (if your repo guards destructive
@@ -154,8 +161,7 @@ preflight clean + this run's local claim planted · wave branch ff'd to
154
161
 
155
162
  Phase 1 uses the selected orchestration mechanics. Resolve every named component,
156
163
  produce the **FILE → SLICES** table and overlap graph, then build the conflict hub
157
- before its dependents. Cut fully file-disjoint waves; shared imports are safe, but
158
- files edited by multiple slices serialize across waves.
164
+ before its dependents. Cut fully file-disjoint waves; shared imports are safe, but files edited by multiple slices serialize across waves.
159
165
  - **Native blocking edges are the frontier authority.** Read the anchor's
160
166
  buildable frontier from the tracker's native issue dependencies:
161
167
  `python3 scripts/board-sync.py frontier <anchor#>` → `FREI` / `BLOCKED by #…` /
@@ -169,6 +175,7 @@ files edited by multiple slices serialize across waves.
169
175
  registries that read targets must serialize helper-owning slices through
170
176
  dependency edges, each appending only its own existing artifact after creation.
171
177
  Both preserve one owner per shared edit and the no-conflict invariant.
178
+ - **Producer/measurer coupling is a semantic dependency even when files are disjoint.** When one slice mutates a surface and another measures/baselines that surface in the same wave, either order the measurer strictly after the producer through an explicit edge so its baseline reflects post-mutation state, or assign an explicit baseline reconciliation owner at integration to drop producer-resolved entries from the measurer baseline.
172
179
  - **Retirement slices require a valid topological deletion order.** Before
173
180
  dispatching slices that delete a legacy cluster, map every to-delete module's
174
181
  production importers and build the cluster's internal import graph. Order the
@@ -179,7 +186,7 @@ files edited by multiple slices serialize across waves.
179
186
 
180
187
  **Done when:** FILE→SLICES table exists · each shared file has either one
181
188
  declaration-only owner with verbatim consume-only dependents, or an explicit serialized
182
- owner sequence for eager/validated additions where each owner appends only its own existing artifact · disjoint waves cut in dependency order.
189
+ owner sequence for eager/validated additions where each owner appends only its own existing artifact · every producer/measurer pair has an explicit edge/order or baseline reconciliation owner · disjoint waves cut in dependency order.
183
190
 
184
191
  ## Phase 2 — Dispatch one wave in parallel (isolated worktree per implementer)
185
192
 
@@ -188,8 +195,8 @@ disjoint wave, conflict hub first. Dispatch only `FREI` slices: re-read
188
195
  `frontier <anchor#>` before each wave and clear changed edges only via `dep-remove`.
189
196
  Before each slice, bind **(a) inline vs delegate** and **(b) tier + effort** under
190
197
  Standing rules. Tiny mechanical work may stay inline.
191
- For Path A/B, create one worktree per agent from wave HEAD, using `§Setup` or
192
- `git worktree add <path> -b feat/<anchor>-<slug>`.
198
+ For Path A/B, create each new worktree through the active receipt: `python3 scripts/worktree-lifecycle/session.py create --anchor <anchor> --owner <claim-owner> --base <wave-HEAD> --profile <profile> <slice-issue> <slug> <type>`.
199
+ It refuses reused/pre-existing targets; never replace this ownership proof with raw `git worktree add`.
193
200
  - **Claim each slice issue at builder launch — the wave claim is not a slice
194
201
  claim.** It guards the anchor on this machine only; the slice issue is the
195
202
  grabbable unit a second machine or cloud agent sees. Before dispatch, skip and
@@ -236,6 +243,7 @@ A single browser + single dev DB ⇒ verify is serial and yours. **A subagent's
236
243
  (real case: "gate PASS" while a size gate was red; files declared missing that
237
244
  existed). Never merge on the subagent's word.
238
245
 
246
+ - When builders authored or changed browser specs, treat each as an unverified artifact: if `§Verify Recipe` names a local e2e runner, give them ONE central green run with it before the central CI/verify gate. Never invent a command under generic fallback.
239
247
  - **Re-run your project's full CI/verify gate CENTRALLY yourself** (`§Verify
240
248
  Recipe`). On an integrated verify/coordinator branch (no per-slice issue number)
241
249
  a branch-name-derived guard can BLOCK with no matching baseline — a branch-naming
@@ -350,8 +358,8 @@ written · merge order documented.
350
358
  - A skill edited during the wave → sync its dual-surface mirror in the SAME PR
351
359
  using the tool named by `§Landing` when present; mirror parity remains a pre-PR
352
360
  gate.
353
- - Leave slice worktrees for the user to inspect, or note they're
354
- post-merge-removable.
361
+ - After reading every `ANNAHMEN.md`, seal the receipt, inspect it against fetched canonical `main`, then run its `teardown`; only ancestry/one-to-one patch-equivalent exact owned OIDs are compare-deleted, while foreign targets, unique/ambiguous content, changed OIDs, dirty/protected worktrees, and open/unknown PR evidence stop.
362
+ - Keep the completed receipt as recovery-OID evidence; only then release this run's wave claim.
355
363
 
356
364
  **Done when:** no orphan process · this run's wave claim removed · this run's
357
365
  unlanded slice claims released · ANNAHMEN propagated ·
@@ -72,6 +72,14 @@ supported as legacy v0 and are never rewritten merely to add the marker.
72
72
  Setup and update preserve every extension byte-for-byte unless a future,
73
73
  declared schema migration explicitly includes it.
74
74
 
75
+ Structured extensions whose Core contract requires every named section declare
76
+ an `all-sections-filled` activation policy and the exact section denominator in
77
+ the Kit readiness catalog. Runtime inspection and readiness both consume that
78
+ same policy, including for a preserved legacy Consumer file. Headings, HTML
79
+ comments, empty fences, placeholders, markers, and explanatory prose outside
80
+ the governed sections do not activate it. Existing v1 extensions without a
81
+ Core activation policy retain their ordinary non-empty-file behavior.
82
+
75
83
  Use an extension for Project language, commands, policy, and capability data
76
84
  that the Core skill already knows how to apply. It is additive and cannot
77
85
  weaken Core user gates, safety, ownership, or validation. Changes to parsing,
@@ -195,12 +203,16 @@ Worktree Lifecycle for this repository?"* Offer exactly **Yes**, **Later**, and
195
203
 
196
204
  - **Yes** — create or deepen only the `worktreeLifecycle` section in
197
205
  `docs/agents/workflow-capabilities.json`, preserve every other section and
198
- unknown key, and reconcile only the exact kit-owned hook commands listed in
199
- the seed.
206
+ unknown key, reconcile an explicit consumer-derived `scratchPatterns` array,
207
+ explicitly derive and review the consumer's
208
+ `wrapup.landingGeneratedArtifactPatterns` array from real landing outputs,
209
+ and reconcile only the exact kit-owned hook commands listed in the seed.
200
210
  - **Later / No** — record the choice in the tracked profile without installing
201
211
  hook wiring. Ordinary reruns do not ask again.
202
212
  - **Existing** — adopt the current section and wiring without normalizing
203
- consumer-owned values.
213
+ consumer-owned values. Preserve an existing landing-artifact policy
214
+ byte-for-byte; if it is missing, surface the explicit derivation decision and
215
+ do not write a default.
204
216
  - **Disable** — remove only the exact kit-owned hook commands first, then set
205
217
  `enabled: false`; retain the profile, setup policy, and unknown keys.
206
218
 
@@ -422,6 +434,12 @@ These are **structured-but-empty** crusts that `/retro` grows; do not ask the us
422
434
 
423
435
  - `docs/agents/skills/spec-self-critique.md` — seed the 12 per-point headings from [spec-self-critique-seed.md](./spec-self-critique-seed.md) so `/retro` has stable append anchors and `spec-self-critique` finds its project layer (suppressing the "layer absent" warning) without inventing project content.
424
436
  - `docs/agents/skills/orchestrate-wave.md` — seed the named `§`-section headings from [orchestrate-wave-seed.md](./orchestrate-wave-seed.md) so the `orchestrate-wave` skill's Phase-0 probe finds its project layer. The sections ship **empty** (the exact commands / tunnel / login can't be guessed) → the skill treats an unfilled seed as "layer absent" and runs its generic fallback until the project fills them. A filled section is a manual project-maintenance edit, not something this run invents.
437
+ - The `orchestrateWaveRecipe` readiness capability declares
438
+ `all-sections-filled` plus the seven named `§` sections. Every one must
439
+ contain real project instructions before either the runtime inspector or
440
+ readiness may activate `projectRecipe`. A comment-only or legacy seed remains
441
+ an intentional generic fallback even when its setup sentinel is
442
+ `state=filled`.
425
443
  - `docs/conventions/spec-completeness.md` — seed **one valid** `## Self-Critique-Check` block (Trigger/Check/Korrektur) from [spec-completeness-seed.md](./spec-completeness-seed.md). A convention file *without* a valid block makes `spec-self-critique` point 8 warn — an empty file is worse than none.
426
444
 
427
445
  > **Handoff drift-guard (`.claude/hooks/drift-guard.py`).** The repo ships a PreToolUse hook that blocks a `.handoff/*.md` Write when the linked issue's rooted graph is not execute-ready (it delegates all coherence to `scripts/execute-ready-check.py --mode handoff`). It self-filters to `.handoff/*.md` and fires **only once handoff docs exist** — a freshly scaffolded project carries the guard but has nothing to guard yet (silently inoperative until the first `.handoff/` write). This scaffold only **documents** the interplay; it does **not** build new mechanics. Once the project starts emitting handoffs, writes land in `.handoff/` and the guard activates automatically.
@@ -506,6 +524,9 @@ unknown consumer keys share this profile. Apply the transition and hook
506
524
  ownership rules from [worktree-lifecycle.md](./worktree-lifecycle.md),
507
525
  [workflow-advisories.md](./workflow-advisories.md), and
508
526
  [safety-guardrails.md](./safety-guardrails.md) transactionally.
527
+ The landing-artifact policy is deletion authority: it is always an explicit
528
+ consumer-reviewed setup value, never an update-time default or an inference
529
+ from ignored paths.
509
530
 
510
531
  For Memory Lifecycle, use only the deterministic setup helper from Section A5.
511
532
  Do not copy templates with shell commands or edit the capability profile by
@@ -10,8 +10,9 @@ detail. The skill probes it at runtime (Phase 0); with the sections below
10
10
 
11
11
  > **Section contract.** The skeleton refers to these exact headings by name.
12
12
  > Keep them; fill each with your project's real detail. While a section is empty
13
- > the skill treats the whole layer as absent (Phase-0 sentinel-stub rule) and
14
- > falls back to generic instructions — so fill them before relying on the recipe.
13
+ > the Kit Core `all-sections-filled` readiness policy treats the whole layer as
14
+ > absent and the skill falls back to generic instructions — so fill them before
15
+ > relying on the recipe.
15
16
 
16
17
  ## §Setup
17
18
  <!-- Project setup steps Phase 0 runs before verify: DB/tunnel/services the
@@ -29,6 +29,7 @@ advisory, and safe cleanup policy as one unit.
29
29
  "operations": [
30
30
  "record-choice",
31
31
  "reconcile-profile-enabled",
32
+ "reconcile-landing-artifact-policy",
32
33
  "reconcile-hook-wiring"
33
34
  ]
34
35
  },
@@ -50,7 +51,8 @@ advisory, and safe cleanup policy as one unit.
50
51
  "state": "existing",
51
52
  "choice": "yes",
52
53
  "operations": [
53
- "adopt-existing"
54
+ "adopt-existing",
55
+ "reconcile-landing-artifact-policy"
54
56
  ]
55
57
  },
56
58
  {
@@ -79,3 +81,29 @@ The exact kit-owned commands are:
79
81
 
80
82
  Preserve unrelated settings, hook groups, profile sections, and unknown keys.
81
83
  Repeated reconciliation with the same choice is byte-identical.
84
+
85
+ ## Scratch classification and sweep
86
+
87
+ Reconcile an explicit `scratchPatterns` array when enabling a new profile.
88
+ Derive its glob values from the consumer's ignored planning artefacts; an empty
89
+ array is valid. Existing values are consumer-owned and remain byte-identical on
90
+ adoption or rerun. Core never supplies filename defaults.
91
+
92
+ Also reconcile an explicit
93
+ `wrapup.landingGeneratedArtifactPatterns` array. Derive candidates from the
94
+ consumer's real landing commands and ignored outputs, show the exact list for
95
+ review, and write it only as part of that explicit setup decision. Never copy
96
+ another repository's values or infer deletion authority from `.gitignore`
97
+ alone. An empty array is valid. Existing configured values remain byte-identical.
98
+ If an existing enabled profile lacks the key, report one actionable setup
99
+ decision and leave the project layer unchanged until the consumer confirms the
100
+ derived list.
101
+
102
+ Patterns use repository-relative POSIX semantics: `*` stays within one segment,
103
+ while `**` crosses `/`; a leading `**/` also matches the repository root.
104
+ Thus `**/__pycache__/**` covers root and nested caches, while `dist-kit/*` does
105
+ not cover `dist-kit/a/b`.
106
+
107
+ The shipped read-only inventory is
108
+ `python3 scripts/worktree-lifecycle/cleanup.py sweep`. The same profile powers
109
+ its branch issue extraction and scratch-only cleanup verdicts.
@@ -1,7 +1,18 @@
1
1
  ---
2
2
  name: wrapup
3
3
  disable-model-invocation: true
4
- "description": "Use ONLY when the user types /wrapup. Session-end \"land & clean\" for a finished feature/fix worktree — merges the open PR, kills the worktree dev server, removes the worktree + local branch, and fast-forwards the main checkout so main is current again, then sweeps merged-branch leftovers (local + stale remote whose PR is merged). If the slice isn't landed yet, it first makes it landable (Step 0): commits a dirty tree (after an .env/secret check), pushes, and opens the PR — reusing one if it already exists. User-triggered only (never auto-invoke, never hook). Aborts hard only on: not in a feature worktree, a detected .env/secret, a rejected push, a conflicting PR, or red (FAILURE) checks."
4
+ description: >-
5
+ Use ONLY when the user directly types $wrapup or /wrapup. Session-end "land & clean" for a
6
+ finished feature/fix worktree — merges the open PR,
7
+ kills the worktree dev server, removes the worktree + local branch, and
8
+ fast-forwards the main checkout so main is current again, then sweeps
9
+ merged-branch leftovers (local + stale remote whose PR is merged). If the
10
+ slice isn't landed yet, it first makes it landable (Step 0): commits a dirty
11
+ tree (after an .env/secret check), pushes, and opens the PR — reusing one if
12
+ it already exists. User-triggered only (never auto-invoke, never hook). Aborts
13
+ hard only on: not in a feature worktree, a detected .env/secret, a rejected
14
+ push, a conflicting PR, terminal red checks, or checks still pending after
15
+ the bounded wait budget.
5
16
  ---
6
17
 
7
18
  <!-- project-extension:protocol-v1:start -->
@@ -14,15 +25,15 @@ Project extensions may specialize Project details, but cannot weaken Core user g
14
25
 
15
26
  # wrapup — land PR & tear down worktree
16
27
 
17
- Trigger: user types `/wrapup` (optionally with a PR number). **Manual only** — `disable-model-invocation: true`, no hook, no auto-invoke.
28
+ Trigger: user makes a direct `$wrapup` or `/wrapup` invocation (optionally with a PR number). **Manual only** — `disable-model-invocation: true`, no hook, no auto-invoke.
18
29
 
19
30
  ## ⚠ Spec context
20
31
 
21
- The user's `/wrapup` input IS the explicit landing authorization for that run.
32
+ The user's direct `$wrapup` or `/wrapup` input IS the explicit landing authorization for that run.
22
33
  It authorizes the normal merge flow whether Prod readiness is ready or degraded;
23
34
  it never authorizes the agent to invent or configure a deploy target. Never call
24
- this skill from a hook, another skill, or autonomously. There is no second merge
25
- confirmation; the pre-flight hard stops are non-negotiable.
35
+ this skill from a hook or another skill. Natural-language requests, indirect skill
36
+ chaining, and autonomous invocation do not authorize it. There is no second merge confirmation; the pre-flight hard stops are non-negotiable.
26
37
 
27
38
  ## Execution model — script does mechanics, the agent does judgment
28
39
 
@@ -52,12 +63,12 @@ conflicting instruction surfaces; never choose a target on the user's behalf.
52
63
 
53
64
  ### 2 · Retro gate (blocking, optional retro-exit — before anything is committed)
54
65
  One reminder, not a merge confirmation:
55
- > "Already ran a retro? **(a)** yes / continue → landing now. **(b)** you want one first → the retro starts now; afterwards, invoke `/wrapup` again — repo-file patches then travel in this PR."
66
+ > "Already ran a retro? **(a)** yes / continue → landing now. **(b)** you want one first → the retro starts now; afterwards, invoke `$wrapup` or `/wrapup` again — repo-file patches then travel in this PR."
56
67
 
57
68
  (b) → **invoke the `retro` skill immediately in this run.** Retro is
58
69
  model-invocable and non-deploying, and every mutation still has its own approval
59
70
  gate. After retro finishes, **land nothing in this run**. Require a **fresh
60
- explicit `/wrapup` invocation** because retro may have changed the exact diff
71
+ explicit `$wrapup` or `/wrapup` invocation** because retro may have changed the exact diff
61
72
  that the next merge authorization covers.
62
73
 
63
74
  General chaining rule: automatically chain only into a **model-invocable**,
@@ -90,10 +101,32 @@ Run **from the main tree** (the script refuses inside the worktree — an in-wor
90
101
  ```bash
91
102
  python3 scripts/wrapup-land.py land --branch "<branch>" --title "<title>" --body-file /tmp/wrapup-pr-body.md
92
103
  ```
93
- One call covers: push → PR create/reuse (+ drift markers merged into the body) → `pr-body-check.py` gate (exit 1 = STOP, exit 2 = fail-open warning) → merge gate (red check / `CONFLICTING` = STOP; fresh-PR `UNKNOWN` mergeable passes the merge itself is the real gate) → **merge** (`--merge` + `--delete-branch`, verified `MERGED`) → dev-server kill (`.dev-ports` ports + cwd-under-worktree walk, own shell ancestry excluded) → worktree remove (no `--force`; refusal = STOP, check surviving processes first) → main `--ff-only` pull + `branch -d` → issue-close verify (auto-close misses are closed manually) → local merged-branch sweep (`-d` only — squash/rebase-merged branches stay a manual call by design) → remote merged-PR sweep (opt-in `wrapup.remoteBranchSweep` in the board profile; PR-status-authoritative via `ls-remote`; deleted remote branches are restorable from the PR page) → anchor-sync (dry-run diff in the report) + anchor completeness check + `execute-ready-check --mode audit` → **upward propagation:** if the anchor's native parent is a Program-PRD, `program-sync` refreshes its Wellenplan (Status + Issue cells) and checks off mechanically completed Phasen-Gates — the slice event is visible at the program level, not only in the wave (`program_sync` block in the report; skipped when the parent isn't a program).
104
+ One call covers: push → PR create/reuse (+ drift markers merged into the body) → `pr-body-check.py` gate (exit 1 = STOP, exit 2 = fail-open warning) → merge gate (pending/null-conclusion checks poll for up to 20 minutes with progress on stderr; terminal red / `CONFLICTING` / timeout = STOP; known zero-step billing or runner failures are named `infrastructure failure`; an already-`MERGED` PR resumes at teardown) → **merge** (`--merge` + `--delete-branch`, verified `MERGED`) → dev-server kill (`.dev-ports` ports + cwd-under-worktree walk, own shell ancestry excluded) → worktree remove (no `--force`; refusal = STOP, check surviving processes first) → main `--ff-only` pull + `branch -d` → issue-close verify (auto-close misses are closed manually) → local merged-branch sweep (`-d` only — squash/rebase-merged branches stay a manual call by design) → remote merged-PR sweep (opt-in `wrapup.remoteBranchSweep` in the board profile; PR-status-authoritative via `ls-remote`; deleted remote branches are restorable from the PR page) → anchor-sync (dry-run diff in the report) + anchor completeness check + `execute-ready-check --mode audit` → **upward propagation:** if the anchor's native parent is a Program-PRD, `program-sync` refreshes its Wellenplan (Status + Issue cells) and checks off mechanically completed Phasen-Gates — the slice event is visible at the program level, not only in the wave (`program_sync` block in the report; skipped when the parent isn't a program).
94
105
 
95
106
  STOP → diagnose in the main conversation, fix, re-run `land` (an already-merged PR resumes at teardown).
96
107
 
108
+ Before merge, the committed worktree policy only nominates exact landing
109
+ evidence. After merge, cleanup reloads `docs/agents/workflow-capabilities.json`
110
+ from canonical `origin/main`; only the identical merged, attempt-bound scratch
111
+ and generator policy authorizes each evidence path and deletion. A mismatch is
112
+ a hard STOP that preserves every file—never bypass it with the unmerged branch
113
+ profile.
114
+
115
+ Landing provenance has one explicit relinquish route. If the STOP names an
116
+ unfinished or drifted landing attempt and the ambiguous files cannot be restored
117
+ to their frozen identities, run:
118
+
119
+ ```bash
120
+ python3 scripts/wrapup-land.py land --branch "<branch>" --abandon-unfinished-attempt
121
+ ```
122
+
123
+ This archives the started or frozen attempt receipt only. It deletes and claims
124
+ no files, works even when the older creation baseline is missing, and returns
125
+ before push, PR, or merge. The next `land` conservatively protects every current
126
+ matching path; classify or move those blockers first. Do not use relinquish for
127
+ an exact unchanged frozen attempt: a normal retry validates that evidence and
128
+ resumes deterministically.
129
+
97
130
  ### 6 · Post-merge (agent)
98
131
  - **Sibling propagation:** for each `drift_markers` entry in the land report, append the note to the target issue's `vor_bau` section + re-stamp its `plan_revision`. Log-based markers → **write directly, then show what was written where** (mandatory report — visibility moved from a pre-gate into the report, decision 2026-07-06); fallback candidates the user hasn't confirmed yet → confirm first. Program context widens the target set to unbuilt wave-stubs/leaves and the Program-PRD itself — same append-only mechanism. **Exception:** appends to the Program-PRD or unbuilt wave-stubs do **not** re-stamp `plan_revision` — that stays reserved for structural wave-plan edits via the `to-waves` escalation path; a mere drift note must not stale-block published stubs.
99
132
  - **Anchor close:** report says `anchor_complete: true` → `gh issue close <anchor> -c "Wave complete — all slices merged via PR #<pr>."` and verify board status Done. The guard keeps anchors away from every auto-close — this verified close is the only close path; without it the anchor stays silently open after the last slice. **Then re-run the upward propagation**: the land-time `program-sync` ran BEFORE this close, so on a wave-completing slice the Wellenplan still shows 🔄 and the Phasen-Gate stays unchecked — after the board shows Done, run `python3 scripts/board-sync.py program-sync <program-prd#>` once more (the report's `program_sync.program` names it; skip when the report says the parent is not a program). Board auto-rules can lag the close (Close→Done race) — verify Done first, that's what the token reads.
@@ -108,5 +141,5 @@ STOP → diagnose in the main conversation, fix, re-run `land` (an already-merge
108
141
  <!-- readiness:end -->
109
142
 
110
143
  ## Out of scope
111
- - Live-verify / DoD: must happen **before** `/wrapup` — this skill lands, it does not verify.
144
+ - Live-verify / DoD: must happen **before** `$wrapup` or `/wrapup` — this skill lands, it does not verify.
112
145
  - Other worktrees / their servers stay untouched.
@@ -12,7 +12,7 @@ def main() -> int:
12
12
  payload = json.load(sys.stdin)
13
13
  core = load_workflow_advisories_core()
14
14
  profile = core.load_profile(Path("docs/agents/workflow-capabilities.json"))
15
- decision = core.migration_reminder_decision(profile, payload)
15
+ decision = core.migration_reminder_decision(profile, payload, Path.cwd())
16
16
  if decision.context:
17
17
  print(json.dumps(hook_event_output(decision.event_name, decision.context)))
18
18
  except Exception:
@@ -33,9 +33,8 @@ node scripts/readiness.mjs check --skill orchestrate-wave --json
33
33
 
34
34
  - `ready`: continue silently with the required tracker/board context and the
35
35
  active `projectRecipe` block.
36
- - `degraded`: required tracker and managed-board evidence is ready, so keep the
37
- complete generic orchestration fallback active, omit only `projectRecipe`,
38
- and emit exactly one concise summary: `Readiness degraded — inactive block
36
+ - `degraded`: use generic fallback without `projectRecipe`, and emit exactly one
37
+ concise summary: `Readiness degraded inactive block
39
38
  projectRecipe (orchestrateWaveRecipe: <state>); using the generic
40
39
  orchestration fallback. Run /setup-workflow, configure
41
40
  docs/agents/skills/orchestrate-wave.md, then rerun this skill.`
@@ -142,7 +141,7 @@ replace the ~30-second heartbeat; otherwise the standing heartbeat remains requi
142
141
  LOCAL annotated tag, so two sessions racing one wave cannot both win. Either
143
142
  `acquired: false` or a work signal you did not create means another session
144
143
  owns the wave — **STOP**, report the returned `claim.owner` plus the exact
145
- branch/worktree, touch nothing. Local coordination state — never push the tag.
144
+ branch/worktree, touch nothing. After acquisition, begin the claim-bound teardown receipt with `python3 scripts/worktree-lifecycle/session.py begin --anchor <anchor> --owner <claim-owner> --base <wave-HEAD>`; claim and receipt stay local — never push them.
146
145
  4. **Wave worktree**: reuse the planning worktree (never re-create; the handoff
147
146
  points there). Bring its branch to current `main`:
148
147
  `git -C <wave> merge --ff-only origin/main` (if your repo guards destructive
@@ -162,8 +161,7 @@ preflight clean + this run's local claim planted · wave branch ff'd to
162
161
 
163
162
  Phase 1 uses the selected orchestration mechanics. Resolve every named component,
164
163
  produce the **FILE → SLICES** table and overlap graph, then build the conflict hub
165
- before its dependents. Cut fully file-disjoint waves; shared imports are safe, but
166
- files edited by multiple slices serialize across waves.
164
+ before its dependents. Cut fully file-disjoint waves; shared imports are safe, but files edited by multiple slices serialize across waves.
167
165
  - **Native blocking edges are the frontier authority.** Read the anchor's
168
166
  buildable frontier from the tracker's native issue dependencies:
169
167
  `python3 scripts/board-sync.py frontier <anchor#>` → `FREI` / `BLOCKED by #…` /
@@ -177,6 +175,7 @@ files edited by multiple slices serialize across waves.
177
175
  registries that read targets must serialize helper-owning slices through
178
176
  dependency edges, each appending only its own existing artifact after creation.
179
177
  Both preserve one owner per shared edit and the no-conflict invariant.
178
+ - **Producer/measurer coupling is a semantic dependency even when files are disjoint.** When one slice mutates a surface and another measures/baselines that surface in the same wave, either order the measurer strictly after the producer through an explicit edge so its baseline reflects post-mutation state, or assign an explicit baseline reconciliation owner at integration to drop producer-resolved entries from the measurer baseline.
180
179
  - **Retirement slices require a valid topological deletion order.** Before
181
180
  dispatching slices that delete a legacy cluster, map every to-delete module's
182
181
  production importers and build the cluster's internal import graph. Order the
@@ -187,7 +186,7 @@ files edited by multiple slices serialize across waves.
187
186
 
188
187
  **Done when:** FILE→SLICES table exists · each shared file has either one
189
188
  declaration-only owner with verbatim consume-only dependents, or an explicit serialized
190
- owner sequence for eager/validated additions where each owner appends only its own existing artifact · disjoint waves cut in dependency order.
189
+ owner sequence for eager/validated additions where each owner appends only its own existing artifact · every producer/measurer pair has an explicit edge/order or baseline reconciliation owner · disjoint waves cut in dependency order.
191
190
 
192
191
  ## Phase 2 — Dispatch one wave in parallel (isolated worktree per implementer)
193
192
 
@@ -196,8 +195,8 @@ disjoint wave, conflict hub first. Dispatch only `FREI` slices: re-read
196
195
  `frontier <anchor#>` before each wave and clear changed edges only via `dep-remove`.
197
196
  Before each slice, bind **(a) inline vs delegate** and **(b) tier + effort** under
198
197
  Standing rules. Tiny mechanical work may stay inline.
199
- For Path A/B, create one worktree per agent from wave HEAD, using `§Setup` or
200
- `git worktree add <path> -b feat/<anchor>-<slug>`.
198
+ For Path A/B, create each new worktree through the active receipt: `python3 scripts/worktree-lifecycle/session.py create --anchor <anchor> --owner <claim-owner> --base <wave-HEAD> --profile <profile> <slice-issue> <slug> <type>`.
199
+ It refuses reused/pre-existing targets; never replace this ownership proof with raw `git worktree add`.
201
200
  - **Claim each slice issue at builder launch — the wave claim is not a slice
202
201
  claim.** It guards the anchor on this machine only; the slice issue is the
203
202
  grabbable unit a second machine or cloud agent sees. Before dispatch, skip and
@@ -244,6 +243,7 @@ A single browser + single dev DB ⇒ verify is serial and yours. **A subagent's
244
243
  (real case: "gate PASS" while a size gate was red; files declared missing that
245
244
  existed). Never merge on the subagent's word.
246
245
 
246
+ - When builders authored or changed browser specs, treat each as an unverified artifact: if `§Verify Recipe` names a local e2e runner, give them ONE central green run with it before the central CI/verify gate. Never invent a command under generic fallback.
247
247
  - **Re-run your project's full CI/verify gate CENTRALLY yourself** (`§Verify
248
248
  Recipe`). On an integrated verify/coordinator branch (no per-slice issue number)
249
249
  a branch-name-derived guard can BLOCK with no matching baseline — a branch-naming
@@ -358,8 +358,8 @@ written · merge order documented.
358
358
  - A skill edited during the wave → sync its dual-surface mirror in the SAME PR
359
359
  using the tool named by `§Landing` when present; mirror parity remains a pre-PR
360
360
  gate.
361
- - Leave slice worktrees for the user to inspect, or note they're
362
- post-merge-removable.
361
+ - After reading every `ANNAHMEN.md`, seal the receipt, inspect it against fetched canonical `main`, then run its `teardown`; only ancestry/one-to-one patch-equivalent exact owned OIDs are compare-deleted, while foreign targets, unique/ambiguous content, changed OIDs, dirty/protected worktrees, and open/unknown PR evidence stop.
362
+ - Keep the completed receipt as recovery-OID evidence; only then release this run's wave claim.
363
363
 
364
364
  **Done when:** no orphan process · this run's wave claim removed · this run's
365
365
  unlanded slice claims released · ANNAHMEN propagated ·
@@ -72,6 +72,14 @@ supported as legacy v0 and are never rewritten merely to add the marker.
72
72
  Setup and update preserve every extension byte-for-byte unless a future,
73
73
  declared schema migration explicitly includes it.
74
74
 
75
+ Structured extensions whose Core contract requires every named section declare
76
+ an `all-sections-filled` activation policy and the exact section denominator in
77
+ the Kit readiness catalog. Runtime inspection and readiness both consume that
78
+ same policy, including for a preserved legacy Consumer file. Headings, HTML
79
+ comments, empty fences, placeholders, markers, and explanatory prose outside
80
+ the governed sections do not activate it. Existing v1 extensions without a
81
+ Core activation policy retain their ordinary non-empty-file behavior.
82
+
75
83
  Use an extension for Project language, commands, policy, and capability data
76
84
  that the Core skill already knows how to apply. It is additive and cannot
77
85
  weaken Core user gates, safety, ownership, or validation. Changes to parsing,
@@ -195,12 +203,16 @@ Worktree Lifecycle for this repository?"* Offer exactly **Yes**, **Later**, and
195
203
 
196
204
  - **Yes** — create or deepen only the `worktreeLifecycle` section in
197
205
  `docs/agents/workflow-capabilities.json`, preserve every other section and
198
- unknown key, and reconcile only the exact kit-owned hook commands listed in
199
- the seed.
206
+ unknown key, reconcile an explicit consumer-derived `scratchPatterns` array,
207
+ explicitly derive and review the consumer's
208
+ `wrapup.landingGeneratedArtifactPatterns` array from real landing outputs,
209
+ and reconcile only the exact kit-owned hook commands listed in the seed.
200
210
  - **Later / No** — record the choice in the tracked profile without installing
201
211
  hook wiring. Ordinary reruns do not ask again.
202
212
  - **Existing** — adopt the current section and wiring without normalizing
203
- consumer-owned values.
213
+ consumer-owned values. Preserve an existing landing-artifact policy
214
+ byte-for-byte; if it is missing, surface the explicit derivation decision and
215
+ do not write a default.
204
216
  - **Disable** — remove only the exact kit-owned hook commands first, then set
205
217
  `enabled: false`; retain the profile, setup policy, and unknown keys.
206
218
 
@@ -422,6 +434,12 @@ These are **structured-but-empty** crusts that `/retro` grows; do not ask the us
422
434
 
423
435
  - `docs/agents/skills/spec-self-critique.md` — seed the 12 per-point headings from [spec-self-critique-seed.md](./spec-self-critique-seed.md) so `/retro` has stable append anchors and `spec-self-critique` finds its project layer (suppressing the "layer absent" warning) without inventing project content.
424
436
  - `docs/agents/skills/orchestrate-wave.md` — seed the named `§`-section headings from [orchestrate-wave-seed.md](./orchestrate-wave-seed.md) so the `orchestrate-wave` skill's Phase-0 probe finds its project layer. The sections ship **empty** (the exact commands / tunnel / login can't be guessed) → the skill treats an unfilled seed as "layer absent" and runs its generic fallback until the project fills them. A filled section is a manual project-maintenance edit, not something this run invents.
437
+ - The `orchestrateWaveRecipe` readiness capability declares
438
+ `all-sections-filled` plus the seven named `§` sections. Every one must
439
+ contain real project instructions before either the runtime inspector or
440
+ readiness may activate `projectRecipe`. A comment-only or legacy seed remains
441
+ an intentional generic fallback even when its setup sentinel is
442
+ `state=filled`.
425
443
  - `docs/conventions/spec-completeness.md` — seed **one valid** `## Self-Critique-Check` block (Trigger/Check/Korrektur) from [spec-completeness-seed.md](./spec-completeness-seed.md). A convention file *without* a valid block makes `spec-self-critique` point 8 warn — an empty file is worse than none.
426
444
 
427
445
  > **Handoff drift-guard (`.claude/hooks/drift-guard.py`).** The repo ships a PreToolUse hook that blocks a `.handoff/*.md` Write when the linked issue's rooted graph is not execute-ready (it delegates all coherence to `scripts/execute-ready-check.py --mode handoff`). It self-filters to `.handoff/*.md` and fires **only once handoff docs exist** — a freshly scaffolded project carries the guard but has nothing to guard yet (silently inoperative until the first `.handoff/` write). This scaffold only **documents** the interplay; it does **not** build new mechanics. Once the project starts emitting handoffs, writes land in `.handoff/` and the guard activates automatically.
@@ -506,6 +524,9 @@ unknown consumer keys share this profile. Apply the transition and hook
506
524
  ownership rules from [worktree-lifecycle.md](./worktree-lifecycle.md),
507
525
  [workflow-advisories.md](./workflow-advisories.md), and
508
526
  [safety-guardrails.md](./safety-guardrails.md) transactionally.
527
+ The landing-artifact policy is deletion authority: it is always an explicit
528
+ consumer-reviewed setup value, never an update-time default or an inference
529
+ from ignored paths.
509
530
 
510
531
  For Memory Lifecycle, use only the deterministic setup helper from Section A5.
511
532
  Do not copy templates with shell commands or edit the capability profile by
@@ -10,8 +10,9 @@ detail. The skill probes it at runtime (Phase 0); with the sections below
10
10
 
11
11
  > **Section contract.** The skeleton refers to these exact headings by name.
12
12
  > Keep them; fill each with your project's real detail. While a section is empty
13
- > the skill treats the whole layer as absent (Phase-0 sentinel-stub rule) and
14
- > falls back to generic instructions — so fill them before relying on the recipe.
13
+ > the Kit Core `all-sections-filled` readiness policy treats the whole layer as
14
+ > absent and the skill falls back to generic instructions — so fill them before
15
+ > relying on the recipe.
15
16
 
16
17
  ## §Setup
17
18
  <!-- Project setup steps Phase 0 runs before verify: DB/tunnel/services the
@@ -29,6 +29,7 @@ advisory, and safe cleanup policy as one unit.
29
29
  "operations": [
30
30
  "record-choice",
31
31
  "reconcile-profile-enabled",
32
+ "reconcile-landing-artifact-policy",
32
33
  "reconcile-hook-wiring"
33
34
  ]
34
35
  },
@@ -50,7 +51,8 @@ advisory, and safe cleanup policy as one unit.
50
51
  "state": "existing",
51
52
  "choice": "yes",
52
53
  "operations": [
53
- "adopt-existing"
54
+ "adopt-existing",
55
+ "reconcile-landing-artifact-policy"
54
56
  ]
55
57
  },
56
58
  {
@@ -79,3 +81,29 @@ The exact kit-owned commands are:
79
81
 
80
82
  Preserve unrelated settings, hook groups, profile sections, and unknown keys.
81
83
  Repeated reconciliation with the same choice is byte-identical.
84
+
85
+ ## Scratch classification and sweep
86
+
87
+ Reconcile an explicit `scratchPatterns` array when enabling a new profile.
88
+ Derive its glob values from the consumer's ignored planning artefacts; an empty
89
+ array is valid. Existing values are consumer-owned and remain byte-identical on
90
+ adoption or rerun. Core never supplies filename defaults.
91
+
92
+ Also reconcile an explicit
93
+ `wrapup.landingGeneratedArtifactPatterns` array. Derive candidates from the
94
+ consumer's real landing commands and ignored outputs, show the exact list for
95
+ review, and write it only as part of that explicit setup decision. Never copy
96
+ another repository's values or infer deletion authority from `.gitignore`
97
+ alone. An empty array is valid. Existing configured values remain byte-identical.
98
+ If an existing enabled profile lacks the key, report one actionable setup
99
+ decision and leave the project layer unchanged until the consumer confirms the
100
+ derived list.
101
+
102
+ Patterns use repository-relative POSIX semantics: `*` stays within one segment,
103
+ while `**` crosses `/`; a leading `**/` also matches the repository root.
104
+ Thus `**/__pycache__/**` covers root and nested caches, while `dist-kit/*` does
105
+ not cover `dist-kit/a/b`.
106
+
107
+ The shipped read-only inventory is
108
+ `python3 scripts/worktree-lifecycle/cleanup.py sweep`. The same profile powers
109
+ its branch issue extraction and scratch-only cleanup verdicts.
@@ -12,7 +12,7 @@
12
12
  "projectReleaseProfile": { "evidence": { "type": "json", "paths": ["docs/agents/workflow-capabilities.json"], "validator": "project-release" } },
13
13
  "securityAuditRunbook": { "evidence": { "type": "runbook-reference", "paths": ["docs/agents/skills/security-audit.md"], "allowLegacy": true } },
14
14
  "prodTarget": { "evidence": { "type": "prod-section", "paths": ["CLAUDE.md", "AGENTS.md"] } },
15
- "orchestrateWaveRecipe": { "evidence": { "type": "sentinel", "paths": ["docs/agents/skills/orchestrate-wave.md"], "allowLegacy": true } },
15
+ "orchestrateWaveRecipe": { "evidence": { "type": "project-extension", "skill": "orchestrate-wave", "paths": ["docs/agents/skills/orchestrate-wave.md"], "activation": { "mode": "all-sections-filled", "sections": ["§Setup", "§Builder Commands", "§Builder Hard Rules", "§Integration Suites", "§Verify Recipe", "§Headless Login", "§Landing"] } } },
16
16
  "specCritiqueLayer": { "evidence": { "type": "sentinel", "paths": ["docs/agents/skills/spec-self-critique.md"], "allowLegacy": true } },
17
17
  "codeReviewLayer": { "evidence": { "type": "sentinel", "paths": ["docs/agents/code-review.md"], "allowLegacy": true } },
18
18
  "verifySpikeLayer": { "evidence": { "type": "sentinel", "paths": ["docs/agents/skills/verify-spike.md"], "allowLegacy": true } },