@sabaiway/agent-workflow-kit 1.11.0 → 1.13.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 +56 -1
- package/README.md +12 -4
- package/SKILL.md +103 -37
- package/capability.json +5 -1
- package/package.json +1 -1
- package/references/templates/AGENTS.md +2 -3
- package/tools/detect-backends.mjs +7 -6
- package/tools/engine-source.mjs +10 -5
- package/tools/engine-source.test.mjs +50 -0
- package/tools/family-registry.mjs +276 -0
- package/tools/family-registry.test.mjs +247 -0
- package/tools/fs-safe.mjs +50 -1
- package/tools/fs-safe.test.mjs +140 -0
- package/tools/inject-methodology.mjs +237 -110
- package/tools/inject-methodology.test.mjs +128 -12
- package/tools/manifest/validate.mjs +3 -1
- package/tools/recipes.mjs +276 -0
- package/tools/recipes.test.mjs +363 -0
- package/tools/uninstall.integration.test.mjs +144 -0
- package/tools/uninstall.mjs +420 -0
- package/tools/uninstall.test.mjs +372 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,62 @@ 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.
|
|
7
|
+
## 1.13.0 — Orchestration recipes: a named way to compose the bridges
|
|
8
|
+
|
|
9
|
+
The kit now knows **how to put the optional execution-backends to work**, not just whether they're set
|
|
10
|
+
up. A new read-only **`/agent-workflow-kit recipes`** advisor presents four named recipes — **Solo**
|
|
11
|
+
(no backend), **Reviewed** (one backend reviews), **Council** (both review, you synthesize), and
|
|
12
|
+
**Delegated** (a backend executes a bounded sub-task) — plans the right one for your environment, and
|
|
13
|
+
**degrades gracefully with a stated reason** when a backend isn't ready (Council → Reviewed → Solo;
|
|
14
|
+
Delegated → Solo). It offers the choice (a multiple-choice prompt where your agent supports it) and
|
|
15
|
+
prints exactly what running it entails, including advisory quota/health notes. It is **read-only**:
|
|
16
|
+
the orchestrator runs the chosen recipe through the bridge skills and always makes the single commit —
|
|
17
|
+
the kit never executes a recipe and never runs a subscription CLI.
|
|
18
|
+
|
|
19
|
+
Every deployed `AGENTS.md` now also carries a one-line **orchestration-recipes pointer** (right under
|
|
20
|
+
the methodology pointer), reconciled live from the engine on bootstrap + upgrade. And the read-only
|
|
21
|
+
backend-status line that bootstrap/upgrade already print gains an **actionable tail** — e.g.
|
|
22
|
+
*"recipes: Reviewed available (via codex) — see /agent-workflow-kit recipes"* — so you're nudged
|
|
23
|
+
toward the recipe that fits, never left guessing.
|
|
24
|
+
|
|
25
|
+
Both entry-point templates were trimmed for headroom so both pointers fit inside the 100-line cap; if
|
|
26
|
+
an entry point is already at the limit, the orchestration pointer is **skipped and reported** (never
|
|
27
|
+
silently) while the methodology pointer still lands. The deployment-lineage head stays **`1.3.0`** (no
|
|
28
|
+
`docs/ai` structural change; no migration file). See **AD-018**.
|
|
29
|
+
|
|
30
|
+
## 1.12.0 — See the whole family, and uninstall it cleanly
|
|
31
|
+
|
|
32
|
+
Two new in-agent modes, built on a single **unified family registry**. `/agent-workflow-kit status`
|
|
33
|
+
shows — read-only — which family members (kit / memory / engine / the two bridges) are installed, at
|
|
34
|
+
what version, and (in a project) what is deployed (`docs/ai`, the version stamps, the hidden-mode
|
|
35
|
+
fence). `/agent-workflow-kit uninstall` is the **guarded teardown**: it reverses what `init` and
|
|
36
|
+
`setup` placed — installed skill dirs + bridge wrappers, and in a project the hidden-mode fence + the
|
|
37
|
+
marker pre-commit hook — but it **never deletes user-authored content** (`docs/ai`, `AGENTS.md`, your
|
|
38
|
+
`.claude/settings.json`); for those it prints the exact commands and lets you run them. It removes only
|
|
39
|
+
what is **provably ours** (a valid manifest, name + kind match; a wrapper symlink that points at our
|
|
40
|
+
source) — anything else is left untouched — and it **previews with `--dry-run` and preflights before
|
|
41
|
+
it touches anything**, so a conflict makes zero changes. The deployment-lineage head stays **`1.3.0`**
|
|
42
|
+
(no `docs/ai` structural change; no migration file). See **AD-017**.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- `tools/family-registry.mjs` — the unified, kit-owned registry over every family member (the
|
|
46
|
+
`KNOWN_BACKENDS` precedent, generalized to all five). Resolves each member's `detect.installed`,
|
|
47
|
+
manifest health, and installed version; powers `/agent-workflow-kit status`. A drift-guard test pins
|
|
48
|
+
it to the five in-repo `capability.json` files.
|
|
49
|
+
- `tools/uninstall.mjs` — the guarded uninstaller behind `/agent-workflow-kit uninstall`: a pure
|
|
50
|
+
classifier (`buildPlan`) + a preflight-then-mutate executor (`executePlan`). Four surface classes —
|
|
51
|
+
safe-remove (provably-ours skill dirs), managed-marker (wrapper symlinks / the hidden-mode fence /
|
|
52
|
+
the marker hook), report-only (never-deleted user content), and stop (present-but-not-ours).
|
|
53
|
+
- `tools/fs-safe.mjs` gains `removeTreeManaged` + `unlinkManaged` — the symlink-safe inverses of
|
|
54
|
+
`copyTreeRefresh` / `linkManaged` (refuse to delete through a symlink or outside the root; remove
|
|
55
|
+
only a symlink whose target is ours).
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- `tools/manifest/validate.mjs` exports `readAuthoritativeVersion` so the registry reports an installed
|
|
59
|
+
member's version from the same authoritative source the validator checks.
|
|
60
|
+
- The kit's own `capability.json` now declares `uninstall.removeResolved` (uniform with memory +
|
|
61
|
+
engine); the guarded uninstaller's behavior matches it — it removes exactly the resolved
|
|
62
|
+
`detect.installed` dir, so the long-declared teardown is now realized, not just documented.
|
|
8
63
|
|
|
9
64
|
The bounded methodology fragment the kit writes into a project's `AGENTS.md` is now read **live from
|
|
10
65
|
the installed `@sabaiway/agent-workflow-engine`** — the family's single source of truth. The kit's old
|
package/README.md
CHANGED
|
@@ -220,6 +220,9 @@ command is printed).
|
|
|
220
220
|
| `/agent-workflow-kit upgrade` | existing deployment | reads `docs/ai/.workflow-version`, shows the changelog diff, preserves your authored memory, applies migrations, re-stamps — then prints a **read-only** one-line backend-status line (what's set up vs missing); never installs a bridge — set one up with `/agent-workflow-kit setup` |
|
|
221
221
|
| `/agent-workflow-kit backends` | any time | **read-only** check of the optional execution-backends (the `codex` / `agy` bridges): what's set up vs missing and the next step. Never writes, never commits, never runs a subscription CLI (credentials = marker-file presence, not a live login). |
|
|
222
222
|
| `/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. |
|
|
223
|
+
| `/agent-workflow-kit status` | any time | **read-only** view of the whole family: which members (kit / memory / engine / the two bridges) are installed and at what version, and — with a project — what's deployed (`docs/ai`, the version stamps, and whether the AI files are git-ignored for hidden mode). Never writes, never commits, never runs a subscription CLI. |
|
|
224
|
+
| `/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. |
|
|
225
|
+
| `/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` / settings — for those it prints the exact `rm` commands to run by hand. Always `--dry-run` first; preflight-then-mutate; never commits. |
|
|
223
226
|
|
|
224
227
|
It **never auto-commits** and **never overwrites** an existing `AGENTS.md` without asking.
|
|
225
228
|
|
|
@@ -258,8 +261,10 @@ agent-workflow-kit — the composition root (installed via npx … init)
|
|
|
258
261
|
|
|
259
262
|
- **Delegates** substrate deployment to **`@sabaiway/agent-workflow-memory`** when a healthy
|
|
260
263
|
standalone copy is present, else uses its **bundled fallback** — same `docs/ai/` either way.
|
|
261
|
-
- **Injects**
|
|
262
|
-
|
|
264
|
+
- **Injects** two bounded pointers into the deployed `AGENTS.md` — the workflow **methodology** and the
|
|
265
|
+
**orchestration recipes** (Solo / Reviewed / Council / Delegated) — read **live** from the installed
|
|
266
|
+
**`agent-workflow-engine`** (the canonical narrative; a published member, never one of the shipped
|
|
267
|
+
backends). `/agent-workflow-kit recipes` surfaces + plans a recipe for your environment, read-only.
|
|
263
268
|
- **Detects & (opt-in) sets up** the optional `codex` / `agy` **bridges** — agent skills (not npm, not
|
|
264
269
|
installed by `init`). They plug into the workflow's **execute** and **review** phases — for *what
|
|
265
270
|
each adds and why*, see the
|
|
@@ -302,11 +307,14 @@ agent-workflow-kit/
|
|
|
302
307
|
├── tools/ ← family tooling:
|
|
303
308
|
│ ├── manifest/ ← capability-manifest schema + validator
|
|
304
309
|
│ ├── delegation.mjs ← detect substrate · delegate-or-fall-back
|
|
305
|
-
│ ├── inject-methodology.mjs ← write the methodology
|
|
310
|
+
│ ├── inject-methodology.mjs ← write the methodology + recipe slots
|
|
306
311
|
│ ├── engine-source.mjs ← live engine fragment read (fail-loud)
|
|
307
312
|
│ ├── detect-backends.mjs ← read-only backend detector
|
|
313
|
+
│ ├── recipes.mjs ← read-only recipe planner (recipes)
|
|
308
314
|
│ ├── setup-backends.mjs ← link-only backend setup
|
|
309
|
-
│ ├── fs-safe.mjs ← symlink-safe copy/link
|
|
315
|
+
│ ├── fs-safe.mjs ← symlink-safe copy/link/remove/unlink
|
|
316
|
+
│ ├── family-registry.mjs ← unified family registry (status)
|
|
317
|
+
│ ├── uninstall.mjs ← guarded teardown (uninstall)
|
|
310
318
|
│ └── release-scan.mjs ← attribution / release gate
|
|
311
319
|
├── bridges/ ← bundled bridge skill mirrors (codex / antigravity)
|
|
312
320
|
├── launchers/ ← Codex / Devin Desktop / Cursor entries
|
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.
|
|
6
|
+
version: '1.13.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-kit
|
|
@@ -52,34 +52,40 @@ made: a partial/broken memory install discovered mid-flow must not disable the w
|
|
|
52
52
|
**Hand-off contract (explicit; tested independent of agent interpretation).**
|
|
53
53
|
- **Delegated** (memory valid): the kit passes the **target project dir** + the **three setup
|
|
54
54
|
answers** (visibility / language / attribution) to `agent-workflow-memory`, which writes
|
|
55
|
-
`docs/ai/` + `AGENTS.md` (
|
|
56
|
-
|
|
57
|
-
**`.workflow-version`**. → **both stamps** present. In **hidden** mode the kit is the **single
|
|
55
|
+
`docs/ai/` + `AGENTS.md` (carrying the **two empty pointer pairs** — `workflow:methodology` and
|
|
56
|
+
`workflow:orchestration`) + **`.memory-version`**. The kit then **reconciles both bounded pointers**
|
|
57
|
+
(below) and writes the kit-fallback **`.workflow-version`**. → **both stamps** present. In **hidden** mode the kit is the **single
|
|
58
58
|
hide authority**: after the hand-off it runs `tools/hide-footprint.mjs` (step 9), which **absorbs
|
|
59
59
|
memory's project-local footprint lines** into the one canonical `.git/info/exclude` block and adds
|
|
60
60
|
the external footprint — so there is **no machine-global write** at any step (a stale memory's
|
|
61
61
|
residual global block is cleaned via the upgrade reconcile, below).
|
|
62
62
|
- **Fallback** (memory absent/invalid): the kit runs the bootstrap procedure below from its own
|
|
63
|
-
bundled assets — whose entry-point template now ships
|
|
64
|
-
reconciles + fills — and writes **`.workflow-version`** only.
|
|
65
|
-
`agent-workflow-memory` — never a prerequisite.
|
|
66
|
-
|
|
67
|
-
**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
**
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
63
|
+
bundled assets — whose entry-point template now ships **two empty pointer pairs** (`workflow:methodology`
|
|
64
|
+
+ `workflow:orchestration`) the kit reconciles + fills — and writes **`.workflow-version`** only.
|
|
65
|
+
Softly suggest installing `agent-workflow-memory` — never a prerequisite.
|
|
66
|
+
|
|
67
|
+
**Bounded pointer reconciliation (the kit is the ONLY writer of these slots).** After `AGENTS.md`
|
|
68
|
+
exists, run ONE command — `node ${CLAUDE_SKILL_DIR}/tools/inject-methodology.mjs reconcile
|
|
69
|
+
<project>/AGENTS.md` — which reconciles **two** bounded pointers in a single atomic write: the
|
|
70
|
+
**workflow-methodology** pointer (the plan → execute → review summary) **and**, right below it, the
|
|
71
|
+
**orchestration-recipes** pointer (the Solo / Reviewed / Council / Delegated vocabulary, routing to
|
|
72
|
+
`/agent-workflow-kit recipes`). Each is **one atomic operation per slot**: **ensure the slot exists**
|
|
73
|
+
(insert an empty marker pair at its anchor when a legacy entry point lacks one) → **inject the bounded
|
|
74
|
+
fragment ONLY IF the slot is empty** (a filled / user-customized slot is preserved verbatim) →
|
|
75
|
+
**cap-check** (the second pointer's check runs on the file *after* the first, so it guards the
|
|
76
|
+
**combined** ≤100-line budget). Both fragments are short summary + pointer, read **live from the
|
|
77
|
+
installed `agent-workflow-engine`** (`references/methodology-slot.md` + `references/orchestration-slot.md`,
|
|
78
|
+
the family's one source of truth) — **not** a bundled mirror, and **not** the full references. The
|
|
79
|
+
live read is **lazy + fail-loud**: the engine is consulted **only when a slot actually needs filling**,
|
|
80
|
+
so a deployment whose pointers are already filled reconciles to a zero-diff no-op even on a host
|
|
81
|
+
without the engine; but when a fill **is** needed and the engine is **absent/invalid**, reconcile
|
|
82
|
+
**STOPs** — report it in plain language with the one-line install command
|
|
83
|
+
`npx @sabaiway/agent-workflow-engine@latest init` (`npx @sabaiway/agent-workflow-kit@latest init`
|
|
84
|
+
installs the engine for you; translate, never leak tool internals). Contract per slot: exactly one
|
|
85
|
+
ordered `start → end` pair; a malformed slot (single, reversed, nested, duplicate) or a missing /
|
|
86
|
+
duplicate anchor → **STOP with an error**, never edit (the file is left byte-for-byte unchanged). The
|
|
87
|
+
**orchestration pointer is soft-skipped** (reported, never silent) when — and only when — adding it
|
|
88
|
+
would exceed the 100-line cap: the methodology pointer still lands and the upgrade continues.
|
|
83
89
|
|
|
84
90
|
**One composition-level commit gate.** The delegated memory mode performs **no** commit and
|
|
85
91
|
raises **no** "ask to commit". There is exactly **one** gate, owned by the kit, **after**
|
|
@@ -96,6 +102,9 @@ Pick the mode from the user's invocation. Auto-detect an existing `docs/ai/` to
|
|
|
96
102
|
- **`/agent-workflow-kit upgrade`** — upgrade an existing deployment to the skill's current `version`.
|
|
97
103
|
- **`/agent-workflow-kit backends`** — read-only environment check: which optional **execution-backends** (the `codex` / `agy` bridges) are set up vs missing. Never writes, never commits, never runs a subscription CLI.
|
|
98
104
|
- **`/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.
|
|
105
|
+
- **`/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.
|
|
106
|
+
- **`/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.
|
|
107
|
+
- **`/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** (`docs/ai`, `AGENTS.md`, `.claude/settings.json`): it prints the exact commands for you to run by hand. `--dry-run` first, always; preflight-then-mutate; never commits.
|
|
99
108
|
|
|
100
109
|
### Version status & the two axes — surface this on every invocation
|
|
101
110
|
|
|
@@ -118,12 +127,20 @@ Before acting, read `docs/ai/.workflow-version` (the project's stamp), state a o
|
|
|
118
127
|
Bootstrap (step 11) and **every** successful `upgrade` exit (steps 4 + 8) print the **same**
|
|
119
128
|
read-only, one-line summary of the optional execution-backends. Run the **backend detector** —
|
|
120
129
|
`node ${CLAUDE_SKILL_DIR}/tools/detect-backends.mjs` — and compose one line from its per-backend
|
|
121
|
-
readiness
|
|
122
|
-
`
|
|
123
|
-
|
|
130
|
+
readiness, then **append an actionable recipe recommendation** from the recipe planner
|
|
131
|
+
(`node ${CLAUDE_SKILL_DIR}/tools/recipes.mjs --json` → `recommendation.clause`, P2-rich). Canonical format:
|
|
132
|
+
`backends: codex ✓ ready · antigravity ✗ needs-credentials — run /agent-workflow-kit backends · recipes: Reviewed available (via codex) — see /agent-workflow-kit recipes`
|
|
133
|
+
|
|
134
|
+
- The **`recipes:` clause is appended after** the `— run /agent-workflow-kit backends` pointer (never
|
|
135
|
+
replacing it) and routes to the read-only `recipes` mode (`see /agent-workflow-kit recipes`). It is
|
|
136
|
+
**never blank**: both backends ready → *"Council available, Reviewed the everyday default"*; one
|
|
137
|
+
ready → *"Reviewed available (via …)"*; **none installed → *"Solo — run /agent-workflow-kit setup to
|
|
138
|
+
add a backend"***; a backend present-but-not-ready → Solo with that backend's specific remedy.
|
|
139
|
+
(Matches `recommendRecipe`.)
|
|
124
140
|
- **Invariants:** **read-only · never blocks the commit gate · never runs a subscription CLI · the
|
|
125
|
-
pointer is the in-agent `backends` mode, never a network fetch ·
|
|
126
|
-
|
|
141
|
+
pointer is the in-agent `backends` mode, never a network fetch · the appended `recipes:` clause
|
|
142
|
+
routes to the in-agent `recipes` mode the same way · `init`/npx is unaffected (it never places
|
|
143
|
+
bridges, AD-011 §5).**
|
|
127
144
|
- **Detector unavailable → skip with a stated reason, never silently.** The detector is a Node script
|
|
128
145
|
the **agent host** runs (not the target project), so the only skip condition is "**the agent host
|
|
129
146
|
can't run it**" — `node` is not on the agent's PATH, or the detector itself errors — **not** "the
|
|
@@ -183,21 +200,21 @@ Fill strategy:
|
|
|
183
200
|
|
|
184
201
|
1. Read `docs/ai/.workflow-version` (the project's stamped lineage). If missing, treat as a pre-versioned deployment and offer to re-bootstrap conservatively.
|
|
185
202
|
2. **Never-downgrade gate — FIRST, before any write.** Compare the stamp to the **deployment-lineage head** (`1.3.0` — NOT this kit's package version). If the stamp is **greater than the head** or unparseable → **STOP and report**; do not touch a newer / unknown deployment at all (not even the methodology slot).
|
|
186
|
-
3. **Reconcile the
|
|
203
|
+
3. **Reconcile the bounded pointers — stamp-independent, BEFORE the equal-head short-circuit.** Reached only when the stamp **≤ head**. Run `node ${CLAUDE_SKILL_DIR}/tools/inject-methodology.mjs reconcile <project>/AGENTS.md`. ONE call reconciles **two** pointers — the **workflow-methodology** pointer and, right below it, the **orchestration-recipes** pointer (Solo / Reviewed / Council / Delegated, routing to `/agent-workflow-kit recipes`) — and is filled on **every** upgrade, idempotently (zero-diff when both are already present + filled), so even a legacy / current **`1.3.0`** deployment gains them **without a lineage-head bump or a migration** (the deployment-lineage head stays `1.3.0`; the `agent-workflow-memory` **package** template did get a docs-only headroom trim for the second pointer, but no deployed-`docs/ai` structure changed). Per slot it inserts an empty pair at its anchor if absent, preserves a customized pair verbatim, and STOPs (never edits) on a malformed pair, a missing / duplicate anchor, or **when a fill is needed but the installed `agent-workflow-engine` is absent/invalid** (both fragments are read live from it — see the distinct outcomes below).
|
|
187
204
|
|
|
188
|
-
|
|
205
|
+
**Classify the exit — there are THREE non-zero exits + one soft in-band skip; handle each differently:**
|
|
189
206
|
|
|
190
|
-
(a) **
|
|
207
|
+
(a) **Soft, reported skip of the orchestration pointer (CONTINUE the upgrade).** The orchestration pointer is the less-critical second pointer; when it can't be added right now `reconcile` exits **zero**, keeps the methodology pointer, and **reports the skip on stdout** (the `… skipped …` line) — never silent (Hard Constraint). Two reasons: **(i)** the methodology pointer fits but adding the orchestration pointer would push the file past the `AGENTS.md` 100-line cap; or **(ii)** the installed `agent-workflow-engine` is **present but too old** to ship the recipes fragment (`<1.2.0`) — it can still supply the methodology pointer, so only the recipes pointer is withheld. Report it in the successful-exit report (**step 4** equal-head, else **step 8**) in plain language, e.g. *"The orchestration-recipes pointer wasn't added — the entry point is at its 100-line limit / your methodology engine is older than the recipes feature. The recipes are still available any time via `/agent-workflow-kit recipes`; to add the pointer, trim the entry point and/or refresh the engine with `npx @sabaiway/agent-workflow-engine@latest init`, then re-run upgrade."* (The separate case where the **methodology** pointer ITSELF can't fit the cap is a non-zero exit that changes nothing — continue without either pointer, same plain-language framing.)
|
|
191
208
|
|
|
192
|
-
(b) **Malformed
|
|
209
|
+
(b) **Malformed pair / missing-or-duplicate anchor (either pointer) — a hard STOP (do NOT continue).** A non-zero exit whose message names a marker/anchor problem; never soft-skip it.
|
|
193
210
|
|
|
194
|
-
(c) **`methodology engine not found/invalid …` — a hard STOP (do NOT continue).** A fill was needed but the installed `agent-workflow-engine`
|
|
211
|
+
(c) **`methodology engine not found/invalid …` — a hard STOP (do NOT continue).** A fill was needed but the installed `agent-workflow-engine` is **fully absent/invalid** — it can supply **neither** fragment (distinct from (a)(ii), where the engine is valid but merely too old for the recipes one). Report it in plain language with the one-line install command `npx @sabaiway/agent-workflow-engine@latest init` (or note that `npx @sabaiway/agent-workflow-kit@latest init` installs the engine for you), then re-run upgrade once it is present. **Never** treat (c) as a soft-skip (a) — mis-handling it would silently drop the methodology pointer (a no-silent-failures violation). (b) and (c) STOP the upgrade; only (a) continues.
|
|
195
212
|
|
|
196
|
-
**No-Node project:** the
|
|
213
|
+
**No-Node project:** the fragments live only in the **installed `agent-workflow-engine`** (`references/methodology-slot.md` + `references/orchestration-slot.md`, under `~/.claude/skills/agent-workflow-engine` or `$AGENT_WORKFLOW_ENGINE_DIR`) — there is no bundled copy, and a No-Node host cannot run the `npx` engine install. Open `AGENTS.md` and classify **each** pointer by hand: a **filled / customized** pair → leave it verbatim (no engine needed); a **malformed** pair (not exactly one ordered `start → end`) → STOP, do not edit. A pair that needs filling — **absent markers OR a present-but-empty pair** — needs the engine's fragment, so: if the engine is **not installed**, that pointer **cannot be added** — report it plainly (the methodology is already in `docs/ai/agent_rules.md`; the recipes are available via `/agent-workflow-kit recipes`; install the engine to add the pointers). If the engine **is** present, **count the lines first** — if adding/filling would take the file over 100 lines, **skip that pointer and report the skip** (methodology first, then orchestration; the orchestration pair sits right under the methodology end marker). Fill each empty pair from its engine fragment (`methodology-slot.md` / `orchestration-slot.md`) — never inline a copy (that would re-create the retired mirror).
|
|
197
214
|
|
|
198
215
|
**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.
|
|
199
216
|
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:
|
|
200
|
-
- **Report step 3's outcome in plain language** —
|
|
217
|
+
- **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); 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).
|
|
201
218
|
- **Print the one-line backend-status line** — the shared contract above (run `node ${CLAUDE_SKILL_DIR}/tools/detect-backends.mjs`; same format, invariants, and detector-unavailable skip-with-reason).
|
|
202
219
|
- **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 backend line.
|
|
203
220
|
5. Show the relevant `${CLAUDE_SKILL_DIR}/CHANGELOG.md` diff (entries newer than the project's stamp).
|
|
@@ -235,6 +252,53 @@ For each backend it:
|
|
|
235
252
|
|
|
236
253
|
**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).
|
|
237
254
|
|
|
255
|
+
### Mode: status
|
|
256
|
+
|
|
257
|
+
Read-only. Answers *"which family members are installed (and at what version), and what is deployed in this project?"* across the **whole family** — the unified registry behind it (`tools/family-registry.mjs`) aggregates every member's `capability.json`. It **never writes, never commits, and never runs a subscription CLI**.
|
|
258
|
+
|
|
259
|
+
Run `node ${CLAUDE_SKILL_DIR}/tools/family-registry.mjs [--dir <project>]` and present its two-axis table:
|
|
260
|
+
|
|
261
|
+
1. **Skill axis (always):** per member — `installed` + the manifest health (`ok` / `not-installed` / `foreign` / `stub` / `invalid-manifest` / `unsupported-schema`, the same precedence the backend detector uses) + the installed version (read from the member's own `SKILL.md`, the authoritative source).
|
|
262
|
+
2. **Deploy axis (`--dir <project>`):** the deployment stamps (`docs/ai/.workflow-version`, `.memory-version`), whether `docs/ai/` exists, and whether the hidden-mode managed fence is present.
|
|
263
|
+
|
|
264
|
+
State plainly that the two version axes stay decoupled (an installed *skill* version is not a project's deployment-lineage stamp — see *Version status & the two axes*). The installed version reflects whatever is on disk under `~/.claude/skills/…`; a stale install shows its real (older) version, honestly.
|
|
265
|
+
|
|
266
|
+
### Mode: recipes
|
|
267
|
+
|
|
268
|
+
Read-only **orchestration advisor**. Answers *"how should I compose the optional execution-backends into plan → execute → review here, and which recipe fits?"* It **never writes, never commits, never runs a subscription CLI, and never executes a recipe** — the orchestrator (you) runs the chosen recipe through the bridge skills and makes the single commit; a backend is advisory or delegated, never autonomous.
|
|
269
|
+
|
|
270
|
+
The four recipes (defined over each bridge's `provides` roles — `codex`: execute + review; `agy`: review + probe), canonical narrative in the **installed engine** (`references/orchestration.md`):
|
|
271
|
+
|
|
272
|
+
- **Solo** — you plan, execute, and self-review; no backend (always available; the floor).
|
|
273
|
+
- **Reviewed** — you execute; **one** backend reviews the result (advisory). Prefers `codex` when both are ready (`agy` carries a standing health caveat).
|
|
274
|
+
- **Council** — **both** backends review independently; you synthesize the two opinions.
|
|
275
|
+
- **Delegated** — you hand a **bounded** execution sub-task to a backend (`codex exec`), then review the returned diff and commit.
|
|
276
|
+
|
|
277
|
+
1. Run **`node ${CLAUDE_SKILL_DIR}/tools/recipes.mjs`** (the read-only planner; `--json` for the structured form). It runs the backend detector, lists the four recipes, and prints — for the current environment — a **per-recipe dispatch plan that degrades with a stated reason** when a backend isn't `ready` (Council → Reviewed → Solo; Delegated → Solo), plus advisory **quota/health notes** (prefer the cheapest model; Council spends two backends' quota; `agy` may stall on substantive prompts — Issue-001, prefer `codex`).
|
|
278
|
+
2. **Offer the choice** via **`AskUserQuestion` where your agent supports it** (`AskUserQuestion` in Claude Code) — one option per recipe, the `recommendRecipe` choice listed **first** — otherwise in prose. Then print `planRecipe(chosen, detection)` (the per-stage dispatch + degradation reasons + quota/health notes) so the user sees exactly what running it entails.
|
|
279
|
+
3. **Availability = `readiness === ready`, full stop.** Every other readiness supplies the human reason (needs-skill → "not installed — `/agent-workflow-kit setup`"; needs-cli → "install the CLI"; needs-credentials → "log in"; degraded → "wrapper not on PATH — `/agent-workflow-kit setup`"). This is set-up state only — **never** a claim that a backend's service is responsive (the detector cannot observe a runtime stall; `agy`'s Issue-001 is a *standing advisory*, not a readiness signal).
|
|
280
|
+
|
|
281
|
+
**Invariants:** read-only · never runs a subscription CLI · never commits · the orchestrator executes the recipe via the bridge skills, not the kit.
|
|
282
|
+
|
|
283
|
+
### Mode: uninstall
|
|
284
|
+
|
|
285
|
+
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**.
|
|
286
|
+
|
|
287
|
+
Run `node ${CLAUDE_SKILL_DIR}/tools/uninstall.mjs [<member>] [--dir <project>] [--bindir <path>] [--dry-run | --yes]`:
|
|
288
|
+
|
|
289
|
+
- `<member>` — limit the skill axis to one member (`agent-workflow-kit` / `-memory` / `-engine` / a bridge); omit for the **whole family**.
|
|
290
|
+
- `--dir <project>` — also reverse the **project-deployment** surfaces in `<project>`.
|
|
291
|
+
- `--bindir <path>` — where the bridge wrappers were linked (default `~/.local/bin`, mirrors `setup`).
|
|
292
|
+
- `--dry-run` — print the plan and change **nothing** (run this first). `--yes` — apply the **auto-removable** set.
|
|
293
|
+
|
|
294
|
+
It classifies every surface into four classes and acts accordingly:
|
|
295
|
+
|
|
296
|
+
- **remove** (safe) — an installed skill dir that is **provably ours** (valid manifest, `name`+`kind` match). A dir present but **not provably ours** (`foreign`/`stub`/`invalid`/unreadable) → **STOP**: left untouched **and reported**, while the teardown still removes the members that ARE ours (a not-ours surface is never clobbered, and never blocks removing the rest — the per-item `setup` posture). **Preflight-then-mutate:** if a mutable surface **changed since the dry-run** (a skill no longer ours, a wrapper turned foreign, a hook that lost our marker, a malformed fence), the run **aborts with zero changes**.
|
|
297
|
+
- **reverse** (managed-marker) — a bridge **wrapper symlink that points at our source** (a foreign/non-symlink one → STOP); the hidden-mode **managed fence** (via the existing `--unhide` path — only the fenced lines); a **pre-commit hook carrying our marker** (an unmarked / user hook → left + reported).
|
|
298
|
+
- **KEEP — never deleted** (report-only) — `docs/ai`, `AGENTS.md`, `CLAUDE.md`, `docs/plans`, and the `.claude/settings.json` `includeCoAuthoredBy` edit. The tool **prints the exact `rm` / `git rm --cached` commands**; the **user** runs them. Surface this in plain language; never delete on their behalf.
|
|
299
|
+
|
|
300
|
+
**Shared globals:** removing `agent-workflow-memory` / `agent-workflow-engine` / a bridge removes a **global** skill that another project on the machine may use — say so before applying. **Windows:** the wrappers are POSIX; the skill-dir + project arms still work, the wrapper arm reports *use WSL*.
|
|
301
|
+
|
|
238
302
|
---
|
|
239
303
|
|
|
240
304
|
## Gotchas
|
|
@@ -251,6 +315,7 @@ The non-obvious traps — scan these before bootstrapping or upgrading. Each is
|
|
|
251
315
|
- **Conversational language never translates artifacts.** It governs *dialogue only*. Code, identifiers, paths, commands, log output, abbreviations, and every deployed `docs/ai/` / `AGENTS.md` file stay in their source language. See [Communication contract](references/contracts.md#communication-contract).
|
|
252
316
|
- **Never auto-commit.** Report quality-gate results and wait for explicit approval — in both modes.
|
|
253
317
|
- **Never leak kit internals to the user.** No ADR ids, tool / function / operation names (`reconcile`, `inject`, `ensureSlot`), marker / slot / fragment / anchor terminology, or verbatim tool stderr in anything the user reads. Translate every tool outcome into plain language a third-party user — who has never read this `SKILL.md` — can understand and act on (e.g. the cap-refusal report in *Mode: upgrade* step 3).
|
|
318
|
+
- **Uninstall never deletes user-authored content, and dry-runs first.** `/agent-workflow-kit uninstall` removes only what is **provably ours** (a managed skill dir / wrapper symlink / fenced block / marker hook) and **prints — never runs** the `rm` / `git rm --cached` for `docs/ai`, the entry-point docs, and `.claude/settings.json`. Always run `--dry-run` first, show the plan, get consent, then `--yes`. A skill dir or symlink that is not provably ours is a STOP, never a clobber (the `setup` posture, inverted). Removing a shared global (memory/engine/a bridge) may affect another project — say so.
|
|
254
319
|
|
|
255
320
|
---
|
|
256
321
|
|
|
@@ -274,6 +339,7 @@ The three setup choices — **visibility** (step 2), **conversational language**
|
|
|
274
339
|
10. **Honest `known_issues.md`.** Every bug with a workaround gets Impact + Plan so it isn't re-discovered later.
|
|
275
340
|
11. **One conversational language.** Talk to the user in the language chosen at bootstrap; keep code, paths, commands, and abbreviations in their source language. See *Communication contract*.
|
|
276
341
|
12. **Attribution is opt-in.** Honour the *Attribution* block: by default no agent/AI/model mention anywhere (commits, PRs, code, comments, docs), and no `Co-Authored-By` trailer. See *Attribution contract*.
|
|
342
|
+
13. **Orchestrate via a named recipe.** Compose execution through a named recipe (Solo / Reviewed / Council / Delegated) and **always commit yourself** — backends are advisory or delegated, never autonomous. Encoded via the reconciled `workflow:orchestration` pointer (it routes to `/agent-workflow-kit recipes` + the engine canon), not by bloating the entry point.
|
|
277
343
|
|
|
278
344
|
---
|
|
279
345
|
|
|
@@ -306,6 +372,6 @@ Deploy these into `AGENTS.md`; remove rows that don't apply to the stack.
|
|
|
306
372
|
- [`references/scripts/`](references/scripts/) — the Node enforcement scripts (caps + staleness + index-freshness gate, 3-tier archive, hook installer) and their unit tests.
|
|
307
373
|
- [`migrations/`](migrations/) — per-version upgrade steps; see `migrations/README.md`.
|
|
308
374
|
- [`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`.
|
|
309
|
-
- [`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), `delegation.mjs` (the executable delegate/fallback decision + hand-off plan), `inject-methodology.mjs` + `engine-source.mjs` (the bounded slot reconciliation — ensure-slot / inject-if-empty / cap
|
|
375
|
+
- [`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), `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), `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).
|
|
310
376
|
- [`capability.json`](capability.json) — the kit's own `agent-workflow` family manifest (`kind: composition-root`).
|
|
311
377
|
- [`CHANGELOG.md`](CHANGELOG.md) — version history of this kernel.
|
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.
|
|
6
|
+
"version": "1.13.0",
|
|
7
7
|
"provides": [],
|
|
8
8
|
"roles": {},
|
|
9
9
|
"detect": {
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
"deployed": { "file": "docs/ai/.workflow-version" }
|
|
16
16
|
},
|
|
17
17
|
"install": { "npm": "@sabaiway/agent-workflow-kit" },
|
|
18
|
+
"uninstall": {
|
|
19
|
+
"removeResolved": "detect.installed",
|
|
20
|
+
"note": "the guarded `/agent-workflow-kit uninstall` removes the resolved detect.installed dir — never user-authored docs/ai (those are reported, not deleted)"
|
|
21
|
+
},
|
|
18
22
|
"cost": "none",
|
|
19
23
|
"quota": null,
|
|
20
24
|
"provenance": { "author": "sabaiway", "source": "github:sabaiway/agent-workflow" }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sabaiway/agent-workflow-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.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",
|
|
@@ -55,19 +55,18 @@ Start-of-session, during-work, and task-completion procedures live in [`docs/ai/
|
|
|
55
55
|
|
|
56
56
|
<!-- workflow:methodology:start -->
|
|
57
57
|
<!-- workflow:methodology:end -->
|
|
58
|
+
<!-- workflow:orchestration:start -->
|
|
59
|
+
<!-- workflow:orchestration:end -->
|
|
58
60
|
|
|
59
61
|
---
|
|
60
62
|
|
|
61
63
|
## 🚫 Hard Constraints
|
|
62
64
|
|
|
63
|
-
> Adapt to this stack — remove rows that don't apply. Style rules should be linter-enforced, not prose.
|
|
64
|
-
|
|
65
65
|
| Rule | Enforcement |
|
|
66
66
|
|------|-------------|
|
|
67
67
|
| No `export default` (named exports only) | Linter |
|
|
68
68
|
| No `any` / no unsafe casts | Linter / type-checker |
|
|
69
69
|
| Functional style (no mutation in app code) | Linter |
|
|
70
|
-
| No single-letter variables | Code review |
|
|
71
70
|
| Interactive elements semantic (button/link, not div+onClick) | Linter / a11y |
|
|
72
71
|
| No hardcoded colors — design tokens only | Code review |
|
|
73
72
|
| No business logic in components → hooks/services | Architecture review |
|
|
@@ -38,12 +38,13 @@ const STUB = 'stub';
|
|
|
38
38
|
const FOREIGN = 'foreign';
|
|
39
39
|
const OK = 'ok';
|
|
40
40
|
|
|
41
|
-
// readiness values.
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
41
|
+
// readiness values. Exported so the recipe planner (tools/recipes.mjs) maps backend availability off
|
|
42
|
+
// the SAME consts the detector emits — no magic readiness literals duplicated across the two modules.
|
|
43
|
+
export const READY = 'ready';
|
|
44
|
+
export const NEEDS_SKILL = 'needs-skill';
|
|
45
|
+
export const NEEDS_CLI = 'needs-cli';
|
|
46
|
+
export const NEEDS_CREDENTIALS = 'needs-credentials';
|
|
47
|
+
export const DEGRADED = 'degraded';
|
|
47
48
|
|
|
48
49
|
const EXPECTED_KIND = 'execution-backend';
|
|
49
50
|
|
package/tools/engine-source.mjs
CHANGED
|
@@ -22,6 +22,10 @@ import { validateManifest, VALID } from './manifest/validate.mjs';
|
|
|
22
22
|
export const ENGINE_ENV = 'AGENT_WORKFLOW_ENGINE_DIR';
|
|
23
23
|
export const EXPECTED_ENGINE_NAME = 'agent-workflow-engine';
|
|
24
24
|
export const ENGINE_FRAGMENT_REL = 'references/methodology-slot.md';
|
|
25
|
+
// The orchestration-recipes slot fragment — a SECOND bounded fragment the kit injects (Plan 4). An
|
|
26
|
+
// engine older than 1.2.0 does not ship it; detectEngine({ rel }) lets a caller verify the specific
|
|
27
|
+
// fragment so `status` can caveat a too-old engine instead of failing the methodology read.
|
|
28
|
+
export const ORCHESTRATION_FRAGMENT_REL = 'references/orchestration-slot.md';
|
|
25
29
|
const ENGINE_DEFAULT_REL = '.claude/skills/agent-workflow-engine';
|
|
26
30
|
|
|
27
31
|
const defaultStatType = (path) => {
|
|
@@ -47,9 +51,10 @@ export const resolveEngineDir = ({ env = {}, home = '' } = {}) => {
|
|
|
47
51
|
// (never a candidate-shipped one), and clones detectMemory's reason ladder so each failure has a
|
|
48
52
|
// distinct, actionable reason. ok only on: a dir that exists + VALID manifest + kind
|
|
49
53
|
// methodology-engine + the right name + available + the live fragment file present.
|
|
50
|
-
export const detectEngine = (engineDir, { source } = {}, deps = {}) => {
|
|
54
|
+
export const detectEngine = (engineDir, { source, rel } = {}, deps = {}) => {
|
|
51
55
|
const validate = deps.validate ?? validateManifest;
|
|
52
56
|
const statType = deps.statType ?? defaultStatType;
|
|
57
|
+
const fragmentRel = rel ?? ENGINE_FRAGMENT_REL;
|
|
53
58
|
|
|
54
59
|
// The dir itself must exist first — this is what lets an env-pointed-but-absent dir read as the
|
|
55
60
|
// distinct `env-set-but-missing` (validateManifest would only say "capability.json not found").
|
|
@@ -72,7 +77,7 @@ export const detectEngine = (engineDir, { source } = {}, deps = {}) => {
|
|
|
72
77
|
return { result: 'invalid', errors: [`validator threw: ${err?.message ?? err}`] };
|
|
73
78
|
}
|
|
74
79
|
})();
|
|
75
|
-
const fragmentPresent = statType(join(engineDir,
|
|
80
|
+
const fragmentPresent = statType(join(engineDir, fragmentRel)) === 'file';
|
|
76
81
|
const ok =
|
|
77
82
|
report.result === VALID &&
|
|
78
83
|
report.kind === 'methodology-engine' &&
|
|
@@ -89,7 +94,7 @@ export const detectEngine = (engineDir, { source } = {}, deps = {}) => {
|
|
|
89
94
|
? `engine manifest name "${report.name}" is not "${EXPECTED_ENGINE_NAME}"`
|
|
90
95
|
: report.available === false
|
|
91
96
|
? 'engine manifest is a declared stub (available:false)'
|
|
92
|
-
: `engine fragment missing (${
|
|
97
|
+
: `engine fragment missing (${fragmentRel})`;
|
|
93
98
|
return { ok, reason, dir: engineDir };
|
|
94
99
|
};
|
|
95
100
|
|
|
@@ -99,14 +104,14 @@ export const detectEngine = (engineDir, { source } = {}, deps = {}) => {
|
|
|
99
104
|
// not found/invalid" prefix is a stable contract: the agent classifies the reconcile STOP by it
|
|
100
105
|
// (distinct from the cap-skip message), so do not reword it without updating SKILL.md.
|
|
101
106
|
export const readEngineFragment = (engineDir, deps = {}) => {
|
|
102
|
-
const detection = detectEngine(engineDir, { source: deps.source }, deps);
|
|
107
|
+
const detection = detectEngine(engineDir, { source: deps.source, rel: deps.rel }, deps);
|
|
103
108
|
const installHint = `npx @sabaiway/agent-workflow-engine@latest init (or set ${ENGINE_ENV})`;
|
|
104
109
|
if (!detection.ok) {
|
|
105
110
|
throw new Error(`methodology engine not found/invalid at ${engineDir} (${detection.reason}) — install it: ${installHint}`);
|
|
106
111
|
}
|
|
107
112
|
const read = deps.readFileSync ?? readFileSync;
|
|
108
113
|
try {
|
|
109
|
-
return read(join(engineDir, ENGINE_FRAGMENT_REL), 'utf8');
|
|
114
|
+
return read(join(engineDir, deps.rel ?? ENGINE_FRAGMENT_REL), 'utf8');
|
|
110
115
|
} catch (err) {
|
|
111
116
|
throw new Error(
|
|
112
117
|
`methodology engine not found/invalid at ${engineDir} (fragment unreadable: ${err.message}) — install it: ${installHint}`,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ENGINE_ENV,
|
|
9
9
|
EXPECTED_ENGINE_NAME,
|
|
10
10
|
ENGINE_FRAGMENT_REL,
|
|
11
|
+
ORCHESTRATION_FRAGMENT_REL,
|
|
11
12
|
} from './engine-source.mjs';
|
|
12
13
|
|
|
13
14
|
// A valid engine dir = it exists (dir), the fragment file exists, and the validator reports a
|
|
@@ -180,3 +181,52 @@ describe('readEngineFragment — live read or loud throw', () => {
|
|
|
180
181
|
);
|
|
181
182
|
});
|
|
182
183
|
});
|
|
184
|
+
|
|
185
|
+
// The orchestration fragment is a SECOND bounded fragment (Plan 4), selected via deps.rel /
|
|
186
|
+
// detectEngine({ rel }) — non-breaking: the default rel stays the methodology fragment so every
|
|
187
|
+
// existing methodology call site is unchanged.
|
|
188
|
+
describe('detectEngine / readEngineFragment — orchestration fragment via rel', () => {
|
|
189
|
+
// statType that knows both fragments live in the engine (a current >=1.2.0 engine).
|
|
190
|
+
const bothPresent = (path) =>
|
|
191
|
+
path === ENGINE_DIR
|
|
192
|
+
? 'dir'
|
|
193
|
+
: path === join(ENGINE_DIR, ENGINE_FRAGMENT_REL) || path === join(ENGINE_DIR, ORCHESTRATION_FRAGMENT_REL)
|
|
194
|
+
? 'file'
|
|
195
|
+
: null;
|
|
196
|
+
|
|
197
|
+
it('verifies the orchestration fragment when rel is the orchestration path', () => {
|
|
198
|
+
const out = detectEngine(ENGINE_DIR, { source: 'default', rel: ORCHESTRATION_FRAGMENT_REL }, deps({ statType: bothPresent }));
|
|
199
|
+
assert.equal(out.ok, true);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('an older engine (no orchestration fragment) → detect not-ok, the reason names that fragment', () => {
|
|
203
|
+
const out = detectEngine(ENGINE_DIR, { source: 'default', rel: ORCHESTRATION_FRAGMENT_REL }, deps()); // okStatType: only the methodology fragment is a file
|
|
204
|
+
assert.equal(out.ok, false);
|
|
205
|
+
assert.match(out.reason, /orchestration-slot\.md/);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('the methodology read is unaffected by the new rel default (back-compat)', () => {
|
|
209
|
+
const out = detectEngine(ENGINE_DIR, { source: 'default' }, deps({ statType: bothPresent }));
|
|
210
|
+
assert.equal(out.ok, true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('readEngineFragment reads the orchestration fragment bytes when deps.rel is set', () => {
|
|
214
|
+
const out = readEngineFragment(
|
|
215
|
+
ENGINE_DIR,
|
|
216
|
+
deps({ source: 'default', rel: ORCHESTRATION_FRAGMENT_REL, statType: bothPresent, readFileSync: () => 'ORCH BODY' }),
|
|
217
|
+
);
|
|
218
|
+
assert.equal(out, 'ORCH BODY');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('readEngineFragment STOPs loudly when the orchestration fragment is absent (older engine)', () => {
|
|
222
|
+
assert.throws(
|
|
223
|
+
() => readEngineFragment(ENGINE_DIR, deps({ source: 'default', rel: ORCHESTRATION_FRAGMENT_REL })),
|
|
224
|
+
(err) => {
|
|
225
|
+
assert.match(err.message, /methodology engine not found\/invalid/);
|
|
226
|
+
assert.match(err.message, /orchestration-slot\.md/);
|
|
227
|
+
assert.match(err.message, /npx @sabaiway\/agent-workflow-engine@latest init/);
|
|
228
|
+
return true;
|
|
229
|
+
},
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
});
|