@sabaiway/agent-workflow-kit 1.17.0 → 1.19.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/CHANGELOG.md CHANGED
@@ -4,6 +4,61 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
4
4
  is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
5
5
  every `migrations/<version>-<slug>.md` newer than it, in semver order.
6
6
 
7
+ ## 1.19.0 — One-command freshness: `init` refreshes memory too, and a capability-adaptive `status` (kit)
8
+
9
+ A **feature** release that closes the returning-user gap and modernizes the status surface. The
10
+ deployment-lineage head stays **`1.3.0`** (no `docs/ai` structural change, no migration); the kit
11
+ **package** version is a separate axis.
12
+
13
+ - **`init` now leaves no stale core member.** After installing/refreshing the kit, `npx
14
+ @sabaiway/agent-workflow-kit@latest init` also refreshes the **memory substrate** and the
15
+ **methodology engine** over npm — so a returning user is no longer left with silently stale memory.
16
+ The memory refresh is **best-effort: a miss is a loud DEGRADED success** — a warning with the exact
17
+ recovery command (and the on-disk version) plus **exit 0**, never a silent skip and never the engine's
18
+ hard STOP. New **`--no-memory`** flag skips it for air-gapped/scripted installs. The cascade
19
+ membership is derived from the one family registry and drift-guarded; bridges are still placed by
20
+ `setup`, never by `init`.
21
+ - **Capability-adaptive `status` output.** The direct-CLI status view (`node tools/family-registry.mjs`)
22
+ is rebuilt as a `surface → view-model → renderers` pipeline: it auto-detects the terminal (plain vs
23
+ ANSI, color via `NO_COLOR`/`FORCE_COLOR`, width with a 40-col floor, ASCII-glyph fallback) and renders
24
+ all four blocks (members · bridges · project deploy/visibility · settings). `--format=<auto|plain|ansi|json>`
25
+ (with `--json` as sugar) selects the surface; unknown flags and a missing `--dir` value now **reject
26
+ loudly** instead of being silently ignored.
27
+ - **Additive `--json` freshness signal.** Each `installed[]` entry gains a structural `refresh`
28
+ `{ behind, recommend }` object (derived from the registry, never parsed from a caveat). The
29
+ agent-mediated `/agent-workflow-kit status` reads it to show a localized "needs refresh" label + the
30
+ exact command **once**; every existing envelope field is unchanged.
31
+ - **Docs.** Install help + READMEs document the memory/engine refresh, `--no-memory`, the degraded-success
32
+ recovery, and that bridges are not installed by `init`. Tarball **75 → 81** (the pure member-table leaf
33
+ + five status-presenter modules).
34
+
35
+ ## 1.18.0 — Agent-writable orchestration config (`set-recipe`), version-aware setup, durable session contracts (kit)
36
+
37
+ A **feature** release. The per-project recipe config (`docs/ai/orchestration.json`) is no longer
38
+ hand-edit-only: a new **`set-recipe`** writer turns plain-language intent into a validated, previewed,
39
+ atomic write — and `setup` now surfaces bridge versions and proactively offers to set the review recipe
40
+ when a backend becomes ready. The deployment-lineage head stays **`1.3.0`** (no `docs/ai` structural
41
+ change, no migration); the kit **package** version is a separate axis.
42
+
43
+ - **`/agent-workflow-kit set-recipe` (new WRITER).** The agent maps plain language → explicit
44
+ `--set <activity>.<slot>=<recipe>` / `--unset <activity>.<slot>` ops; the kit validates → merges →
45
+ **previews by default** → writes only on `--write`. Split modules: `tools/orchestration-config.mjs`
46
+ (schema/read/pure — the shared slot-recipe validity table + `parseOp` / `applySetOps` /
47
+ `serializeConfig` / the canonical-refresh helpers) and `tools/orchestration-write.mjs` (the **only**
48
+ fs-writer — deployment gate, exclusive-create temp + rename, symlink/TOCTOU-safe, last-writer-wins).
49
+ `procedures` never imports the writer → the read-only invariant is **structural**. Renamed from the
50
+ planned `orchestrate` (it never *runs* a recipe). Hand-editing the file stays fully supported.
51
+ - **Setup surfaces versions + closes the loop.** Each skill line shows the bridge version (`(vX)` for a
52
+ fresh place / equal refresh, `(vOld → vNew)` on a bump, never `vnull → …`); a closing pointer at
53
+ `/agent-workflow-kit status`; and — re-detecting AFTER apply — a proactive `set-recipe` offer for
54
+ **both** `plan-authoring.review` and `plan-execution.review` when a review backend just became ready.
55
+ - **Canonical-refresh reaches the filled base.** `inject-methodology` refreshes a filled pointer slot to
56
+ the current engine canon when its content matches a known-prior fragment (a customization is preserved
57
+ + advised); the `_README` refresh reuses the same `refreshIfCanonical` helper, and the upgrade
58
+ config-ensure is now seed-**or-refresh**.
59
+ - **Docs.** New `### Mode: set-recipe`; `procedures` / `velocity` / README no longer say the config is
60
+ "never written for you". Tarball **72 → 75** (three new `tools/*.mjs`).
61
+
7
62
  ## 1.17.0 — Hardened Codex bridge: quality-first delegation, clean capture, enforced git-write boundary (kit)
8
63
 
9
64
  A **feature** release. The bundled `codex-cli-bridge` (`bridges/codex-cli-bridge/`) is overhauled to
package/README.md CHANGED
@@ -194,20 +194,25 @@ other agent). The manual path works identically but **isn't reflected in install
194
194
  <details>
195
195
  <summary><b>What <code>init</code> touches — and how to undo it</b></summary>
196
196
 
197
- `init` is **additive — it never deletes your settings.** It writes only its own namespaced slots:
197
+ `init` is **additive — it never deletes your settings.** It writes its own namespaced slots, then
198
+ refreshes the other npm core members so a returning `init` leaves **no stale core member**:
198
199
 
199
200
  | Path | What |
200
201
  |------|------|
201
202
  | `~/.claude/skills/agent-workflow-kit/` | the kit itself (refreshed on every `init`) |
203
+ | `~/.claude/skills/agent-workflow-memory/` | the **memory substrate**, refreshed via `npx @sabaiway/agent-workflow-memory@latest init` — **best-effort:** a failure is a **loud degraded success** (warning + the exact recovery command + exit 0), never silent; skip with `--no-memory` |
204
+ | `~/.claude/skills/agent-workflow-engine/` | the **methodology engine** the kit reads live, refreshed via `npx @sabaiway/agent-workflow-engine@latest init` — **required** (the live read STOPs without it); skip with `--no-engine` |
202
205
  | `~/.codex/skills/agent-workflow-kit` | a symlink — only if you have Codex |
203
206
  | `…/global_workflows/agent-workflow-kit.md` | a managed file — only if you have Devin Desktop |
204
207
 
205
- Your other Codex skills and Devin Desktop workflows are never touched. If one of those exact slots
206
- already holds a file the kit didn't write, it is **left alone** and you're told re-run with
207
- `--force` to replace it (the original is first copied to `*.bak.<timestamp>` and the restore
208
- command is printed).
208
+ The **execution-backend bridges** (`codex` / `agy`) are **not** installed by `init` set one up on
209
+ demand with `/agent-workflow-kit setup`. Your other Codex skills and Devin Desktop workflows are
210
+ never touched. If one of those exact slots already holds a file the kit didn't write, it is **left
211
+ alone** and you're told — re-run with `--force` to replace it (the original is first copied to
212
+ `*.bak.<timestamp>` and the restore command is printed).
209
213
 
210
- **Uninstall:** delete the slots above (the kit folder, the symlink, the workflow file).
214
+ **Uninstall:** delete the slots above (the kit / memory / engine folders, the symlink, the workflow
215
+ file), or run the guarded `/agent-workflow-kit uninstall`.
211
216
  </details>
212
217
 
213
218
  ---
@@ -223,7 +228,8 @@ command is printed).
223
228
  | `/agent-workflow-kit setup [backend]` | opt-in, any time | **link-only** auto-setup of a bridge: places the bundled bridge skill (only into an absent / empty / managed dir — never overwrites an unmanaged one) + links its wrappers onto `PATH` via managed symlinks (idempotent; refuses to clobber a non-symlink; try `--dry-run` to preview). The binary install + the one-time subscription login stay **manual**: it prints the exact **login** command and points the binary install at each bridge's `setup/README.md`. POSIX wrappers — on Windows use WSL. Never commits, never runs a subscription CLI. |
224
229
  | `/agent-workflow-kit status` | any time | **read-only** single view of **versions + deployment + settings + bridges**: which members (kit / memory / engine / the two bridges) are installed and at what version (with an honest "installed on this machine" note when one is behind) and — in a project — what's deployed (`docs/ai`, the version stamps, and the **visibility**: visible / hidden / unclear), plus your settings (orchestration recipes, attribution, velocity) and the bridges' readiness. The two version axes (package number vs deployment-structure head) stay decoupled. Never writes, never commits, never runs a subscription CLI. |
225
230
  | `/agent-workflow-kit recipes` | any time | **read-only** orchestration advisor: presents four named recipes for composing the bridges into plan → execute → review — **Solo / Reviewed / Council / Delegated** — plans + recommends one for your environment (degrading with a stated reason when a backend isn't ready), and offers the choice. The orchestrator runs it via the bridge skills and **always commits**; the kit never executes a recipe, never runs a subscription CLI, never commits. |
226
- | `/agent-workflow-kit procedures <activity>` | any time | **read-only** activity-procedures advisor: prints a named activity's ordered steps (`plan-authoring` / `plan-execution`) read **live** from the engine, plus the **resolved recipe per slot** from your hand-edited `docs/ai/orchestration.json` + backend readiness (default Reviewed when a backend is ready, Council on request, slot-aware incl. Delegated). `--override <slot>=<recipe>` adjusts one slot per run. Composes with `recipes`; never writes, never commits, never runs a subscription CLI. |
231
+ | `/agent-workflow-kit procedures <activity>` | any time | **read-only** activity-procedures advisor: prints a named activity's ordered steps (`plan-authoring` / `plan-execution`) read **live** from the engine, plus the **resolved recipe per slot** from your `docs/ai/orchestration.json` (agent-writable via `set-recipe`, or hand-edited) + backend readiness (default Reviewed when a backend is ready, Council on request, slot-aware incl. Delegated). `--override <slot>=<recipe>` adjusts one slot per run. Composes with `recipes`; never writes, never commits, never runs a subscription CLI. |
232
+ | `/agent-workflow-kit set-recipe` | any time | **config writer** for `docs/ai/orchestration.json`: tell the agent your preference in plain language and it maps it to explicit `--set <activity>.<slot>=<recipe>` / `--unset` ops; the kit validates, **previews by default**, and writes only on `--write` (deployment-gated, atomic, symlink/TOCTOU-safe), resolving the effective recipe vs live readiness. Writes **only** that file — **never runs a backend, never commits**; hand-editing stays fully supported. |
227
233
  | `/agent-workflow-kit uninstall` | opt-in, any time | **guarded teardown** — the inverse of `init` / `setup`. Removes only what's **provably ours** (managed skill dirs + bridge wrappers; in a project, the hidden-mode git-ignore block it added + the pre-commit hook it installed); **never deletes** your `docs/ai` / `AGENTS.md` (prints the exact `rm` to run by hand) or your `.claude/settings.json` (prints an **edit** — remove the attribution key, review any velocity `permissions.*` — never an `rm`). Always `--dry-run` first; preflight-then-mutate; never commits. |
228
234
  | `/agent-workflow-kit velocity` | Claude Code · opt-in | **onboarding velocity profile** — seeds a fixed, audited **read-only** allowlist into `.claude/settings.json` so routine read-only commands stop idling on approval prompts while you're away; opt-in `acceptEdits`; plus a **read-only advisory** of likely project gate commands to add by hand. Writes **only** `.claude/settings.json` — **never** allowlists commit/push/publish, never writes `settings.local.json`, never commits. A seeded entry is a **trust posture, not a sandbox** (a redirection/command-substitution residual remains, closed by a deferred hook); a direct commit/push/publish still asks. `--dry-run` first. |
229
235
 
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.17.0'
6
+ version: '1.19.0'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
@@ -28,6 +28,10 @@ when it is present and healthy, and otherwise uses its **own bundled copy** (`re
28
28
  memory substrate**. (The methodology slot is a separate axis: its fragment is read **live from the
29
29
  installed `agent-workflow-engine`**, which `npx @sabaiway/agent-workflow-kit@latest init` installs — a
30
30
  runtime dependency placed by `init` and read live; see *Methodology slot reconciliation* below.)
31
+ `init` also **refreshes the installed memory substrate** (best-effort — a miss is a loud DEGRADED
32
+ success: a warning with the exact recovery command + exit 0, never silent, never the engine's hard
33
+ STOP; `--no-memory` skips it), so a returning `init` leaves **no stale core member**. The
34
+ execution-backend bridges are still **not** installed by `init` (placed on demand by `setup`).
31
35
 
32
36
  **Detection (kit-owned, decided BEFORE any project write).** Run the kit's **own shipped**
33
37
  validator — `node ${CLAUDE_SKILL_DIR}/tools/manifest/validate.mjs <memory-skill-dir>` — never a
@@ -107,7 +111,8 @@ Pick the mode from the user's invocation. Auto-detect an existing `docs/ai/` to
107
111
  - **`/agent-workflow-kit setup [backend]`** — the **link-only**, opt-in companion to `backends`: place the bundled bridge skill + link its wrappers onto `PATH`. **In-agent only** — `init` (npx) never places bridges. The binary install + the interactive subscription login stay **manual** (it prints the exact commands); idempotent; refuses to clobber a non-symlink; never commits, never runs a subscription CLI.
108
112
  - **`/agent-workflow-kit status`** — read-only view of the **whole family**: which members (kit / memory / engine / the two bridges) are installed, at what version, and — in a project — what is deployed (`docs/ai`, the version stamps, the hidden-mode fence). Never writes, never commits, never runs a subscription CLI.
109
113
  - **`/agent-workflow-kit recipes`** — read-only **orchestration advisor**: present the four recipes (Solo / Reviewed / Council / Delegated) over the bridges' role vocabulary, plan + recommend one for the current environment, and offer the choice. **The orchestrator executes the chosen recipe via the bridge skills and always commits** — the kit only surfaces/selects/plans it; it never executes a recipe, never runs a subscription CLI, never commits.
110
- - **`/agent-workflow-kit procedures <activity>`** — read-only **activity-procedures advisor**: print the ordered steps of a named activity (`plan-authoring` / `plan-execution`) read **live** from the installed engine (`references/procedures.md`), and the **resolved effective recipe per slot** from the per-project `docs/ai/orchestration.json` (hand-edited, strict JSON) + backend readiness (default = Reviewed when a backend is ready, Council on request, slot-aware incl. Delegated; graceful default vs loud override degradation). A per-run `--override <slot>=<recipe>` overrides one slot. Composes with `recipes` (which stays read-only); never writes, never commits, never runs a subscription CLI.
114
+ - **`/agent-workflow-kit procedures <activity>`** — read-only **activity-procedures advisor**: print the ordered steps of a named activity (`plan-authoring` / `plan-execution`) read **live** from the installed engine (`references/procedures.md`), and the **resolved effective recipe per slot** from the per-project `docs/ai/orchestration.json` (strict JSON; agent-writable via `set-recipe` or hand-edit) + backend readiness (default = Reviewed when a backend is ready, Council on request, slot-aware incl. Delegated; graceful default vs loud override degradation). A per-run `--override <slot>=<recipe>` overrides one slot. Composes with `recipes` (which stays read-only); never writes, never commits, never runs a subscription CLI.
115
+ - **`/agent-workflow-kit set-recipe`** — the **config writer** for `docs/ai/orchestration.json`: turn the user's plain language into explicit `--set <activity>.<slot>=<recipe>` / `--unset` ops; the kit validates, merges, **previews by default**, and writes only on `--write` (deployment-gated, atomic, symlink/TOCTOU-safe). Resolves the effective recipe vs live readiness (degradation honesty on both paths). **Writes only `docs/ai/orchestration.json`; never runs a backend, never commits.** Hand-editing the file stays fully supported.
111
116
  - **`/agent-workflow-kit uninstall`** — the **guarded teardown** companion to `init`/`setup`. Removes what they placed — installed skill dirs + the bridge wrappers — and, in a project, reverses the hidden-mode fence + the marker pre-commit hook. **Never deletes user-authored content**: it prints the exact `rm` for `docs/ai` / `AGENTS.md` and an **edit** for `.claude/settings.json` (the `includeCoAuthoredBy` key + any velocity `permissions.*`), for you to run by hand. `--dry-run` first, always; preflight-then-mutate; never commits.
112
117
  - **`/agent-workflow-kit velocity`** — opt-in onboarding **velocity profile**: seed a fixed, audited **read-only** Claude Code allowlist into `.claude/settings.json` so routine read-only commands stop idling on approval prompts; opt-in `acceptEdits`; plus a **read-only advisory** of likely project gate commands to add by hand. **Writes only `.claude/settings.json`, never allowlists commit/push/publish, never writes `settings.local.json`, never commits.** `--dry-run` first.
113
118
 
@@ -283,9 +288,9 @@ Fill strategy:
283
288
 
284
289
  **Hidden-mode footprint reconcile — stamp-independent, same gate, BEFORE the equal-head short-circuit (D9 / AD-014).** A deployment does not record whether it chose `hidden`, so first **infer visibility**: `node ${CLAUDE_SKILL_DIR}/tools/hide-footprint.mjs --dir <project> --reconcile --dry-run` (writes **zero bytes**). It reports one of — **visible** (the entry point is tracked) → nothing to do; **ambiguous** (untracked but not ignored — could be a fresh uncommitted repo, or a hide that broke) → **ASK** the user which it is, never guess; **hidden** → re-run without `--dry-run` to migrate any older **machine-global** hide to the **project-local** `.git/info/exclude` (one managed block; folds in the legacy `.claude/skills/` line), idempotently (a clean re-run is zero-diff). Handle its surfaced paths exactly as bootstrap step 9 (already-committed → show `git rm --cached`, ask before `--include`; generic-name present file → ask; **leftover machine-wide ignore block → ASK before `--remove-global`**, default keep + report). No Node on the agent host / Windows → as step 9. This runs on **every** hidden upgrade, like the methodology slot — no lineage-head bump, no migration file.
285
290
 
286
- **Orchestration config ensure — stamp-independent, same gate, BEFORE the equal-head short-circuit.** Ensure `docs/ai/orchestration.json` exists: **create it if missing**, **preserve it byte-for-byte if it already exists** (a user may have edited it — never clobber it). In the **delegated** path memory does this from its own template (memory upgrade step 2); in the **fallback** path the kit seeds it from `${CLAUDE_SKILL_DIR}/references/templates/orchestration.json`. Like the pointer slots + the footprint reconcile, this lets an equal-head (`1.3.0`) deployment gain the config seed **without a lineage-head bump or a migration file** (it is a `.json`, inherently outside the docs cap-validator). Report it in the step 4 / step 8 success report (config *seeded* vs *already present*).
291
+ **Orchestration config ensure (seed-or-refresh) — stamp-independent, same gate, BEFORE the equal-head short-circuit.** Ensure `docs/ai/orchestration.json` exists **and its onboarding note is current**: **create it from the template if missing**; **if it already exists, preserve every activity/slot the user set, and refresh ONLY the `_README` note when the existing one still matches a known prior canonical** — the tested `refreshIfCanonical` / `refreshReadme` in `tools/orchestration-config.mjs` is the source of truth for that decision (normalize CRLF/whitespace before comparing; a *customized* `_README` is preserved verbatim; a *malformed* existing config is **preserved + a loud warning**, never clobbered or silently skipped). The current note points at `/agent-workflow-kit set-recipe` (the config is now agent-writable no more "never written for you"). **The refresh helper is kit-owned** — in the **delegated** path memory only seeds/preserves the file (memory upgrade step 2) and the **kit** then applies the `_README` refresh; in the **fallback** path the kit seeds-or-refreshes directly from `${CLAUDE_SKILL_DIR}/references/templates/orchestration.json`. (Memory stays standalone — it never depends on this helper.) Like the pointer slots + the footprint reconcile, this reaches an equal-head (`1.3.0`) deployment **without a lineage-head bump or a migration file** (it is a `.json`, inherently outside the docs cap-validator). Report it in the step 4 / step 8 success report (config *seeded* / *note refreshed* / *already current* / *customized — preserved*).
287
292
  4. **Equal-head exit — a real successful-exit report, not a bare stop.** If the stamp **equals** the head, the lineage is up to date — but step 3 (the methodology-slot **and** hidden-mode footprint reconciles) ran first and may have changed things, so this is a proper exit report, not a no-op:
288
- - **Report step 3's outcome in plain language** — for **each** pointer (workflow-methodology and orchestration-recipes) whether it was *added*, was *already present* (nothing changed), or was *skipped because the entry point is over its line limit* (the cap-refusal soft-skip from step 3, with its reason); whether the `docs/ai/orchestration.json` config was *seeded* or was *already present* (a user edit is preserved); and, for a hidden deployment, whether the hidden-mode footprint was *moved to project-local*, was *already project-local* (nothing changed), or needed a question (ambiguous visibility / a leftover machine-wide block). Plain wording only — never the reconcile/slot/anchor/marker terms (Gotcha: never leak kit internals).
293
+ - **Report step 3's outcome in plain language** — for **each** pointer (workflow-methodology and orchestration-recipes) whether it was *added*, was *already present* (nothing changed), or was *skipped because the entry point is over its line limit* (the cap-refusal soft-skip from step 3, with its reason); whether the `docs/ai/orchestration.json` config was *seeded* (created from the template), had its onboarding note *refreshed*, was *already current*, or carried a *customized note that was preserved* (a user edit is never clobbered); and, for a hidden deployment, whether the hidden-mode footprint was *moved to project-local*, was *already project-local* (nothing changed), or needed a question (ambiguous visibility / a leftover machine-wide block). Plain wording only — never the reconcile/slot/anchor/marker terms (Gotcha: never leak kit internals).
289
294
  - **Name the version axis so the package number isn't mistaken for a newer release.** When you state the deployment is up to date, say it is current at the **deployment-lineage head** (`1.3.0`) and add one plain line: this head versions the deployed `docs/ai` structure and is a **separate axis** from the kit **package** version published on npm/GitHub (the larger number users see on the repo/npm page). A packaging-only release can bump that package version **without** moving the head — the head advances only when the deployed `docs/ai` structure changes — so an equal-head report is **not** a stale deployment even though GitHub shows a higher package number. (This is the only place the two axes meet the user in `upgrade`; surfacing it here prevents the recurring "but GitHub shows a higher version" confusion.)
290
295
  - **Print the report footer** in the canonical order (version block → one-line backend-status line → welcome mat — the shared contracts above; rendered from the helpers, same host-can't-run skip-with-reason). The welcome mat closes on **one** caveat-aware next step (a behind member first, else `setup` / `recipes` / `velocity`).
291
296
  - **Then ask before committing — never auto-commit.** If step 3 added the slot (or anything else changed), report it and ask. If step 3 was a pure zero-diff no-op and nothing else changed, say **"already up to date"** and still print the read-only version block + backend line.
@@ -320,6 +325,11 @@ For each backend it:
320
325
  2. **Links its wrappers** (`codex-exec` / `codex-review`; `agy-run`) onto `--bindir` via **managed symlinks** — replacing only a symlink that already points at our source. A non-symlink or a foreign symlink → **STOP**; it **preflights every target first**, so a conflict on one wrapper makes **zero** changes. If `--bindir` is not on `PATH`, it prints the one-line `export PATH=…` to add — it never edits a shell rc.
321
326
  3. **Guides the manual, secret-bearing steps it will NOT automate** — the binary install (each bridge's `setup/README.md` §1) and the one-time interactive subscription login (`codex login` / `agy`) — printing the exact command for whichever axis is still missing (axis-aware: it can ask for both the CLI and the login at once).
322
327
 
328
+ **Close-the-loop output (surface both, localized).** The tool prints, after the per-backend report:
329
+ - a **bridge version** on each skill line — `(vX)` for a fresh place / equal refresh, `(vOld → vNew)` when a refresh bumps the bridge (never `vnull → …`);
330
+ - a **status pointer** — the full family + deployment version view lives in `/agent-workflow-kit status`;
331
+ - a **proactive recipe offer** when a setup just made a review backend ready (re-detected AFTER apply, so it reflects the real new state): it prints `/agent-workflow-kit set-recipe --set plan-authoring.review=<depth>` **and** `…plan-execution.review=<depth>` (Council when both are ready, else Reviewed). Relay it in plain language: offer to set the review recipe for **both** planning and execution review (preview first; you'll write it via *Mode: set-recipe*, or they can hand-edit) — never offer only `plan-execution`. Ask if the scope is unclear.
332
+
323
333
  **Windows:** the wrappers are POSIX `.sh`; on `win32` it reports *unsupported — use WSL* and mutates nothing.
324
334
 
325
335
  **Exit codes:** `0` = done / already set up / only manual steps remain (guidance is never a failure); **non-zero** = a STOP (a dir/symlink it refuses to clobber), a bad argument, a missing bundle, or a native fs error (the underlying reason is preserved in the message).
@@ -330,7 +340,9 @@ Read-only. The **single answer to "versions + deployment + settings + bridges"**
330
340
 
331
341
  Run `node ${CLAUDE_SKILL_DIR}/tools/family-registry.mjs --json [--dir <project>]` and render it **compact**, in the user's conversational language — **never paste the JSON or any internal field name** (no-leak rule). Map the **`installed[].state`** token via the value→plain-language map under *The version block + welcome mat* (the `visibility` and wrapper states have their own phrasings, below). Present, each area on its own line(s), routing detail to its domain mode:
332
342
 
333
- 1. **Versions — the version block** (from `installed[]` + `deploymentHead`): the deployment-structure head, the installed package versions by `display`, the two-axes disambiguation, plus any member `notes` (e.g. a behind member's refresh+restart line). This is the shared version block above.
343
+ 1. **Versions — a status-only render from `installed[]` + `deploymentHead`** (this is **NOT** the shared notes-based version block — see the separation note below): the deployment-structure head, then each member by its `display` showing its `version` (or, when there is no version, the plain phrase for its `state`, mapped above), plus the two-axes disambiguation. **Freshness comes from `installed[].refresh`, not from `notes`:** for each member whose **`refresh.behind`** is `true`, show a **localized "needs refresh"** label and the **verbatim `refresh.recommend`** command **exactly once** (the command/package name stays source-language; **do not also paste the English `notes` caveats** — `refresh.recommend` is the single source of the recovery step, so the command is never duplicated on this surface). Lead with a one-line **headline count** derived from `installed[].state` + `refresh.behind` (e.g. *"5 members installed · 1 needs a refresh"*).
344
+
345
+ > **Status reads `refresh`; the shared version block + the bootstrap/upgrade footers stay `notes`-based (unchanged this release).** *Mode: status* has its OWN status-only render (above), keyed on `installed[].refresh.behind` / `refresh.recommend`. The shared **version block** (under *The version block + welcome mat*) and the bootstrap (step 11) + every upgrade (steps 4 / 8) report footer still consume `installed[].notes` verbatim — that wiring is deliberately **untouched** here (their migration onto `refresh` is deferred). Do not rewrite those footers onto `refresh`.
334
346
  2. **Deployment (`--dir`)** (from `project`): whether `docs/ai/` is deployed + the deploy stamps by `display`; and **visibility** — render `project.visibility.state` in **user-safe words only**: *visible (tracked)* / *hidden (git-ignored, local-only)* / *unclear (uncommitted or partially set up)* — **never** the words "hidden fence" or any marker term. A `visibility.error` → surface it plainly.
335
347
  3. **Settings (`--dir`, one line each)** (from `project.settings`):
336
348
  - **recipes** — the effective recipe per slot (detail → `/agent-workflow-kit procedures` / `recipes`); a `recipes.detectError` → say the backends couldn't be checked, so recipes floored at solo.
@@ -371,7 +383,7 @@ The two v1 activities (canon in the **installed engine**, `references/procedures
371
383
 
372
384
  Run **`node ${CLAUDE_SKILL_DIR}/tools/procedures.mjs <activity> [--override <slot>=<recipe>]… [--json]`**. It reads the activity's steps live from the engine and prints them **verbatim**, then the **resolved effective recipe per slot** from the per-project config + the read-only backend detector:
373
385
 
374
- 1. **Config = `docs/ai/orchestration.json`** — strict JSON, **hand-edited** (the kit reads + validates it; `recipes` stays read-only — there is no writer). Shape: `{ "<activity>": { "<slot>": "<recipe>" } }`; all slots optional (an absent slot → its computed default, stated); an optional `"_README"` string is allowed + ignored. `review` accepts `solo|reviewed|council`; `execute` accepts `solo|delegated`. Seeded by `init` (a user-editable template) — see *Mode: bootstrap*.
386
+ 1. **Config = `docs/ai/orchestration.json`** — strict JSON, **agent-writable via `/agent-workflow-kit set-recipe` (Mode: set-recipe) OR hand-edited** (the kit reads + validates it; `procedures`/`recipes` stay read-only — the writer is `set-recipe`). Shape: `{ "<activity>": { "<slot>": "<recipe>" } }`; all slots optional (an absent slot → its computed default, stated); an optional `"_README"` string is allowed + ignored. `review` accepts `solo|reviewed|council`; `execute` accepts `solo|delegated`. Seeded by `init` (a user-editable template) — see *Mode: bootstrap*.
375
387
  2. **Default resolution (config silent):** `review` → Reviewed if any review-capable backend is `ready`, else Solo (never Council by default); `execute` → Solo (Delegated is opt-in). **Degradation:** a config/computed default degrades **gracefully with a stated reason** (Council → Reviewed → Solo; Delegated → Solo); a per-run **`--override <slot>=<recipe>`** that can't be satisfied degrades **loudly** (a flagged warning, so you tell the user) — but is **still exit 0** (a valid request that gracefully degraded).
376
388
  3. **Exit codes:** `0` success; `2` usage (unknown `<activity>` / bad `--override` — a bare `--override <recipe>`, an unknown slot, an invalid recipe-for-slot, or a duplicate slot); `1` config error (malformed / schema-invalid / unreadable `orchestration.json`) **or** engine error (the installed engine is absent / invalid / **too old** to ship `references/procedures.md` — upgrade it with `npx @sabaiway/agent-workflow-engine@latest init`). A `1`/`2` failure is loud (`path: reason`), never a silent fallback.
377
389
 
@@ -379,6 +391,30 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/procedures.mjs <activity> [--override <slo
379
391
 
380
392
  **Invariants:** read-only · never writes · never commits · never runs a subscription CLI · the deterministic resolution is the kit's, the recipe execution is the orchestrator's.
381
393
 
394
+ ### Mode: set-recipe
395
+
396
+ The **config writer** for `docs/ai/orchestration.json` — the answer to *"set my standing recipe preference without hand-editing JSON."* **Division of labor (AD-025):** YOU turn the user's plain language into explicit ops; the KIT does the deterministic validate → merge → preview → write. It **previews by default** (writes nothing); `--write` applies. It **never runs a backend and never commits**. Hand-editing `docs/ai/orchestration.json` stays fully supported — this is an offered convenience, never a lock.
397
+
398
+ **Map the user's plain language → explicit ops** (the kit ships no NL parser; it performs no `all`-magic, so you expand scope explicitly, asking when unclear):
399
+
400
+ | user says (RU/EN) | op | scope |
401
+ |---|---|---|
402
+ | "оба ревьюят" / "both review" | `--set <activity>.review=council` | **disambiguate**: which activity? If both, pass `--set plan-authoring.review=council --set plan-execution.review=council`. |
403
+ | "один ревьюер" / "one reviewer" | `--set <activity>.review=reviewed` | per the named activity, else ask |
404
+ | "делегируй исполнение" / "delegate execution" | `--set plan-execution.execute=delegated` | execution only |
405
+ | "верни как было / сам" / "revert / do it myself" | `--unset <activity>.<slot>` | the named slot → its computed default |
406
+
407
+ Run **`node ${CLAUDE_SKILL_DIR}/tools/set-recipe.mjs [--set <activity>.<slot>=<recipe>]… [--unset <activity>.<slot>]… [--write] [--json]`**:
408
+
409
+ 1. **Grammar — always fully-qualified `<activity>.<slot>`** (the kit never guesses the activity; a bare `review=council` is rejected). `review` accepts `solo|reviewed|council`; `execute` accepts `solo|delegated`. Activities/slots: `plan-authoring.review`, `plan-execution.execute`, `plan-execution.review`.
410
+ 2. **Preview by default** — prints `current → proposed` for the **changed** slots only, plus the **effective recipe resolved against live backend readiness** (degradation stated honestly, e.g. *council requested, 1 ready reviewer → runs reviewed until a 2nd backend is ready*). It writes **nothing**. Re-run with **`--write`** to apply (same effective/degradation note — a direct `--write` is never quieter than the preview). `--unset` returns a slot to its computed default (reverting needs no hand-edit either). A no-op `--set` (slot already equals) writes nothing and never re-seeds the onboarding note.
411
+ 3. **`--write`** applies via a hardened, atomic write (deployment-gated — refuses to scatter a config into a repo with no `docs/ai`; exclusive-create temp + rename; symlink/TOCTOU-safe; last-writer-wins). It preserves the onboarding note + every untouched slot, normalizing to canonical 2-space JSON.
412
+ 4. **Exit codes:** `0` success (an explicit recipe that gracefully degrades is still `0`); `2` usage (a bare/duplicate op, or `--write` with no ops); `1` config error (malformed/unreadable config — the file is left **untouched**, never clobbered) or a write STOP (no deployment / a symlinked config). A `1`/`2` failure is loud; on a malformed config, offer to show the parse error so you can help the user fix the JSON.
413
+
414
+ Output is **English/structured** — **localize it to the user's conversational language** when you narrate. Surface the effective-recipe/degradation note plainly.
415
+
416
+ **Invariants:** writer (writes only `docs/ai/orchestration.json`) · never commits · never runs a subscription CLI · previews by default · degradation honesty on preview AND `--write` · hand-edit stays first-class.
417
+
382
418
  ### Mode: uninstall
383
419
 
384
420
  The **guarded teardown** — the inverse of `init` (the kit + engine skills) + `setup` (the bridges) + a hidden deploy. **In-agent, opt-in**, and built around one hard rule: **it never deletes user-authored content.** Run **`--dry-run` first, always**, show the user the classified plan in plain language, get explicit consent, then re-run with `--yes`. It **never commits**.
@@ -411,7 +447,7 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/velocity-profile.mjs [--dry-run | --apply] [
411
447
  - **"Keep per-edit approval prompts (recommended)"** — seed only the read-only allowlist; file edits still prompt.
412
448
  - **"Auto-accept file edits (`defaultMode: acceptEdits`)"** — present the honest FULL posture: it auto-applies Edit/Write AND auto-runs `mkdir`/`touch`/`mv`/`cp` in the working dir, is paired with the read-only allowlist, and — stated plainly — a settings-level allow rule is a **trust posture, not a sandbox**: a read-only entry can still write a file via output redirection, and (Claude Code's allow rules do not inspect command substitution) could in principle run another command via `cmd $(…)`. velocity **never adds `commit`/`push`/`publish` as allow rules** — so a direct `git push` still ASKs — but that same redirection/substitution residual means they are not *fully* closed until the deferred PreToolUse hook (family backlog). Note also that a `defaultMode` in `settings.local.json` would override this project-level write (local > project), since velocity writes only `.claude/settings.json`.
413
449
  3. **Only on an explicit yes**, re-run with `--apply` (add `--accept-edits` only if they chose the second option). It merges-don't-clobber (preserves `includeCoAuthoredBy`, every key, and existing allow entries) and writes **only** `.claude/settings.json`.
414
- 4. **Surface delegation-readiness, read-only.** If they want a step run Delegated, point them at the hand-edited `docs/ai/orchestration.json` (*Mode: procedures*); the tool never writes it.
450
+ 4. **Surface delegation-readiness, read-only.** If they want a step run Delegated, set it with `/agent-workflow-kit set-recipe --set plan-execution.execute=delegated` (*Mode: set-recipe*) or by hand-editing `docs/ai/orchestration.json`; **velocity itself never writes the orchestration config.**
415
451
 
416
452
  **Invariants:** creates `.claude/` if absent and writes **only** `.claude/settings.json` (no other file); **never** allowlists commit/push/publish; **never** writes `settings.local.json`; never commits; opt-in `acceptEdits`, never silent.
417
453
 
@@ -491,6 +527,6 @@ Deploy these into `AGENTS.md`; remove rows that don't apply to the stack.
491
527
  - [`references/scripts/`](references/scripts/) — the Node enforcement scripts (caps + staleness + index-freshness gate, 3-tier archive, hook installer) and their unit tests.
492
528
  - [`migrations/`](migrations/) — per-version upgrade steps; see `migrations/README.md`.
493
529
  - [`launchers/`](launchers/) — run the bootstrapper from non-Claude agents (`SKILL.md` is a native Codex skill; a Devin Desktop workflow launcher + install script). See `launchers/README.md`.
494
- - [`tools/`](tools/) — the family-wide tooling the kit **owns and ships**: `manifest/{schema.md,validate.mjs}` (the `capability.json` schema + the validator the kit runs as the memory detector, and root CI invokes), `commands.mjs` (the canonical **command catalog** + the pure `routeInvocation` router behind `/agent-workflow-kit help` and the safe unknown-invocation routing rule — one source of truth for the command surface, drift-guarded against the `### Mode:` headers), `delegation.mjs` (the executable delegate/fallback decision + hand-off plan), `inject-methodology.mjs` + `engine-source.mjs` (the bounded **two-slot** reconciliation — ensure-slot / inject-if-empty / cap for the `workflow:methodology` **and** `workflow:orchestration` pointers; both fragments read **live** from the installed `agent-workflow-engine` via `engine-source.mjs` (`deps.rel` selects which) — the family's one source of truth, no bundled mirror; fail-loud when the engine is needed but absent, orchestration soft-skipped when it would bust the cap), `detect-backends.mjs` (the read-only **backend detector** behind `/agent-workflow-kit backends`, plus the axis-aware `guideFor`; exports the readiness consts the planner reuses), `recipes.mjs` (the read-only **recipe planner** behind `/agent-workflow-kit recipes` — `RECIPES` / `planRecipe` / `recommendRecipe` over the bridges' role vocabulary, drift-guarded against `provides`/`cost`/`quota` + an engine↔kit recipe-name parity guard; pure, never runs a subscription CLI; also exports the pure `ACTIVITIES` / `resolveActivityRecipe` activity-procedures resolver), `procedures.mjs` (the read-only **activity-procedures advisor** behind `/agent-workflow-kit procedures` — reads `references/procedures.md` live from the engine via `engine-source.mjs`, reads + validates the hand-edited `docs/ai/orchestration.json`, and prints the steps + the resolved effective recipe per slot; drift-guarded activity/slot table vs the canon; read-only, never runs a subscription CLI), `setup-backends.mjs` (the **link-only** backend setup behind `/agent-workflow-kit setup` — place the bundled bridge + link wrappers), `fs-safe.mjs` (the shared symlink-traversal-safe copy/link/**remove/unlink** primitives that `setup-backends`, the npx installer, and the uninstaller use), `known-footprint.mjs` + `hide-footprint.mjs` (the **hidden-mode** registry + the single hide-writer behind step 9 / the upgrade reconcile — one managed block in the **project-local** `.git/info/exclude` covering the full AI/agent footprint; pinned by `known-footprint.test.mjs` drift-guard + `hide-footprint.test.mjs` / `.integration.test.mjs`), `family-registry.mjs` (the **unified family registry** behind `/agent-workflow-kit status` — aggregates every member's `capability.json`; pinned by a `family-registry.test.mjs` drift-guard), `uninstall.mjs` (the **guarded teardown** behind `/agent-workflow-kit uninstall` — classify each surface, preflight-then-mutate, never delete user-authored content), and `release-scan.mjs` (the attribution-off release gate). The bundled bridge skill mirrors live under [`bridges/`](bridges/) (byte-identical to the repo-root bridges, pinned by `test/bridges-mirror.test.mjs`). See [`tools/manifest/schema.md`](tools/manifest/schema.md).
530
+ - [`tools/`](tools/) — the family-wide tooling the kit **owns and ships**: `manifest/{schema.md,validate.mjs}` (the `capability.json` schema + the validator the kit runs as the memory detector, and root CI invokes), `commands.mjs` (the canonical **command catalog** + the pure `routeInvocation` router behind `/agent-workflow-kit help` and the safe unknown-invocation routing rule — one source of truth for the command surface, drift-guarded against the `### Mode:` headers), `delegation.mjs` (the executable delegate/fallback decision + hand-off plan), `inject-methodology.mjs` + `engine-source.mjs` (the bounded **two-slot** reconciliation — ensure-slot / inject-if-empty / cap for the `workflow:methodology` **and** `workflow:orchestration` pointers; both fragments read **live** from the installed `agent-workflow-engine` via `engine-source.mjs` (`deps.rel` selects which) — the family's one source of truth, no bundled mirror; fail-loud when the engine is needed but absent, orchestration soft-skipped when it would bust the cap), `detect-backends.mjs` (the read-only **backend detector** behind `/agent-workflow-kit backends`, plus the axis-aware `guideFor`; exports the readiness consts the planner reuses), `recipes.mjs` (the read-only **recipe planner** behind `/agent-workflow-kit recipes` — `RECIPES` / `planRecipe` / `recommendRecipe` over the bridges' role vocabulary, drift-guarded against `provides`/`cost`/`quota` + an engine↔kit recipe-name parity guard; pure, never runs a subscription CLI; also exports the pure `ACTIVITIES` / `resolveActivityRecipe` activity-procedures resolver), `procedures.mjs` (the read-only **activity-procedures advisor** behind `/agent-workflow-kit procedures` — reads `references/procedures.md` live from the engine via `engine-source.mjs`, reads + validates the agent-writable `docs/ai/orchestration.json` via `orchestration-config.mjs`, and prints the steps + the resolved effective recipe per slot; drift-guarded activity/slot table vs the canon; read-only, never imports the writer, never runs a subscription CLI), `orchestration-config.mjs` (the config **schema/read/pure-transform core** — `loadConfig`/`validateConfig`/the shared slot-recipe validity + `parseOp`/`applySetOps`/`serializeConfig`/the canonical-refresh helpers; no fs writes), `orchestration-write.mjs` (the **only** config fs-writer — a deployment-gated, atomic, symlink/TOCTOU-safe `writeConfig`; imported by `set-recipe` alone, never by `procedures`), `set-recipe.mjs` (the **config writer** behind `/agent-workflow-kit set-recipe` — validate → merge → preview-by-default → write; never runs a backend, never commits), `setup-backends.mjs` (the **link-only** backend setup behind `/agent-workflow-kit setup` — place the bundled bridge + link wrappers), `fs-safe.mjs` (the shared symlink-traversal-safe copy/link/**remove/unlink** primitives that `setup-backends`, the npx installer, and the uninstaller use), `known-footprint.mjs` + `hide-footprint.mjs` (the **hidden-mode** registry + the single hide-writer behind step 9 / the upgrade reconcile — one managed block in the **project-local** `.git/info/exclude` covering the full AI/agent footprint; pinned by `known-footprint.test.mjs` drift-guard + `hide-footprint.test.mjs` / `.integration.test.mjs`), `family-registry.mjs` (the **unified family registry** behind `/agent-workflow-kit status` — aggregates every member's `capability.json`; pinned by a `family-registry.test.mjs` drift-guard), `uninstall.mjs` (the **guarded teardown** behind `/agent-workflow-kit uninstall` — classify each surface, preflight-then-mutate, never delete user-authored content), and `release-scan.mjs` (the attribution-off release gate). The bundled bridge skill mirrors live under [`bridges/`](bridges/) (byte-identical to the repo-root bridges, pinned by `test/bridges-mirror.test.mjs`). See [`tools/manifest/schema.md`](tools/manifest/schema.md).
495
531
  - [`capability.json`](capability.json) — the kit's own `agent-workflow` family manifest (`kind: composition-root`).
496
532
  - [`CHANGELOG.md`](CHANGELOG.md) — version history of this kernel.
package/bin/install.mjs CHANGED
@@ -18,9 +18,13 @@
18
18
  // compares the version already on disk (the installed SKILL.md) against this runner's own version,
19
19
  // never the registry — which is why `@latest` (above) is the documented form: a bare `npx … init`
20
20
  // can reuse an OLDER cached build of this installer, so a returning user must bypass the cache to
21
- // actually upgrade (see decisions.md AD-012). One step DOES contact a server: `init` fetches and
22
- // installs the methodology engine the kit reads live (`npx @sabaiway/agent-workflow-engine@latest
23
- // init`), skippable with `--no-engine` (Plan 3D / AD-016). No tracking either way.
21
+ // actually upgrade (see decisions.md AD-012). Two steps DO contact a server: after the kit copy,
22
+ // `init` cascades the other npm-installable CORE members so a returning run leaves NO stale core
23
+ // member the memory substrate (`npx @sabaiway/agent-workflow-memory@latest init`, best-effort: a
24
+ // failure is a loud DEGRADED success, never silent — skippable with `--no-memory`) and the
25
+ // methodology engine the kit reads live (`npx @sabaiway/agent-workflow-engine@latest init`, fatal —
26
+ // the live read STOPs without it — skippable with `--no-engine`). The bridges are NOT installed by
27
+ // `init` (placed by `/agent-workflow-kit setup`). No tracking either way.
24
28
  //
25
29
  // Dependency-free, Node >= 18.
26
30
 
@@ -31,6 +35,11 @@ import { fileURLToPath } from 'node:url';
31
35
  import { homedir } from 'node:os';
32
36
  import { spawnSync } from 'node:child_process';
33
37
  import { copyTreeRefresh } from '../tools/fs-safe.mjs';
38
+ // The ONE registry of family members (npm packages, kinds). The init-refresh cascade derives its
39
+ // membership from this table — no second source of "who gets refreshed" — so it can't drift from the
40
+ // manifests (a drift-guard test pins the derivation). Imported from the DATA LEAF (family-members.mjs),
41
+ // NOT family-registry.mjs, so the npx cold-start path stays lean (no status/presenter graph pulled in).
42
+ import { FAMILY_MEMBERS } from '../tools/family-members.mjs';
34
43
 
35
44
  const __dirname = dirname(fileURLToPath(import.meta.url));
36
45
  const PKG_ROOT = resolve(__dirname, '..');
@@ -146,6 +155,7 @@ const parseArgs = (argv) => {
146
155
  help: argv.includes('--help') || argv.includes('-h'),
147
156
  version: argv.includes('--version') || argv.includes('-v'),
148
157
  noLaunchers: argv.includes('--no-launchers'),
158
+ noMemory: argv.includes('--no-memory'),
149
159
  noEngine: argv.includes('--no-engine'),
150
160
  force: argv.includes('--force'),
151
161
  allowDowngrade: argv.includes('--allow-downgrade'),
@@ -153,47 +163,72 @@ const parseArgs = (argv) => {
153
163
  };
154
164
  };
155
165
 
156
- // Mandatory engine install (Plan 3D / AD-016). The kit reads the methodology fragment LIVE from the
157
- // installed agent-workflow-engine, so init places it as a CORE part of the kit (not an optional
158
- // execution-backendthis deliberately diverges from AD-011 §5). It is fetched over npm, consistent
159
- // with the kit's own npx install context; NO engine canon is bundled into the kit (that would
160
- // re-create the mirror Plan 3D deletes). --no-engine skips it for air-gapped/scripted installs.
161
- export const ENGINE_PACKAGE = '@sabaiway/agent-workflow-engine';
162
-
163
- // The exact command + argv to install the engine. Windows resolution: spawn `npx.cmd` on win32,
164
- // `npx` elsewhere, WITHOUT shell:true (no shell-parse overhead/inconsistency; the repo has no
165
- // npx-spawn precedent to inherit a shell from). Pure unit-tested in-process, no network.
166
- export const engineInstallArgv = (platform) => ({
166
+ // Init-refresh cascade (Plan 3D / AD-016 for the engine; the memory cascade closes the
167
+ // returning-user "no stale core member" journey). After the kit copy, init refreshes the OTHER
168
+ // npm-installable CORE members the memory substrate + the methodology engine each over npm,
169
+ // consistent with the kit's own npx install context (NO engine/memory canon is bundled into the kit;
170
+ // that would re-create the mirror Plan 3D deletes). The npm package names are read from the ONE
171
+ // registry (FAMILY_MEMBERS) so there is no second source of truth. --no-memory / --no-engine skip
172
+ // each for air-gapped/scripted installs.
173
+ const npmFor = (name) => {
174
+ const member = FAMILY_MEMBERS.find((m) => m.name === name);
175
+ if (!member?.npm) throw new Error(`[agent-workflow-kit] no npm package registered for ${name}`);
176
+ return member.npm;
177
+ };
178
+ export const ENGINE_PACKAGE = npmFor('agent-workflow-engine');
179
+ export const MEMORY_PACKAGE = npmFor('agent-workflow-memory');
180
+
181
+ // The npm-installable core members the cascade refreshes, DERIVED from FAMILY_MEMBERS (every npm
182
+ // member that is neither the kit — the composition root this very runner installs — nor an
183
+ // execution-backend, which `setup` places, not init). Order + policy are part of the contract:
184
+ // NON-FATAL first (memory — a miss is a degraded success), then FATAL (engine — the live methodology
185
+ // read STOPs without it), so a hard engine failure never pre-empts the best-effort memory refresh.
186
+ // A drift-guard test pins this derivation, so adding a future npm core member can't silently bypass
187
+ // the cascade. Per-member messaging stays explicit in main() (the degraded-vs-STOP wording differs).
188
+ const FATAL_KINDS = new Set(['methodology-engine']);
189
+ export const cascadePlan = () =>
190
+ FAMILY_MEMBERS
191
+ .filter((m) => m.npm && m.kind !== 'execution-backend' && m.name !== 'agent-workflow-kit')
192
+ .map((m) => ({ name: m.name, npm: m.npm, fatal: FATAL_KINDS.has(m.kind) }))
193
+ .sort((a, b) => Number(a.fatal) - Number(b.fatal)); // non-fatal (memory) before fatal (engine)
194
+
195
+ // The exact command + argv to install a member over npx. Windows resolution: spawn `npx.cmd` on
196
+ // win32, `npx` elsewhere, WITHOUT shell:true (no shell-parse overhead/inconsistency; the repo has no
197
+ // npx-spawn precedent to inherit a shell from). `@latest` exactly — never a pinned version, so the
198
+ // cascade always fetches the newest published member. Pure → unit-tested in-process, no network.
199
+ export const memberInstallArgv = (npmPackage, platform) => ({
167
200
  command: platform === 'win32' ? 'npx.cmd' : 'npx',
168
- args: [`${ENGINE_PACKAGE}@latest`, 'init'],
201
+ args: [`${npmPackage}@latest`, 'init'],
169
202
  options: { stdio: 'inherit' }, // note: no `shell: true`
170
203
  });
204
+ export const engineInstallArgv = (platform) => memberInstallArgv(ENGINE_PACKAGE, platform);
205
+ export const memoryInstallArgv = (platform) => memberInstallArgv(MEMORY_PACKAGE, platform);
171
206
 
172
207
  // The default runner — the only place that actually spawns. Injected in tests so the suite never
173
208
  // hits the network.
174
- const spawnEngine = ({ command, args, options }) => spawnSync(command, args, options);
209
+ const spawnMember = ({ command, args, options }) => spawnSync(command, args, options);
175
210
 
176
211
  // Synchronous backoff before the single retry. The common first-attempt failure is a TRANSIENT
177
212
  // npm/network blip (rate-limit, registry hiccup, momentary DNS) — an immediate retry tends to hit the
178
213
  // same blip, so wait briefly first. Atomics.wait is a dependency-free sync sleep (the install flow is
179
214
  // already synchronous here). Injected in tests as a 0ms no-op so the suite never actually sleeps.
180
- const ENGINE_RETRY_DELAY_MS = 1500;
215
+ const RETRY_DELAY_MS = 1500;
181
216
  const sleepSync = (ms) => {
182
217
  if (ms > 0) Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
183
218
  };
184
219
 
185
220
  // D1 failure policy: attempt → wait → retry-once → fail. Retry exactly once before giving up. Pure
186
221
  // aside from the injected runner/sleep; returns { ok } so the caller prints the loud manual-recovery
187
- // message + nonzero exit on a hard failure (the kit is already on disk — recovery is one step; never
188
- // a silent skip).
189
- export const installEngine = (platform, runner, { sleep = sleepSync, retryDelayMs = ENGINE_RETRY_DELAY_MS } = {}) => {
190
- const descriptor = engineInstallArgv(platform);
191
- const ranOk = (label) => {
222
+ // message (the engine's nonzero exit, the memory's degraded warning) on a hard failure (the kit is
223
+ // already on disk — recovery is one step; never a silent skip). `label` names the member in the
224
+ // per-attempt warning (e.g. "methodology engine", "memory substrate").
225
+ const installMember = (label, descriptor, runner, { sleep = sleepSync, retryDelayMs = RETRY_DELAY_MS } = {}) => {
226
+ const ranOk = (attempt) => {
192
227
  const res = runner(descriptor);
193
228
  const ok = (res?.status ?? 1) === 0 && !res?.error;
194
229
  if (!ok) {
195
230
  const why = res?.error ? `: ${res.error.message}` : ` (exit ${res?.status ?? 'unknown'})`;
196
- console.warn(`[agent-workflow-kit] methodology engine install ${label} failed${why}.`);
231
+ console.warn(`[agent-workflow-kit] ${label} install ${attempt} failed${why}.`);
197
232
  }
198
233
  return ok;
199
234
  };
@@ -203,17 +238,47 @@ export const installEngine = (platform, runner, { sleep = sleepSync, retryDelayM
203
238
  return { ok: false };
204
239
  };
205
240
 
241
+ export const installEngine = (platform, runner, opts = {}) =>
242
+ installMember('methodology engine', engineInstallArgv(platform), runner, opts);
243
+ export const installMemory = (platform, runner, opts = {}) =>
244
+ installMember('memory substrate', memoryInstallArgv(platform), runner, opts);
245
+
206
246
  const resolveTarget = (dirArg) => {
207
247
  if (dirArg) return resolve(dirArg);
208
248
  if (process.env.AGENT_WORKFLOW_KIT_DIR) return resolve(process.env.AGENT_WORKFLOW_KIT_DIR);
209
249
  return resolve(homedir(), '.claude/skills/agent-workflow-kit');
210
250
  };
211
251
 
252
+ // Where the memory substrate lives — its env override else its home-relative default, both read from
253
+ // the ONE registry (FAMILY_MEMBERS), expanding a leading `~/`. Used only by the DEGRADED warning to
254
+ // report the on-disk memory version after a refresh miss (init never WRITES here — that is memory's
255
+ // own installer's job). getenv/home injectable for hermetic tests.
256
+ const resolveMemoryTarget = (getenv = process.env, home = homedir()) => {
257
+ const member = FAMILY_MEMBERS.find((m) => m.name === 'agent-workflow-memory');
258
+ const envDir = getenv[member.installed.env];
259
+ if (envDir) return resolve(envDir);
260
+ const dflt = member.installed.default;
261
+ return dflt.startsWith('~/') ? resolve(home, dflt.slice(2)) : resolve(dflt);
262
+ };
263
+
264
+ // Crash-proof on-disk version read for the degraded memory warning: readInstalledVersion returns null
265
+ // for an ABSENT SKILL.md and THROWS for a present-but-UNREADABLE one — but the warning must NEVER
266
+ // become fatal, so any throw is swallowed to null here. Both branches (absent → null directly,
267
+ // unreadable → caught → null) keep the warning best-effort and exit 0 (degraded success, no silent
268
+ // skip). Returns the semver string or null.
269
+ export const readMemberVersionSafe = async (dir) => {
270
+ try {
271
+ return await readInstalledVersion(dir);
272
+ } catch {
273
+ return null;
274
+ }
275
+ };
276
+
212
277
  const printHelp = (version) => {
213
278
  console.log(`agent-workflow-kit ${version}
214
279
 
215
280
  Usage:
216
- npx @sabaiway/agent-workflow-kit@latest init [--dir <path>] [--no-launchers] [--no-engine] [--force] [--allow-downgrade]
281
+ npx @sabaiway/agent-workflow-kit@latest init [--dir <path>] [--no-launchers] [--no-memory] [--no-engine] [--force] [--allow-downgrade]
217
282
  npx @sabaiway/agent-workflow-kit@latest --version
218
283
  npx @sabaiway/agent-workflow-kit@latest --help
219
284
 
@@ -222,11 +287,15 @@ Use the @latest form: a bare \`npx … init\` (no @latest) can reuse an OLDER ca
222
287
 
223
288
  Installs/refreshes the kit at ~/.claude/skills/agent-workflow-kit
224
289
  (override with --dir <path> or AGENT_WORKFLOW_KIT_DIR), then wires any
225
- Codex / Devin Desktop you have, then installs the methodology engine the kit reads
226
- live (npx ${ENGINE_PACKAGE}@latest init). --no-launchers skips the
227
- launcher wiring; --no-engine skips the engine install (the live methodology read then
228
- STOPs until you install it by hand); --force replaces a pre-existing non-kit launcher
229
- file (backed up first). init is additive it never deletes your settings. If the
290
+ Codex / Devin Desktop you have, then refreshes the other npm core members so no stale
291
+ one is left behind: the memory substrate (npx ${MEMORY_PACKAGE}@latest init)
292
+ and the methodology engine the kit reads live (npx ${ENGINE_PACKAGE}@latest init).
293
+ --no-launchers skips the launcher wiring; --no-memory skips the memory refresh (if it is
294
+ stale, refresh it yourself + restarta miss is otherwise a non-fatal degraded success,
295
+ never the engine's hard STOP); --no-engine skips the engine install (the live methodology
296
+ read then STOPs until you install it by hand); --force replaces a pre-existing non-kit
297
+ launcher file (backed up first). The bridges are NOT installed by init (placed by
298
+ /agent-workflow-kit setup). init is additive — it never deletes your settings. If the
230
299
  installed kit is newer than the version you ran, init refuses (no network — it compares
231
300
  the version on disk) and points you at @latest; --allow-downgrade overrides that
232
301
  refusal (distinct from --force, which is launcher-only).
@@ -335,9 +404,35 @@ const main = async () => {
335
404
  }
336
405
  }
337
406
 
338
- // Mandatory engine install — AFTER the kit + launchers but BEFORE the success block, so a failure
339
- // never first claims everything succeeded. The kit reads the methodology fragment live from the
340
- // installed engine; this places it (over npm, no canon bundled into the kit). --no-engine opts out.
407
+ // Memory substrate refresh — AFTER the kit + launchers, BEFORE the (fatal) engine and the success
408
+ // block, so a returning `init` leaves no stale memory. Unlike the engine, a memory miss is a
409
+ // DEGRADED success: warn with the exact recovery command + the on-disk version (read crash-proof)
410
+ // and keep exit 0 — never silently skip (Hard Constraint), never the engine's hard STOP.
411
+ const memoryCmd = `npx ${MEMORY_PACKAGE}@latest init`;
412
+ if (args.noMemory) {
413
+ console.log(
414
+ `[agent-workflow-kit] --no-memory: skipped refreshing the memory substrate. If it is stale, ` +
415
+ `refresh it yourself and restart the session:\n ${memoryCmd}`,
416
+ );
417
+ } else {
418
+ console.log(`[agent-workflow-kit] refreshing the memory substrate: ${memoryCmd}`);
419
+ const memory = installMemory(process.platform, spawnMember);
420
+ if (memory.ok) {
421
+ console.log('[agent-workflow-kit] memory substrate refreshed.');
422
+ } else {
423
+ const onDisk = await readMemberVersionSafe(resolveMemoryTarget());
424
+ const where = onDisk ? `on disk: v${onDisk}` : 'not found on disk';
425
+ console.warn(
426
+ `[agent-workflow-kit] could not refresh the memory substrate (${where}) — continuing; the ` +
427
+ `kit itself IS installed and works. To get the latest memory, run it yourself and restart ` +
428
+ `the session:\n ${memoryCmd}`,
429
+ );
430
+ }
431
+ }
432
+
433
+ // Mandatory engine install — AFTER the kit + launchers + memory but BEFORE the success block, so a
434
+ // failure never first claims everything succeeded. The kit reads the methodology fragment live from
435
+ // the installed engine; this places it (over npm, no canon bundled into the kit). --no-engine opts out.
341
436
  const engineCmd = `npx ${ENGINE_PACKAGE}@latest init`;
342
437
  if (args.noEngine) {
343
438
  console.log(
@@ -347,7 +442,7 @@ const main = async () => {
347
442
  );
348
443
  } else {
349
444
  console.log(`[agent-workflow-kit] installing the methodology engine the kit reads live: ${engineCmd}`);
350
- const engine = installEngine(process.platform, spawnEngine);
445
+ const engine = installEngine(process.platform, spawnMember);
351
446
  if (!engine.ok) {
352
447
  // D1: two attempts failed → loud error + concrete recommendations + nonzero exit. The kit IS on
353
448
  // disk, so recovery is one step. Never a silent skip (Hard Constraint: no silent failures).
package/capability.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "agent-workflow-kit",
5
5
  "kind": "composition-root",
6
- "version": "1.17.0",
6
+ "version": "1.19.0",
7
7
  "provides": [],
8
8
  "roles": {},
9
9
  "detect": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sabaiway/agent-workflow-kit",
3
- "version": "1.17.0",
3
+ "version": "1.19.0",
4
4
  "description": "Portable, cross-agent memory & workflow for AI coding agents — Claude Code, Codex, Cursor, Devin Desktop. One command deploys an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement into any repo.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -1,5 +1,10 @@
1
1
  {
2
- "_README": "Per-project orchestration config: the recipe used at each step (slot) of each named activity. Hand-edit this file — it is never written for you. Each activity is configured independently (e.g. plan-authoring, plan-execution), and so is each slot within it. A slot's value is a recipe: a 'review' slot accepts solo | reviewed | council (you self-review / one backend reviews / both review and you synthesize); an 'execute' slot accepts solo | delegated (you implement / a backend runs a bounded sub-task). The default below is 'solo' everywhere — no execution backend required. Raise a slot to reviewed or council for a second opinion, or to delegated to hand off execution; those need an execution backend set up first. Remove a slot's line to fall back to the computed default (reviewed when a review backend is ready, otherwise solo). Run the read-only procedures advisor to see an activity's steps plus the recipe resolved for your environment, and pass a per-run override to change one slot just once. Strict JSON — no comments.",
3
- "plan-authoring": { "review": "solo" },
4
- "plan-execution": { "execute": "solo", "review": "solo" }
2
+ "_README": "Per-project orchestration config: the recipe used at each step (slot) of each named activity. Easiest: tell the agent in plain language and run the `set-recipe` writer — it interprets your intent, previews the change, and writes valid JSON for you. You can still hand-edit this file directly whenever you prefer; that option never goes away. Each activity is configured independently (e.g. plan-authoring, plan-execution), and so is each slot within it. A slot's value is a recipe: a 'review' slot accepts solo | reviewed | council (you self-review / one backend reviews / both review and you synthesize); an 'execute' slot accepts solo | delegated (you implement / a backend runs a bounded sub-task). The default below is 'solo' everywhere — no execution backend required. Raise a slot to reviewed or council for a second opinion, or to delegated to hand off execution; those need an execution backend set up first. Remove a slot's line (or run `set-recipe --unset <activity>.<slot>`) to fall back to the computed default (reviewed when a review backend is ready, otherwise solo). Run the read-only procedures advisor to see an activity's steps plus the recipe resolved for your environment. Strict JSON — no comments.",
3
+ "plan-authoring": {
4
+ "review": "solo"
5
+ },
6
+ "plan-execution": {
7
+ "execute": "solo",
8
+ "review": "solo"
9
+ }
5
10
  }
@@ -115,6 +115,13 @@ const CATALOG = [
115
115
  kind: READ_ONLY,
116
116
  oneLine: 'Show a named activity’s steps and which recipe applies at each stage here.',
117
117
  },
118
+ {
119
+ key: 'set-recipe',
120
+ invocation: invocationOf('set-recipe'),
121
+ group: 'Orchestrate',
122
+ kind: WRITER,
123
+ oneLine: 'Set the orchestration recipe for an activity from plain language — previews the change, then writes the config when you confirm.',
124
+ },
118
125
  ];
119
126
 
120
127
  // Deep-freeze: freeze the array AND every entry, so the catalog is genuinely immutable at runtime