@ikon85/agent-workflow-kit 0.36.4 → 0.37.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 (43) hide show
  1. package/.agents/skills/orchestrate-wave/SKILL.md +15 -7
  2. package/.agents/skills/setup-workflow/SKILL.md +16 -2
  3. package/.agents/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
  4. package/.agents/skills/setup-workflow/worktree-lifecycle.md +11 -0
  5. package/.agents/skills/wrapup/SKILL.md +20 -9
  6. package/.claude/hooks/migration-snapshot-reminder.py +1 -1
  7. package/.claude/skills/orchestrate-wave/SKILL.md +6 -6
  8. package/.claude/skills/setup-workflow/SKILL.md +16 -2
  9. package/.claude/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
  10. package/.claude/skills/setup-workflow/worktree-lifecycle.md +11 -0
  11. package/.claude/skills/skill-manifest.json +1 -1
  12. package/.claude/skills/wrapup/SKILL.md +11 -10
  13. package/README.md +59 -1
  14. package/agent-workflow-kit.package.json +26 -26
  15. package/docs/agents/workflow-capabilities.json +1 -0
  16. package/package.json +1 -1
  17. package/scripts/anchor_table.py +14 -8
  18. package/scripts/project-skill-extension.mjs +21 -2
  19. package/scripts/readiness.mjs +32 -4
  20. package/scripts/release-state.mjs +19 -9
  21. package/scripts/release-state.test.mjs +71 -8
  22. package/scripts/test_anchor_table.py +69 -0
  23. package/scripts/test_board_sync_create_idempotency.py +15 -2
  24. package/scripts/test_board_sync_wave_title.py +14 -2
  25. package/scripts/test_census_backstop.py +33 -0
  26. package/scripts/test_orchestrate_wave_contract.py +35 -0
  27. package/scripts/test_retro_wrapup_contract.py +19 -2
  28. package/scripts/test_wrapup_land.py +428 -0
  29. package/scripts/workflow-advisories/core.py +44 -2
  30. package/scripts/worktree-lifecycle/README.md +18 -4
  31. package/scripts/worktree-lifecycle/cleanup.py +173 -6
  32. package/scripts/worktree-lifecycle/core.py +331 -18
  33. package/scripts/worktree-lifecycle/profile.py +2 -0
  34. package/scripts/wrapup-land.py +336 -15
  35. package/src/cli.mjs +60 -27
  36. package/src/lib/manifest.mjs +173 -3
  37. package/src/lib/projectSkillExtension.mjs +78 -1
  38. package/src/lib/updateCandidate.mjs +11 -1
  39. package/src/lib/updateDecisions.mjs +2 -2
  40. package/src/lib/updateReconcile.mjs +6 -0
  41. package/src/lib/verifyUpdateCandidate.mjs +6 -3
  42. package/src/lib/verifyUpdateCandidateProtocol.mjs +15 -0
  43. package/src/lib/verifyUpdateCandidateTransaction.mjs +23 -1
@@ -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.`
@@ -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
 
@@ -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
@@ -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,8 +203,8 @@ 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
+ and reconcile only the exact kit-owned hook commands listed in the seed.
200
208
  - **Later / No** — record the choice in the tracked profile without installing
201
209
  hook wiring. Ordinary reruns do not ask again.
202
210
  - **Existing** — adopt the current section and wiring without normalizing
@@ -422,6 +430,12 @@ These are **structured-but-empty** crusts that `/retro` grows; do not ask the us
422
430
 
423
431
  - `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
432
  - `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.
433
+ - The `orchestrateWaveRecipe` readiness capability declares
434
+ `all-sections-filled` plus the seven named `§` sections. Every one must
435
+ contain real project instructions before either the runtime inspector or
436
+ readiness may activate `projectRecipe`. A comment-only or legacy seed remains
437
+ an intentional generic fallback even when its setup sentinel is
438
+ `state=filled`.
425
439
  - `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
440
 
427
441
  > **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.
@@ -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
@@ -79,3 +79,14 @@ The exact kit-owned commands are:
79
79
 
80
80
  Preserve unrelated settings, hook groups, profile sections, and unknown keys.
81
81
  Repeated reconciliation with the same choice is byte-identical.
82
+
83
+ ## Scratch classification and sweep
84
+
85
+ Reconcile an explicit `scratchPatterns` array when enabling a new profile.
86
+ Derive its glob values from the consumer's ignored planning artefacts; an empty
87
+ array is valid. Existing values are consumer-owned and remain byte-identical on
88
+ adoption or rerun. Core never supplies filename defaults.
89
+
90
+ The shipped read-only inventory is
91
+ `python3 scripts/worktree-lifecycle/cleanup.py sweep`. The same profile powers
92
+ 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,7 +101,7 @@ 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,5 +119,5 @@ STOP → diagnose in the main conversation, fix, re-run `land` (an already-merge
108
119
  <!-- readiness:end -->
109
120
 
110
121
  ## Out of scope
111
- - Live-verify / DoD: must happen **before** `/wrapup` — this skill lands, it does not verify.
122
+ - Live-verify / DoD: must happen **before** `$wrapup` or `/wrapup` — this skill lands, it does not verify.
112
123
  - 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.`
@@ -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
 
@@ -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
@@ -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,8 +203,8 @@ 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
+ and reconcile only the exact kit-owned hook commands listed in the seed.
200
208
  - **Later / No** — record the choice in the tracked profile without installing
201
209
  hook wiring. Ordinary reruns do not ask again.
202
210
  - **Existing** — adopt the current section and wiring without normalizing
@@ -422,6 +430,12 @@ These are **structured-but-empty** crusts that `/retro` grows; do not ask the us
422
430
 
423
431
  - `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
432
  - `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.
433
+ - The `orchestrateWaveRecipe` readiness capability declares
434
+ `all-sections-filled` plus the seven named `§` sections. Every one must
435
+ contain real project instructions before either the runtime inspector or
436
+ readiness may activate `projectRecipe`. A comment-only or legacy seed remains
437
+ an intentional generic fallback even when its setup sentinel is
438
+ `state=filled`.
425
439
  - `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
440
 
427
441
  > **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.
@@ -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
@@ -79,3 +79,14 @@ The exact kit-owned commands are:
79
79
 
80
80
  Preserve unrelated settings, hook groups, profile sections, and unknown keys.
81
81
  Repeated reconciliation with the same choice is byte-identical.
82
+
83
+ ## Scratch classification and sweep
84
+
85
+ Reconcile an explicit `scratchPatterns` array when enabling a new profile.
86
+ Derive its glob values from the consumer's ignored planning artefacts; an empty
87
+ array is valid. Existing values are consumer-owned and remain byte-identical on
88
+ adoption or rerun. Core never supplies filename defaults.
89
+
90
+ The shipped read-only inventory is
91
+ `python3 scripts/worktree-lifecycle/cleanup.py sweep`. The same profile powers
92
+ 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 } },
@@ -2,7 +2,7 @@
2
2
  name: wrapup
3
3
  disable-model-invocation: true
4
4
  description: >-
5
- Use ONLY when the user types /wrapup. Session-end "land & clean" for a
5
+ Use ONLY when the user directly types $wrapup or /wrapup. Session-end "land & clean" for a
6
6
  finished feature/fix worktree — merges the open PR,
7
7
  kills the worktree dev server, removes the worktree + local branch, and
8
8
  fast-forwards the main checkout so main is current again, then sweeps
@@ -11,7 +11,8 @@ description: >-
11
11
  tree (after an .env/secret check), pushes, and opens the PR — reusing one if
12
12
  it already exists. User-triggered only (never auto-invoke, never hook). Aborts
13
13
  hard only on: not in a feature worktree, a detected .env/secret, a rejected
14
- push, a conflicting PR, or red (FAILURE) checks.
14
+ push, a conflicting PR, terminal red checks, or checks still pending after
15
+ the bounded wait budget.
15
16
  ---
16
17
 
17
18
  <!-- project-extension:protocol-v1:start -->
@@ -24,15 +25,15 @@ Project extensions may specialize Project details, but cannot weaken Core user g
24
25
 
25
26
  # wrapup — land PR & tear down worktree
26
27
 
27
- 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.
28
29
 
29
30
  ## ⚠ Spec context
30
31
 
31
- 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.
32
33
  It authorizes the normal merge flow whether Prod readiness is ready or degraded;
33
34
  it never authorizes the agent to invent or configure a deploy target. Never call
34
- this skill from a hook, another skill, or autonomously. There is no second merge
35
- 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.
36
37
 
37
38
  ## Execution model — script does mechanics, the agent does judgment
38
39
 
@@ -62,12 +63,12 @@ conflicting instruction surfaces; never choose a target on the user's behalf.
62
63
 
63
64
  ### 2 · Retro gate (blocking, optional retro-exit — before anything is committed)
64
65
  One reminder, not a merge confirmation:
65
- > "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."
66
67
 
67
68
  (b) → **invoke the `retro` skill immediately in this run.** Retro is
68
69
  model-invocable and non-deploying, and every mutation still has its own approval
69
70
  gate. After retro finishes, **land nothing in this run**. Require a **fresh
70
- 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
71
72
  that the next merge authorization covers.
72
73
 
73
74
  General chaining rule: automatically chain only into a **model-invocable**,
@@ -100,7 +101,7 @@ Run **from the main tree** (the script refuses inside the worktree — an in-wor
100
101
  ```bash
101
102
  python3 scripts/wrapup-land.py land --branch "<branch>" --title "<title>" --body-file /tmp/wrapup-pr-body.md
102
103
  ```
103
- 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).
104
105
 
105
106
  STOP → diagnose in the main conversation, fix, re-run `land` (an already-merged PR resumes at teardown).
106
107
 
@@ -118,5 +119,5 @@ STOP → diagnose in the main conversation, fix, re-run `land` (an already-merge
118
119
  <!-- readiness:end -->
119
120
 
120
121
  ## Out of scope
121
- - Live-verify / DoD: must happen **before** `/wrapup` — this skill lands, it does not verify.
122
+ - Live-verify / DoD: must happen **before** `$wrapup` or `/wrapup` — this skill lands, it does not verify.
122
123
  - Other worktrees / their servers stay untouched.
package/README.md CHANGED
@@ -322,6 +322,7 @@ rolls that migration back with the rest of the candidate.
322
322
  ```sh
323
323
  npx github:iKon85/agent-workflow-kit diff # preview an update (dry run, writes nothing)
324
324
  npx github:iKon85/agent-workflow-kit update # apply it
325
+ npx github:iKon85/agent-workflow-kit update --yes --keep-deleted # headless/CI
325
326
  npx github:iKon85/agent-workflow-kit uninstall # remove kit-installed files
326
327
  ```
327
328
 
@@ -369,9 +370,17 @@ Containment and file type are revalidated when read.
369
370
  Ownership commands are designed for a single-user CLI workflow and are not
370
371
  concurrency-safe. Do not run manifest-mutating commands concurrently. Flags:
371
372
  `--force` (overwrite pre-existing untracked files on `init`), `--yes` / `-y`
372
- (confirm only already-classified safe update actions), and
373
+ (run `update` non-interactively and confirm only already-classified safe
374
+ actions), `--keep-deleted` (follow upstream deletions and remove those files
375
+ locally), `--restore-deleted` (retain files that were deleted upstream), and
373
376
  `--as=explicit-fork` for `own`.
374
377
 
378
+ A headless `update` requires `--yes`; otherwise it exits before reading release
379
+ state or touching consumer files. The mutually exclusive deletion flags only
380
+ override the blanket answer for files removed upstream. They never resolve an
381
+ ownership collision or content conflict, so a conflicted headless update still
382
+ prints its report, exits non-zero, and leaves the consumer byte-identical.
383
+
375
384
  The optional Contribution Routing capability is consumer-owned:
376
385
 
377
386
  ```json
@@ -445,6 +454,55 @@ the old way. Decision record:
445
454
 
446
455
  ## Release notes
447
456
 
457
+ ### 0.37.0
458
+
459
+ - added: `scripts/test_anchor_table.py`
460
+ - added: `scripts/test_wrapup_land.py`
461
+ - changed: `.agents/skills/orchestrate-wave/SKILL.md`
462
+ - changed: `.agents/skills/setup-workflow/SKILL.md`
463
+ - changed: `.agents/skills/setup-workflow/orchestrate-wave-seed.md`
464
+ - changed: `.agents/skills/setup-workflow/worktree-lifecycle.md`
465
+ - changed: `.agents/skills/wrapup/SKILL.md`
466
+ - changed: `.claude/hooks/migration-snapshot-reminder.py`
467
+ - changed: `.claude/skills/orchestrate-wave/SKILL.md`
468
+ - changed: `.claude/skills/setup-workflow/SKILL.md`
469
+ - changed: `.claude/skills/setup-workflow/orchestrate-wave-seed.md`
470
+ - changed: `.claude/skills/setup-workflow/worktree-lifecycle.md`
471
+ - changed: `.claude/skills/skill-manifest.json`
472
+ - changed: `.claude/skills/wrapup/SKILL.md`
473
+ - changed: `README.md`
474
+ - changed: `agent-workflow-kit.package.json`
475
+ - changed: `docs/agents/workflow-capabilities.json`
476
+ - changed: `scripts/anchor_table.py`
477
+ - changed: `scripts/project-skill-extension.mjs`
478
+ - changed: `scripts/readiness.mjs`
479
+ - changed: `scripts/release-state.mjs`
480
+ - changed: `scripts/release-state.test.mjs`
481
+ - changed: `scripts/test_board_sync_create_idempotency.py`
482
+ - changed: `scripts/test_board_sync_wave_title.py`
483
+ - changed: `scripts/test_census_backstop.py`
484
+ - changed: `scripts/test_orchestrate_wave_contract.py`
485
+ - changed: `scripts/test_retro_wrapup_contract.py`
486
+ - changed: `scripts/workflow-advisories/core.py`
487
+ - changed: `scripts/worktree-lifecycle/README.md`
488
+ - changed: `scripts/worktree-lifecycle/cleanup.py`
489
+ - changed: `scripts/worktree-lifecycle/core.py`
490
+ - changed: `scripts/worktree-lifecycle/profile.py`
491
+ - changed: `scripts/wrapup-land.py`
492
+ - changed: `src/cli.mjs`
493
+ - changed: `src/lib/manifest.mjs`
494
+ - changed: `src/lib/projectSkillExtension.mjs`
495
+ - changed: `src/lib/updateCandidate.mjs`
496
+ - changed: `src/lib/updateDecisions.mjs`
497
+ - changed: `src/lib/verifyUpdateCandidateProtocol.mjs`
498
+
499
+ ### 0.36.5
500
+
501
+ - changed: `src/lib/updateCandidate.mjs`
502
+ - changed: `src/lib/updateReconcile.mjs`
503
+ - changed: `src/lib/verifyUpdateCandidate.mjs`
504
+ - changed: `src/lib/verifyUpdateCandidateTransaction.mjs`
505
+
448
506
  ### 0.36.4
449
507
 
450
508
  - changed: `scripts/release-delta-guard.mjs`