@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.
- package/.agents/skills/orchestrate-wave/SKILL.md +20 -12
- package/.agents/skills/setup-workflow/SKILL.md +24 -3
- package/.agents/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
- package/.agents/skills/setup-workflow/worktree-lifecycle.md +29 -1
- package/.agents/skills/wrapup/SKILL.md +42 -9
- package/.claude/hooks/migration-snapshot-reminder.py +1 -1
- package/.claude/skills/orchestrate-wave/SKILL.md +11 -11
- package/.claude/skills/setup-workflow/SKILL.md +24 -3
- package/.claude/skills/setup-workflow/orchestrate-wave-seed.md +3 -2
- package/.claude/skills/setup-workflow/worktree-lifecycle.md +29 -1
- package/.claude/skills/skill-manifest.json +1 -1
- package/.claude/skills/wrapup/SKILL.md +33 -10
- package/README.md +88 -1
- package/agent-workflow-kit.package.json +36 -28
- package/docs/adr/0007-session-teardown-requires-provenance-bound-ownership.md +88 -0
- package/docs/agents/workflow-capabilities.json +11 -0
- package/package.json +1 -1
- package/scripts/anchor_table.py +14 -8
- package/scripts/project-skill-extension.mjs +21 -2
- package/scripts/readiness.mjs +32 -4
- package/scripts/release-state.mjs +19 -9
- package/scripts/release-state.test.mjs +71 -8
- package/scripts/test_anchor_table.py +69 -0
- package/scripts/test_board_sync_create_idempotency.py +15 -2
- package/scripts/test_board_sync_wave_title.py +14 -2
- package/scripts/test_census_backstop.py +33 -0
- package/scripts/test_orchestrate_wave_contract.py +44 -0
- package/scripts/test_retro_wrapup_contract.py +19 -2
- package/scripts/test_worktree_wrapup_contract.py +1004 -3
- package/scripts/test_wrapup_land.py +428 -0
- package/scripts/workflow-advisories/core.py +44 -2
- package/scripts/worktree-lifecycle/README.md +126 -4
- package/scripts/worktree-lifecycle/capabilities.json +9 -1
- package/scripts/worktree-lifecycle/cleanup.py +143 -5
- package/scripts/worktree-lifecycle/core.py +1383 -20
- package/scripts/worktree-lifecycle/profile.py +40 -3
- package/scripts/worktree-lifecycle/session.py +1857 -0
- package/scripts/worktree-lifecycle/setup.py +15 -0
- package/scripts/wrapup-land.py +650 -27
- package/src/cli.mjs +60 -27
- package/src/lib/bundle.mjs +1 -0
- package/src/lib/manifest.mjs +173 -3
- package/src/lib/projectSkillExtension.mjs +78 -1
- package/src/lib/updateCandidate.mjs +3 -1
- package/src/lib/updateDecisions.mjs +2 -2
- package/src/lib/verifyUpdateCandidateProtocol.mjs +15 -0
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orchestrate-wave
|
|
3
|
-
|
|
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`:
|
|
29
|
-
|
|
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.
|
|
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
|
|
192
|
-
`git worktree add
|
|
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
|
-
-
|
|
354
|
-
|
|
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,
|
|
199
|
-
the
|
|
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
|
|
14
|
-
> falls back to generic instructions — so fill them before
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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`:
|
|
37
|
-
|
|
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.
|
|
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
|
|
200
|
-
`git worktree add
|
|
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
|
-
-
|
|
362
|
-
|
|
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,
|
|
199
|
-
the
|
|
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
|
|
14
|
-
> falls back to generic instructions — so fill them before
|
|
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": "
|
|
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 } },
|