@ikon85/agent-workflow-kit 0.31.0 → 0.32.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.
@@ -23,6 +23,35 @@ skills the other steps rely on drift, and nothing fixes them unless a recipe doe
23
23
  Not for: rewriting a domain skill's content on demand (that is the skill itself),
24
24
  or auditing application code (a code review or a diagnosis does that).
25
25
 
26
+ ## Readiness preflight — first
27
+
28
+ <!-- readiness:optional-preflight:start -->
29
+ Before enumerating skills, launching research subagents, or editing any skill,
30
+ run this once from the project root:
31
+
32
+ ```bash
33
+ node scripts/readiness.mjs check --skill audit-skills --json
34
+ ```
35
+
36
+ - `ready`: continue silently with the generic audit and the active
37
+ `projectChecks` block.
38
+ - `degraded`: keep the generic audit active, omit only `projectChecks`, and emit
39
+ exactly one concise summary: `Readiness degraded — inactive block
40
+ projectChecks (auditSkillsLayer: <state>). Run /setup-workflow, configure
41
+ docs/agents/skills/audit-skills.md, then rerun this skill.`
42
+ - `blocked`: stop before continuing and report the non-ready required capability
43
+ plus the exact `/setup-workflow` recovery path.
44
+ - Invalid evidence is always visible in that one summary; never interpret it as
45
+ an opt-out or invent project checks.
46
+ <!-- readiness:optional-preflight:end -->
47
+
48
+ <!-- readiness:block projectChecks -->
49
+ When `projectChecks` is active, read
50
+ `docs/agents/skills/audit-skills.md` and apply its concrete class assignments,
51
+ project-specific guard commands, and drift checks in addition to the generic
52
+ recipe below.
53
+ <!-- readiness:end -->
54
+
26
55
  ## Standing guards (run without this audit)
27
56
 
28
57
  Two automatic nets catch the most common drift classes before an audit — this
@@ -31,7 +60,7 @@ recipe complements them, it does not replace them:
31
60
  1. **A skill-sync test** — for any un-guessable enumeration a skill documents (a
32
61
  status→bucket map, a design-token list), a test parses the value out of the
33
62
  SKILL.md and asserts equality with the code constant. Drift breaks the build.
34
- Your project layer names the concrete tests.
63
+ Run the concrete tests available in the repository.
35
64
  2. **The drift-hint hook** (`.claude/hooks/skill-drift-hint.py`) + a per-skill
36
65
  `SOURCES.txt`: at SessionStart it flags any skill whose declared source file
37
66
  is newer in git than its SKILL.md.
@@ -79,8 +108,9 @@ plus the `SOURCES.txt` files. Sort every skill into one of three classes:
79
108
  scripts or hooks with no `SOURCES.txt` and no hook net. No hook warns, so
80
109
  re-check them manually each audit.
81
110
 
82
- Your project layer assigns each concrete skill to a class a completeness gate
83
- catches the next new skill that would otherwise stay invisible.
111
+ Derive each concrete skill's class from the manifest, its `SOURCES.txt`, and the
112
+ repository surfaces — a completeness gate catches the next new skill that would
113
+ otherwise stay invisible.
84
114
 
85
115
  ### 2. Audit in parallel — one subagent per skill
86
116
 
@@ -129,8 +159,7 @@ alongside the Claude source), sync the mirror in the **same** change — otherwi
129
159
  the second surface rots silently. Mirror the body, but preserve each surface's
130
160
  own frontmatter: a mirror's `description` may be deliberately condensed, so never
131
161
  blind-copy the whole file over it. A `SOURCES.txt` is a plain anchor list and can
132
- be mirrored verbatim. Your project layer names the surfaces and the exact
133
- transform.
162
+ be mirrored verbatim. Use the repository's declared surfaces and exact transform.
134
163
 
135
164
  ## Done
136
165
 
@@ -20,11 +20,36 @@ discipline and its guards) didn't stop it.
20
20
 
21
21
  ## Precondition
22
22
 
23
- If your project has a prevention layer a SessionStart warning on active
24
- worktrees, a pre-edit guard that blocks edits on the wrong branch — this skill
25
- handles the case where that layer did NOT prevent a misplaced commit. Your project
26
- layer names those guards (`docs/agents/skills/git-worktree-recover.md`, seeded as
27
- an empty stub by `/setup-workflow`).
23
+ This generic recovery remains usable whether or not the project has prevention
24
+ guards or a custom worktree setup command.
25
+
26
+ ## Readiness preflight first
27
+
28
+ <!-- readiness:optional-preflight:start -->
29
+ Before assessing refs or moving a branch, run this once from the project root:
30
+
31
+ ```bash
32
+ node scripts/readiness.mjs check --skill git-worktree-recover --json
33
+ ```
34
+
35
+ - `ready`: continue silently with generic recovery and the active
36
+ `projectRecovery` block.
37
+ - `degraded`: keep generic reflog recovery active, omit only
38
+ `projectRecovery`, and emit exactly one concise summary: `Readiness degraded
39
+ — inactive block projectRecovery (worktreeRecoveryLayer: <state>). Run
40
+ /setup-workflow, configure docs/agents/skills/git-worktree-recover.md, then
41
+ rerun this skill.`
42
+ - `blocked`: stop before continuing and report the non-ready required capability
43
+ plus the exact `/setup-workflow` recovery path.
44
+ - Invalid evidence is always visible in that one summary; never interpret it as
45
+ an opt-out or invent a project command.
46
+ <!-- readiness:optional-preflight:end -->
47
+
48
+ <!-- readiness:block projectRecovery -->
49
+ When `projectRecovery` is active, read
50
+ `docs/agents/skills/git-worktree-recover.md` and apply its named prevention
51
+ guards and exact worktree setup command around the generic recovery below.
52
+ <!-- readiness:end -->
28
53
 
29
54
  ---
30
55
 
@@ -124,16 +149,12 @@ it.
124
149
 
125
150
  ## Phase 5 — Set up a worktree
126
151
 
127
- Set the recovered branch up cleanly in its own worktree. If your project has a
128
- worktree-setup command, use it (it typically runs `git worktree add`, installs
129
- deps and copies env files); otherwise:
152
+ Set the recovered branch up cleanly in its own worktree. The generic fallback is:
130
153
 
131
154
  ```bash
132
155
  git worktree add <path> <recovered-branch>
133
156
  ```
134
157
 
135
- Your project layer names the exact command and what it copies.
136
-
137
158
  **Verify after setup:**
138
159
 
139
160
  ```bash
@@ -13,13 +13,46 @@ correctly, AFK. Subagents BUILD; **you** integrate + verify + land.
13
13
  The anchor, its sub-issues and the locked plan doc contain the verbatim contracts
14
14
  you must NOT paraphrase.
15
15
 
16
- > **Phase 0 probes a project layer.** Concrete tooling exact test/verify
16
+ ## Readiness preflightfirst
17
+
18
+ <!-- readiness:optional-preflight:start -->
19
+ Before reading from the issue tracker, claiming a wave, creating worktrees, or
20
+ making any local or remote mutation, run this once from the project root:
21
+
22
+ ```bash
23
+ node scripts/readiness.mjs check --skill orchestrate-wave --json
24
+ ```
25
+
26
+ - `ready`: continue silently with the required tracker/board context and the
27
+ 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
31
+ projectRecipe (orchestrateWaveRecipe: <state>); using the generic
32
+ orchestration fallback. Run /setup-workflow, configure
33
+ docs/agents/skills/orchestrate-wave.md, then rerun this skill.`
34
+ - `blocked`: `STOP` before tracker access, dispatch, claims, worktrees, or other
35
+ mutation. Report `issueTracker=<state>` and `managedBoard=<state>`, then give
36
+ exactly one recovery path: **Run `/setup-workflow`, then rerun
37
+ `/orchestrate-wave`.** Never fall back to bare tracker or board commands.
38
+ - `managedBoard=not-applicable`: `STOP` and report that `/orchestrate-wave` is
39
+ inapplicable without a managed board. This is a terminal project decision,
40
+ not invalid evidence and not a partially active mode.
41
+ - Invalid evidence is always visible and never treated as an opt-out.
42
+ <!-- readiness:optional-preflight:end -->
43
+
44
+ <!-- readiness:block projectRecipe -->
45
+ > **Phase 0 consumes the active project recipe.** Concrete tooling — exact test/verify
17
46
  > commands, a DB/tunnel setup, a headless login recipe, brand checks, deploy
18
47
  > lockstep — is project-specific and lives in a **project layer** this skill reads
19
48
  > at runtime, not in this skeleton. The skeleton names the layer's sections
20
49
  > (`§Setup`, `§Builder Commands`, `§Builder Hard Rules`, `§Integration Suites`,
21
50
  > `§Verify Recipe`, `§Headless Login`, `§Landing`) and falls back to generic
22
51
  > instructions when the layer is absent. See **Phase 0**.
52
+ >
53
+ > When `projectRecipe` is active, read the filled project layer before applying
54
+ > any phase-specific command below.
55
+ <!-- readiness:end -->
23
56
 
24
57
  ## Standing rules (all phases)
25
58
 
@@ -59,15 +92,11 @@ you must NOT paraphrase.
59
92
  1. **Read everything**: the anchor body, every sub-issue body (each has a Handoff
60
93
  block: scope, blast-radius, live-verify, PR line), and the locked plan /
61
94
  plan-review doc in the planning worktree (file-exact).
62
- 2. **Probe the project layer.** Read the project layer doc for this skill (the
63
- consumer's `docs/agents/skills/orchestrate-wave.md` or the path your project
64
- uses). If its `§`-sections carry **filled** content, follow the project recipe
65
- wherever a phase below points at a `§`-section. If the file is only a
66
- `setup-workflow` sentinel stub (empty headings, no real content) or absent,
67
- treat the layer as **ABSENT** → use the generic fallback in each phase and warn
68
- **once** that `/setup-workflow` plus project maintenance fill the layer (the
69
- commands/tunnel/login can't be guessed). Never treat an empty heading as a
70
- verify recipe.
95
+ 2. **Select exact commands or the generic fallback.** If the readiness result
96
+ activated `projectRecipe`, use the loaded filled recipe wherever a phase below
97
+ points at a `§`-section. Otherwise use each phase's generic fallback; the
98
+ preflight's single degraded summary is the only warning. Never guess a project
99
+ command, tunnel, login, or verify recipe.
71
100
  3. **Preflight — refuse a wave already in flight, otherwise claim it.** Before
72
101
  dispatch, inspect all three same-machine collision signals: **(a)** an existing
73
102
  `wave-active/<anchor>` tag; **(b)** any slice branch ahead of the wave's current
@@ -88,10 +117,10 @@ you must NOT paraphrase.
88
117
  tunnel or service the live-verify depends on. Absent layer → start whatever your
89
118
  live-verify environment requires before Phase 4.
90
119
 
91
- **Done when:** anchor + every sub-issue + plan read · project layer probed
92
- (filledproject recipe; stub/absent → generic + one-time warning) · preflight
93
- clean + this run's local claim planted · wave branch ff'd to `origin/main` + deps
94
- installed · project setup steps running.
120
+ **Done when:** anchor + every sub-issue + plan read · readiness result consumed
121
+ (active `projectRecipe` exact recipe; inactive → generic fallback) · collision
122
+ preflight clean + this run's local claim planted · wave branch ff'd to
123
+ `origin/main` + deps installed · project setup steps running.
95
124
 
96
125
  ## Phase 1 — Disjointness recon (the load-bearing step)
97
126
 
@@ -23,6 +23,35 @@ skills the other steps rely on drift, and nothing fixes them unless a recipe doe
23
23
  Not for: rewriting a domain skill's content on demand (that is the skill itself),
24
24
  or auditing application code (a code review or a diagnosis does that).
25
25
 
26
+ ## Readiness preflight — first
27
+
28
+ <!-- readiness:optional-preflight:start -->
29
+ Before enumerating skills, launching research subagents, or editing any skill,
30
+ run this once from the project root:
31
+
32
+ ```bash
33
+ node scripts/readiness.mjs check --skill audit-skills --json
34
+ ```
35
+
36
+ - `ready`: continue silently with the generic audit and the active
37
+ `projectChecks` block.
38
+ - `degraded`: keep the generic audit active, omit only `projectChecks`, and emit
39
+ exactly one concise summary: `Readiness degraded — inactive block
40
+ projectChecks (auditSkillsLayer: <state>). Run /setup-workflow, configure
41
+ docs/agents/skills/audit-skills.md, then rerun this skill.`
42
+ - `blocked`: stop before continuing and report the non-ready required capability
43
+ plus the exact `/setup-workflow` recovery path.
44
+ - Invalid evidence is always visible in that one summary; never interpret it as
45
+ an opt-out or invent project checks.
46
+ <!-- readiness:optional-preflight:end -->
47
+
48
+ <!-- readiness:block projectChecks -->
49
+ When `projectChecks` is active, read
50
+ `docs/agents/skills/audit-skills.md` and apply its concrete class assignments,
51
+ project-specific guard commands, and drift checks in addition to the generic
52
+ recipe below.
53
+ <!-- readiness:end -->
54
+
26
55
  ## Standing guards (run without this audit)
27
56
 
28
57
  Two automatic nets catch the most common drift classes before an audit — this
@@ -31,7 +60,7 @@ recipe complements them, it does not replace them:
31
60
  1. **A skill-sync test** — for any un-guessable enumeration a skill documents (a
32
61
  status→bucket map, a design-token list), a test parses the value out of the
33
62
  SKILL.md and asserts equality with the code constant. Drift breaks the build.
34
- Your project layer names the concrete tests.
63
+ Run the concrete tests available in the repository.
35
64
  2. **The drift-hint hook** (`.claude/hooks/skill-drift-hint.py`) + a per-skill
36
65
  `SOURCES.txt`: at SessionStart it flags any skill whose declared source file
37
66
  is newer in git than its SKILL.md.
@@ -79,8 +108,9 @@ plus the `SOURCES.txt` files. Sort every skill into one of three classes:
79
108
  scripts or hooks with no `SOURCES.txt` and no hook net. No hook warns, so
80
109
  re-check them manually each audit.
81
110
 
82
- Your project layer assigns each concrete skill to a class a completeness gate
83
- catches the next new skill that would otherwise stay invisible.
111
+ Derive each concrete skill's class from the manifest, its `SOURCES.txt`, and the
112
+ repository surfaces — a completeness gate catches the next new skill that would
113
+ otherwise stay invisible.
84
114
 
85
115
  ### 2. Audit in parallel — one subagent per skill
86
116
 
@@ -129,8 +159,7 @@ alongside the Claude source), sync the mirror in the **same** change — otherwi
129
159
  the second surface rots silently. Mirror the body, but preserve each surface's
130
160
  own frontmatter: a mirror's `description` may be deliberately condensed, so never
131
161
  blind-copy the whole file over it. A `SOURCES.txt` is a plain anchor list and can
132
- be mirrored verbatim. Your project layer names the surfaces and the exact
133
- transform.
162
+ be mirrored verbatim. Use the repository's declared surfaces and exact transform.
134
163
 
135
164
  ## Done
136
165
 
@@ -26,11 +26,36 @@ discipline and its guards) didn't stop it.
26
26
 
27
27
  ## Precondition
28
28
 
29
- If your project has a prevention layer a SessionStart warning on active
30
- worktrees, a pre-edit guard that blocks edits on the wrong branch — this skill
31
- handles the case where that layer did NOT prevent a misplaced commit. Your project
32
- layer names those guards (`docs/agents/skills/git-worktree-recover.md`, seeded as
33
- an empty stub by `/setup-workflow`).
29
+ This generic recovery remains usable whether or not the project has prevention
30
+ guards or a custom worktree setup command.
31
+
32
+ ## Readiness preflight first
33
+
34
+ <!-- readiness:optional-preflight:start -->
35
+ Before assessing refs or moving a branch, run this once from the project root:
36
+
37
+ ```bash
38
+ node scripts/readiness.mjs check --skill git-worktree-recover --json
39
+ ```
40
+
41
+ - `ready`: continue silently with generic recovery and the active
42
+ `projectRecovery` block.
43
+ - `degraded`: keep generic reflog recovery active, omit only
44
+ `projectRecovery`, and emit exactly one concise summary: `Readiness degraded
45
+ — inactive block projectRecovery (worktreeRecoveryLayer: <state>). Run
46
+ /setup-workflow, configure docs/agents/skills/git-worktree-recover.md, then
47
+ rerun this skill.`
48
+ - `blocked`: stop before continuing and report the non-ready required capability
49
+ plus the exact `/setup-workflow` recovery path.
50
+ - Invalid evidence is always visible in that one summary; never interpret it as
51
+ an opt-out or invent a project command.
52
+ <!-- readiness:optional-preflight:end -->
53
+
54
+ <!-- readiness:block projectRecovery -->
55
+ When `projectRecovery` is active, read
56
+ `docs/agents/skills/git-worktree-recover.md` and apply its named prevention
57
+ guards and exact worktree setup command around the generic recovery below.
58
+ <!-- readiness:end -->
34
59
 
35
60
  ---
36
61
 
@@ -130,16 +155,12 @@ it.
130
155
 
131
156
  ## Phase 5 — Set up a worktree
132
157
 
133
- Set the recovered branch up cleanly in its own worktree. If your project has a
134
- worktree-setup command, use it (it typically runs `git worktree add`, installs
135
- deps and copies env files); otherwise:
158
+ Set the recovered branch up cleanly in its own worktree. The generic fallback is:
136
159
 
137
160
  ```bash
138
161
  git worktree add <path> <recovered-branch>
139
162
  ```
140
163
 
141
- Your project layer names the exact command and what it copies.
142
-
143
164
  **Verify after setup:**
144
165
 
145
166
  ```bash
@@ -21,13 +21,46 @@ correctly, AFK. Subagents BUILD; **you** integrate + verify + land.
21
21
  The anchor, its sub-issues and the locked plan doc contain the verbatim contracts
22
22
  you must NOT paraphrase.
23
23
 
24
- > **Phase 0 probes a project layer.** Concrete tooling exact test/verify
24
+ ## Readiness preflightfirst
25
+
26
+ <!-- readiness:optional-preflight:start -->
27
+ Before reading from the issue tracker, claiming a wave, creating worktrees, or
28
+ making any local or remote mutation, run this once from the project root:
29
+
30
+ ```bash
31
+ node scripts/readiness.mjs check --skill orchestrate-wave --json
32
+ ```
33
+
34
+ - `ready`: continue silently with the required tracker/board context and the
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
39
+ projectRecipe (orchestrateWaveRecipe: <state>); using the generic
40
+ orchestration fallback. Run /setup-workflow, configure
41
+ docs/agents/skills/orchestrate-wave.md, then rerun this skill.`
42
+ - `blocked`: `STOP` before tracker access, dispatch, claims, worktrees, or other
43
+ mutation. Report `issueTracker=<state>` and `managedBoard=<state>`, then give
44
+ exactly one recovery path: **Run `/setup-workflow`, then rerun
45
+ `/orchestrate-wave`.** Never fall back to bare tracker or board commands.
46
+ - `managedBoard=not-applicable`: `STOP` and report that `/orchestrate-wave` is
47
+ inapplicable without a managed board. This is a terminal project decision,
48
+ not invalid evidence and not a partially active mode.
49
+ - Invalid evidence is always visible and never treated as an opt-out.
50
+ <!-- readiness:optional-preflight:end -->
51
+
52
+ <!-- readiness:block projectRecipe -->
53
+ > **Phase 0 consumes the active project recipe.** Concrete tooling — exact test/verify
25
54
  > commands, a DB/tunnel setup, a headless login recipe, brand checks, deploy
26
55
  > lockstep — is project-specific and lives in a **project layer** this skill reads
27
56
  > at runtime, not in this skeleton. The skeleton names the layer's sections
28
57
  > (`§Setup`, `§Builder Commands`, `§Builder Hard Rules`, `§Integration Suites`,
29
58
  > `§Verify Recipe`, `§Headless Login`, `§Landing`) and falls back to generic
30
59
  > instructions when the layer is absent. See **Phase 0**.
60
+ >
61
+ > When `projectRecipe` is active, read the filled project layer before applying
62
+ > any phase-specific command below.
63
+ <!-- readiness:end -->
31
64
 
32
65
  ## Standing rules (all phases)
33
66
 
@@ -67,15 +100,11 @@ you must NOT paraphrase.
67
100
  1. **Read everything**: the anchor body, every sub-issue body (each has a Handoff
68
101
  block: scope, blast-radius, live-verify, PR line), and the locked plan /
69
102
  plan-review doc in the planning worktree (file-exact).
70
- 2. **Probe the project layer.** Read the project layer doc for this skill (the
71
- consumer's `docs/agents/skills/orchestrate-wave.md` or the path your project
72
- uses). If its `§`-sections carry **filled** content, follow the project recipe
73
- wherever a phase below points at a `§`-section. If the file is only a
74
- `setup-workflow` sentinel stub (empty headings, no real content) or absent,
75
- treat the layer as **ABSENT** → use the generic fallback in each phase and warn
76
- **once** that `/setup-workflow` plus project maintenance fill the layer (the
77
- commands/tunnel/login can't be guessed). Never treat an empty heading as a
78
- verify recipe.
103
+ 2. **Select exact commands or the generic fallback.** If the readiness result
104
+ activated `projectRecipe`, use the loaded filled recipe wherever a phase below
105
+ points at a `§`-section. Otherwise use each phase's generic fallback; the
106
+ preflight's single degraded summary is the only warning. Never guess a project
107
+ command, tunnel, login, or verify recipe.
79
108
  3. **Preflight — refuse a wave already in flight, otherwise claim it.** Before
80
109
  dispatch, inspect all three same-machine collision signals: **(a)** an existing
81
110
  `wave-active/<anchor>` tag; **(b)** any slice branch ahead of the wave's current
@@ -96,10 +125,10 @@ you must NOT paraphrase.
96
125
  tunnel or service the live-verify depends on. Absent layer → start whatever your
97
126
  live-verify environment requires before Phase 4.
98
127
 
99
- **Done when:** anchor + every sub-issue + plan read · project layer probed
100
- (filledproject recipe; stub/absent → generic + one-time warning) · preflight
101
- clean + this run's local claim planted · wave branch ff'd to `origin/main` + deps
102
- installed · project setup steps running.
128
+ **Done when:** anchor + every sub-issue + plan read · readiness result consumed
129
+ (active `projectRecipe` exact recipe; inactive → generic fallback) · collision
130
+ preflight clean + this run's local claim planted · wave branch ff'd to
131
+ `origin/main` + deps installed · project setup steps running.
103
132
 
104
133
  ## Phase 1 — Disjointness recon (the load-bearing step)
105
134
 
package/README.md CHANGED
@@ -348,6 +348,15 @@ concurrency-safe. Do not run manifest-mutating commands concurrently. Flags:
348
348
 
349
349
  ## Release notes
350
350
 
351
+ ### 0.32.0
352
+
353
+ - changed: `.agents/skills/audit-skills/SKILL.md`
354
+ - changed: `.agents/skills/git-worktree-recover/SKILL.md`
355
+ - changed: `.agents/skills/orchestrate-wave/SKILL.md`
356
+ - changed: `.claude/skills/audit-skills/SKILL.md`
357
+ - changed: `.claude/skills/git-worktree-recover/SKILL.md`
358
+ - changed: `.claude/skills/orchestrate-wave/SKILL.md`
359
+
351
360
  ### 0.31.0
352
361
 
353
362
  - changed: `.agents/skills/board-to-waves/SKILL.md`
@@ -1,5 +1,5 @@
1
1
  {
2
- "kitVersion": "0.31.0",
2
+ "kitVersion": "0.32.0",
3
3
  "files": [
4
4
  {
5
5
  "path": ".agents/skills/ask-matt/SKILL.md",
@@ -27,7 +27,7 @@
27
27
  "ownerSkill": "audit-skills",
28
28
  "surface": "codex",
29
29
  "installRole": "consumer",
30
- "sha256": "f99bfc88bf23ad8279583653bdd7b63dcdcff010227258e4adf9e8df69384f7f",
30
+ "sha256": "662c4dec0c03716c468f202f73f52140ceba84e092873e6619692dde6d7ed0f2",
31
31
  "mode": 420,
32
32
  "origin": "kit"
33
33
  },
@@ -197,7 +197,7 @@
197
197
  "ownerSkill": "git-worktree-recover",
198
198
  "surface": "codex",
199
199
  "installRole": "consumer",
200
- "sha256": "71e043456586a59ddb83fb3fb1f98c8c269cd7575ade8616238bdb7e07fba4ba",
200
+ "sha256": "1628f47a5b5f71b7596ec070c8f038a3ce98abe007fce1b7f5c21ea40858124d",
201
201
  "mode": 420,
202
202
  "origin": "kit"
203
203
  },
@@ -417,7 +417,7 @@
417
417
  "ownerSkill": "orchestrate-wave",
418
418
  "surface": "codex",
419
419
  "installRole": "consumer",
420
- "sha256": "39c0dd4d6f7663ab9a3602aab2869a881497604ca12f53f6ba0ca7debb0a4157",
420
+ "sha256": "7a94293b7db49f42497d34e6ae0fe9992ab1c770ae0766557618818d6d671c50",
421
421
  "mode": 420,
422
422
  "origin": "kit"
423
423
  },
@@ -1189,7 +1189,7 @@
1189
1189
  "ownerSkill": "audit-skills",
1190
1190
  "surface": "claude",
1191
1191
  "installRole": "consumer",
1192
- "sha256": "80ab0f1910914f4bcb375bf63aa66a1297a0b873082d7cc4f386d0d931e6015f",
1192
+ "sha256": "dce7c13e9b9c2eb6fe9028f69fe2fe2d48ad50546327c9d9c1232191425f1b7c",
1193
1193
  "mode": 420,
1194
1194
  "origin": "kit"
1195
1195
  },
@@ -1419,7 +1419,7 @@
1419
1419
  "ownerSkill": "git-worktree-recover",
1420
1420
  "surface": "claude",
1421
1421
  "installRole": "consumer",
1422
- "sha256": "435c3a32a0c31dbefc774d8f6caa30cae9f23026930292ea0c364d2115ed3e52",
1422
+ "sha256": "3251c8db671286330e48748719e05ee3fdc0555d93d61d7fee3fc0e0d2868e92",
1423
1423
  "mode": 420,
1424
1424
  "origin": "kit"
1425
1425
  },
@@ -1699,7 +1699,7 @@
1699
1699
  "ownerSkill": "orchestrate-wave",
1700
1700
  "surface": "claude",
1701
1701
  "installRole": "consumer",
1702
- "sha256": "20a972d7c13f059b1fda4daaeb77da777c898620bf9ec6bf6dd19c31b7e41d90",
1702
+ "sha256": "9690ec772a99131c225037dd4bca884e899c133a8e460c36b26a25d6c6c797e1",
1703
1703
  "mode": 420,
1704
1704
  "origin": "kit"
1705
1705
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikon85/agent-workflow-kit",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "description": "Portable AI-agent workflow skills (plan → execute → land → learn) for Claude Code & Codex — grilling, TDD, diagnosis, two-axis code review, cross-model Codex review, design & domain-modeling, plus a skill router (ask-matt). npx init/update/diff/uninstall.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import re
7
+ import subprocess
7
8
  import unittest
8
9
  from pathlib import Path
9
10
 
@@ -12,7 +13,8 @@ MANIFEST_PATH = ROOT / ".claude/skills/skill-manifest.json"
12
13
  START = re.compile(r"^<!-- readiness:block ([a-z][A-Za-z0-9]*) -->$")
13
14
  END = "<!-- readiness:end -->"
14
15
  SURFACE = {"claude": ".claude/skills", "codex": ".agents/skills"}
15
- REQUIRED = {
16
+ FIXTURES = ROOT / "test/fixtures/readiness"
17
+ REQUIRED_V1 = {
16
18
  "to-prd": ["issueTracker", "managedBoard"],
17
19
  "to-issues": ["issueTracker", "managedBoard", "specCompleteness"],
18
20
  "to-waves": ["issueTracker", "managedBoard", "specCompleteness"],
@@ -23,7 +25,7 @@ REQUIRED = {
23
25
  "project-release": ["projectReleaseProfile"],
24
26
  "security-audit": ["securityAuditRunbook"],
25
27
  }
26
- OPTIONAL = {
28
+ OPTIONAL_V1 = {
27
29
  "wrapup": {"deployReport": "prodTarget"},
28
30
  "orchestrate-wave": {"projectRecipe": "orchestrateWaveRecipe"},
29
31
  "spec-self-critique": {"projectEnrichment": "specCritiqueLayer"},
@@ -32,6 +34,74 @@ OPTIONAL = {
32
34
  "audit-skills": {"projectChecks": "auditSkillsLayer"},
33
35
  "git-worktree-recover": {"projectRecovery": "worktreeRecoveryLayer"},
34
36
  }
37
+ COMPAT_UPDATE_SCRIPT = r"""
38
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
39
+ import { join } from 'node:path';
40
+ import { pathToFileURL } from 'node:url';
41
+ const [repo, fixturePath] = process.argv.slice(-2);
42
+ const load = async (path) => import(pathToFileURL(join(repo, path)));
43
+ const { init } = await load('src/commands/init.mjs');
44
+ const { update } = await load('src/commands/update.mjs');
45
+ const { checkSkill } = await load('scripts/readiness.mjs');
46
+ const { makeKit, makeEmptyDir, cleanup } = await load('test/helpers.mjs');
47
+ const { PACKAGE_MANIFEST_NAME, readManifest, writeManifest } = await load('src/lib/manifest.mjs');
48
+ const { sha256 } = await load('src/lib/hash.mjs');
49
+ const readinessPath = '.claude/skills/skill-manifest.json';
50
+ const fixture = JSON.parse(await readFile(fixturePath, 'utf8'));
51
+ const current = JSON.parse(await readFile(join(repo, readinessPath), 'utf8'));
52
+ const previous = structuredClone(current);
53
+ for (const skill of Object.keys(fixture.readinessFixture.skills)) {
54
+ previous.skills[skill].readiness = {};
55
+ }
56
+ const kit = await makeKit({ '.claude/skills/to-prd/SKILL.md': 'fixture\n' });
57
+ const consumer = await makeEmptyDir();
58
+ async function setKitReadiness(manifest) {
59
+ const content = `${JSON.stringify(manifest, null, 2)}\n`;
60
+ const path = join(kit, readinessPath);
61
+ await mkdir(join(kit, '.claude/skills'), { recursive: true });
62
+ await writeFile(path, content);
63
+ const pkg = await readManifest(join(kit, PACKAGE_MANIFEST_NAME));
64
+ const entry = pkg.files.find(({ path: candidate }) => candidate === readinessPath);
65
+ if (entry) entry.sha256 = sha256(content);
66
+ else pkg.files.push({ path: readinessPath, kind: 'doc', sha256: sha256(content), mode: 0o644, origin: 'kit' });
67
+ await writeManifest(join(kit, PACKAGE_MANIFEST_NAME), pkg);
68
+ }
69
+ try {
70
+ await setKitReadiness(previous);
71
+ await init({ kitRoot: kit, consumerRoot: consumer });
72
+ for (const [relative, body] of Object.entries(fixture.readinessFixture.evidence)) {
73
+ const path = join(consumer, relative);
74
+ await mkdir(join(path, '..'), { recursive: true });
75
+ await writeFile(path, body);
76
+ }
77
+ const manifestPath = join(consumer, 'agent-workflow-kit.json');
78
+ const installed = await readManifest(manifestPath);
79
+ await writeManifest(manifestPath, {
80
+ ...installed,
81
+ readinessDecisions: fixture.readinessDecisions ?? {},
82
+ readinessFixture: fixture.readinessFixture,
83
+ });
84
+ const before = {};
85
+ for (const skill of Object.keys(fixture.readinessFixture.skills)) {
86
+ before[skill] = await checkSkill({ root: consumer, skill, manifest: previous });
87
+ }
88
+ await setKitReadiness(current);
89
+ const identity = { name: '@ikon85/agent-workflow-kit', version: '0.1.0', tarballIntegrity: 'sha512-fixture', manifestSha256: 'fixture-manifest' };
90
+ const result = await update({
91
+ kitRoot: kit, consumerRoot: consumer,
92
+ releaseIdentities: { installed: { name: identity.name, version: identity.version, manifestSha256: identity.manifestSha256 }, npm: identity, github: identity },
93
+ verify: async () => {},
94
+ });
95
+ const afterManifest = await readManifest(manifestPath);
96
+ const after = {};
97
+ for (const skill of Object.keys(fixture.readinessFixture.skills)) {
98
+ after[skill] = await checkSkill({ root: consumer, skill, manifest: current });
99
+ }
100
+ console.log(JSON.stringify({ before, result, afterManifest, after }));
101
+ } finally {
102
+ await cleanup(kit, consumer);
103
+ }
104
+ """
35
105
 
36
106
 
37
107
  def load_manifest() -> dict:
@@ -100,11 +170,32 @@ class ReadinessContractTests(unittest.TestCase):
100
170
  blocks = list(declaration.get("optionalBlocks", {}))
101
171
  self.assertEqual(len(blocks), len(set(blocks)), skill)
102
172
 
103
- def test_initial_enforcement_mapping_is_exact(self) -> None:
104
- for skill, required in REQUIRED.items():
105
- self.assertEqual(self.published[skill]["readiness"]["required"], required)
106
- for skill, blocks in OPTIONAL.items():
107
- self.assertEqual(self.published[skill]["readiness"]["optionalBlocks"], blocks)
173
+ def test_locked_v1_policy_cannot_disappear_from_the_manifest(self) -> None:
174
+ actual_required = {
175
+ skill: entry["readiness"]["required"]
176
+ for skill, entry in self.published.items()
177
+ if entry.get("readiness", {}).get("required")
178
+ }
179
+ actual_optional = {
180
+ skill: entry["readiness"]["optionalBlocks"]
181
+ for skill, entry in self.published.items()
182
+ if entry.get("readiness", {}).get("optionalBlocks")
183
+ }
184
+ self.assertEqual(actual_required, REQUIRED_V1)
185
+ self.assertEqual(actual_optional, OPTIONAL_V1)
186
+
187
+ def test_every_declared_consumer_has_the_standard_preflight(self) -> None:
188
+ consumers = {
189
+ skill: entry for skill, entry in self.published.items()
190
+ if entry.get("readiness")
191
+ }
192
+ self.assertGreater(len(consumers), 0)
193
+ for skill, entry in consumers.items():
194
+ expected = f"node scripts/readiness.mjs check --skill {skill} --json"
195
+ for surface in entry["surfaces"]:
196
+ path = ROOT / SURFACE[surface] / skill / "SKILL.md"
197
+ body = path.read_text(encoding="utf-8")
198
+ self.assertEqual(body.count(expected), 1, f"{surface}:{skill}")
108
199
 
109
200
  def test_markers_are_balanced_declared_and_surface_equal_when_activated(self) -> None:
110
201
  for skill, entry in self.published.items():
@@ -114,6 +205,7 @@ class ReadinessContractTests(unittest.TestCase):
114
205
  path = ROOT / SURFACE[surface] / skill / "SKILL.md"
115
206
  self.assertTrue(path.is_file(), f"missing published surface: {path}")
116
207
  sequence = marker_sequence(path.read_text(encoding="utf-8"), declared)
208
+ self.assertEqual(set(sequence), declared, f"undeclared marker coverage: {surface}:{skill}")
117
209
  sequences.append((surface, sequence))
118
210
  if len(sequences) > 1:
119
211
  validate_surface_sequences([sequence for _, sequence in sequences])
@@ -134,6 +226,34 @@ class ReadinessContractTests(unittest.TestCase):
134
226
  with self.assertRaises(AssertionError):
135
227
  validate_surface_sequences([["projectEnrichment"], []])
136
228
 
229
+ def test_legacy_and_current_consumers_keep_previously_ready_skill_cores(self) -> None:
230
+ fixtures = sorted(FIXTURES.glob("*/agent-workflow-kit.json"))
231
+ self.assertEqual([path.parent.name for path in fixtures], ["current", "legacy"])
232
+ for fixture_path in fixtures:
233
+ fixture = json.loads(fixture_path.read_text(encoding="utf-8"))
234
+ scenario = fixture["readinessFixture"]
235
+ with self.subTest(fixture=fixture_path.parent.name):
236
+ run = subprocess.run(
237
+ ["node", "--input-type=module", "-e", COMPAT_UPDATE_SCRIPT,
238
+ str(ROOT), str(fixture_path)],
239
+ check=True, capture_output=True, text=True,
240
+ )
241
+ proof = json.loads(run.stdout)
242
+ self.assertEqual(proof["result"]["state"], "applied")
243
+ self.assertEqual(proof["result"]["availability"]["newlyBlocked"], [])
244
+ for skill, expected in scenario["skills"].items():
245
+ self.assertEqual(proof["before"][skill]["verdict"], "ready", skill)
246
+ verdict = proof["after"][skill]
247
+ self.assertNotEqual(verdict["verdict"], "blocked", skill)
248
+ self.assertEqual(verdict["verdict"], expected["verdict"], skill)
249
+ self.assertEqual(verdict["inactiveBlocks"], expected["inactiveBlocks"], skill)
250
+ self.assertEqual(
251
+ proof["afterManifest"].get("readinessDecisions", {}),
252
+ scenario["expectedDecisions"],
253
+ "unavailable behavior must not manufacture a decision",
254
+ )
255
+ self.assertEqual(proof["afterManifest"]["readinessFixture"], scenario)
256
+
137
257
 
138
258
  if __name__ == "__main__":
139
259
  unittest.main()