@sabaiway/agent-workflow-kit 14.1.0 → 14.3.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 +68 -0
- package/README.md +3 -3
- package/SKILL.md +1 -1
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/modes/agents.md +1 -1
- package/references/modes/dispatch.md +3 -3
- package/references/modes/grounding.md +1 -1
- package/references/modes/procedures.md +6 -4
- package/references/modes/recipes.md +2 -2
- package/references/modes/recommendations.md +1 -1
- package/references/modes/set-recipe.md +4 -2
- package/references/modes/status.md +1 -1
- package/references/templates/orchestration.json +1 -1
- package/tools/carriers.mjs +6 -1
- package/tools/checkpoint-restore.mjs +62 -5
- package/tools/checkpoint.mjs +16 -7
- package/tools/dispatch-baseline.mjs +49 -21
- package/tools/dispatch-store.mjs +2 -2
- package/tools/dispatch.mjs +37 -17
- package/tools/exec-producer.mjs +4 -4
- package/tools/inject-methodology.mjs +6 -4
- package/tools/orchestration-readme.mjs +10 -2
- package/tools/procedures.mjs +11 -7
- package/tools/task-brief.mjs +20 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,74 @@ 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
|
+
## 14.3.0 — the activity table gains its tier rows: `epic` (author, review) and `task` (author, execute) are configured, resolved and rendered like every other activity (AD-147)
|
|
8
|
+
|
|
9
|
+
**Epics and tasks now have recipe slots.** Until 14.2.0 the kit had an epic file and a task brief, but no slot said who
|
|
10
|
+
writes an epic, who reviews it, who writes a task brief or who runs one. 14.3.0 adds two activity rows to the one
|
|
11
|
+
registry, so `set-recipe`, `procedures`, `recipes`, `status` and the config validator all accept them with no second
|
|
12
|
+
list. A config without the new rows reads and resolves exactly as before. Story S7 of the epic
|
|
13
|
+
`EPICS-STORIES-TASKS-AS-THE-UNIT-OF-WORK`; contract `docs/ai/specs/kit/carriers/` revision 6 (part `activity-tiers`).
|
|
14
|
+
|
|
15
|
+
- **Two registry rows (`tools/carriers.mjs`).** `epic` has `author` (`solo | subagent`) and `review`
|
|
16
|
+
(`solo | reviewed | council`); `task` has `author` and `execute`, both `solo | delegated | subagent`. Neither row
|
|
17
|
+
carries an autonomy policy. A silent `epic.review` is reviewed as soon as a review backend is ready (solo until then);
|
|
18
|
+
the other three slots default to solo. `SLICE_BY_SLOT` gains the subagent slice sentence of `epic.author`,
|
|
19
|
+
`task.author` and `task.execute`.
|
|
20
|
+
- **The epic render (`tools/procedures.mjs`).** When `epic.review` is a shorthand recipe that dispatches agy, the
|
|
21
|
+
grounding pre-step carries no `--plan` and the review line is `agy-review plan <brief-file>`: plan mode over the
|
|
22
|
+
rendered epic brief, never the code form.
|
|
23
|
+
- **The orchestration note refreshes (`tools/orchestration-readme.mjs`).** The `_README` that 14.2.0 wrote is now a
|
|
24
|
+
known prior, and the current note names six activities and the new slots' values and defaults, so a deployed
|
|
25
|
+
`docs/ai/orchestration.json` that still carries that note refreshes on its next write. Both seed templates carry the new note.
|
|
26
|
+
- **The methodology pointer (`tools/inject-methodology.mjs`).** The four-activity fragment is a known prior and
|
|
27
|
+
refreshes to six. A customized fragment kept as is gets an upgrade note naming the current canon unless it carries
|
|
28
|
+
the six-activity token `feedback-triage, epic, task`.
|
|
29
|
+
- **Copy.** Every restatement of the activity list and of the subagent-capable slots names the two rows: the README,
|
|
30
|
+
and the `agents`, `procedures`, `recipes`, `recommendations`, `set-recipe` and `status` mode docs.
|
|
31
|
+
- **Tests.** Scenario cases S11–S18 of the carriers contract in `carriers.test.mjs`, `orchestration-config.test.mjs`,
|
|
32
|
+
`set-recipe.test.mjs`, `family-registry.test.mjs`, `recipes-shorthand.test.mjs`, `procedures-roster.test.mjs` and
|
|
33
|
+
`inject-methodology.test.mjs` (S17 is in the engine's canon test).
|
|
34
|
+
- **Stated limit.** The held-session gate of `review-state` and the fold lane of `procedures` still key on
|
|
35
|
+
`plan-execution.execute`, so they cover a delegated task only when that slot is delegated as well; the engine canon
|
|
36
|
+
says so.
|
|
37
|
+
|
|
38
|
+
Needs engine 5.8.0: `procedures epic` and `procedures task` exit 1 against an engine without the two sections.
|
|
39
|
+
|
|
40
|
+
## 14.2.0 — a task thread is measured over its own files: file-disjoint tasks of one checkpoint run as a wave, `open` refuses `task-files-scope`, `return` and `fold` refuse `out-of-files`, and `checkpoint restore <oid> --nonce <n>` undoes one task (AD-146)
|
|
41
|
+
|
|
42
|
+
**Tasks can now run side by side.** In 14.1.0 a delegation thread could name its task, but it was still measured over
|
|
43
|
+
the whole tree, so a second task's edits spoiled the first one's fingerprints and only one exec dispatch could run at a
|
|
44
|
+
time. From 14.2.0 a task thread is measured over the files its brief lists, so tasks whose files do not overlap can run
|
|
45
|
+
on one checkpoint at once, each on its own codex session. Untasked threads measure and restore exactly as in 14.1.0.
|
|
46
|
+
Story S9 of the epic `EPICS-STORIES-TASKS-AS-THE-UNIT-OF-WORK`; the contract `docs/ai/specs/kit/task-thread/` is now
|
|
47
|
+
live.
|
|
48
|
+
|
|
49
|
+
**Before you upgrade:** close every task thread opened under 14.1.0. A thread opened there is measured under two rules
|
|
50
|
+
and is not guaranteed to refuse. To undo a stray change: inside the files of a task thread closed without a fold, run
|
|
51
|
+
that thread's task restore on its own checkpoint; otherwise close every thread and run the whole-tree `restore <oid>`.
|
|
52
|
+
|
|
53
|
+
- **The files scope (`tools/dispatch-baseline.mjs`, `tools/dispatch-store.mjs`, `tools/exec-producer.mjs`).** The
|
|
54
|
+
base-relative diff, payload, fingerprint and clean probe take the thread's file list; the store fingerprint, the
|
|
55
|
+
returned-object enumeration and the returned diff pass it. Without a list every value is byte-identical to 14.1.0.
|
|
56
|
+
- **`dispatch open --task` refuses `task-files-scope`** for a listed path a task may not claim, naming the path and
|
|
57
|
+
its kind.
|
|
58
|
+
- **`dispatch return` and `fold` refuse `out-of-files`** for a task thread, naming every changed path that no open or
|
|
59
|
+
folded task thread on the same checkpoint lists (since the last commit); they fail closed on an undecidable domain or
|
|
60
|
+
an unreadable ledger.
|
|
61
|
+
- **`task-brief check` tolerates a wave.** A checkpoint dirtied only in files that other open or folded task threads on
|
|
62
|
+
it list (since the last commit) still passes; dirt in the brief's own files or in a path no such thread lists refuses
|
|
63
|
+
`checkpoint-stale`, and an unreadable ledger refuses with its reason.
|
|
64
|
+
- **`checkpoint restore <oid> --nonce <n>`** (`tools/checkpoint-restore.mjs` exports `restoreTaskThread`) restores
|
|
65
|
+
exactly one closed task thread's files and leaves every other path alone; it refuses `open-thread`, `task-folded` and
|
|
66
|
+
`task-target` in the contract's states, proves the result with git's own diff (external diff helpers and textconv off)
|
|
67
|
+
and prints `checkpoint restore <oid> task <n> proof clean`. The whole-tree `restore <oid>` is unchanged.
|
|
68
|
+
- **Copy.** `DISPATCH_CONTRACT` and the dispatch mode doc gain the task clause; D10 is stated as a bar for untasked
|
|
69
|
+
threads and a mechanism for task threads in the mode doc, the module comment and HELP, and `await`'s no-slot message
|
|
70
|
+
no longer restates it; the README's dispatch row names both refusals.
|
|
71
|
+
- **Tests.** New suites `dispatch-baseline.test/files-scope.test.mjs`, `dispatch.test/task-scope.test.mjs`,
|
|
72
|
+
`dispatch.test/task-wave.test.mjs` (two tasks, two sessions, no degrade) and `checkpoint.test/task-restore.test.mjs`;
|
|
73
|
+
six wave cases in `task-brief.test.mjs`.
|
|
74
|
+
|
|
7
75
|
## 14.1.0 — a dispatch names its task: `dispatch open --task <brief>` records the brief and its files, the ledger refuses overlapping and mixed task threads (`files-overlap`, `mixed-open`), and the held-session judge holds one session per task instead of one per commit (AD-145)
|
|
8
76
|
|
|
9
77
|
**A held session now belongs to a task.** Until 14.0.0 the held-session judge kept ONE held session per commit, so a
|
package/README.md
CHANGED
|
@@ -233,8 +233,8 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
|
|
|
233
233
|
| `/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. |
|
|
234
234
|
| `/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), and the **feature-spec adoption state** (`not adopted` / `adopting (N draft)` / `adopted (N live, M draft)` / `could not be read`, plus `declined` when recorded), 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. |
|
|
235
235
|
| `/agent-workflow-kit now` | any time | **read-only** answer to where work stands in four blocks: **NOW** names every plan in flight, its phase, current and next step, and the tree evidence; **STEPS** gives every ledger row its evidence-derived status; **QUEUE** folds named rows under their full heading paths and calls position priority only in the judged backlog; **CAMPAIGN** shows the source-size practice figures and config state. The plan's own text never sets a status; a contradicted claim prints beside it. A block that cannot be derived is WITHHELD with its cause; NOW has two halves, plans and tree, each independently a value or WITHHELD, and NOW itself is WITHHELD only when both are. Never writes, never commits, never runs a subscription CLI. |
|
|
236
|
-
| `/agent-workflow-kit recipes` | any time | **read-only** orchestration advisor: presents five named recipes for composing the carriers of a step — the bridges and the full-tool executor subagent — into plan → execute → review — **Solo / Reviewed / Council / Delegated / Subagent** — plans + recommends one for your environment (degrading with a stated reason when a backend isn't ready, or when the executor vehicle is missing/unusable), and offers the choice. The activity/slot registry (
|
|
237
|
-
| `/agent-workflow-kit procedures <activity>` | any time | **read-only** activity-procedures advisor: prints a named activity's ordered steps (`plan-authoring` / `plan-execution` / `routine` / `feedback-triage`) 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) + carrier readiness (`plan-authoring`: author, fold, review; default Reviewed when a backend is ready, Council on request; slot-aware incl. Delegated and Subagent) — and, for every dispatched backend, the **full driving contract at the point of use** (exact copy-pasteable invocation, grounding levers like agy's `--facts`/`--decided`, the round-2 `--continue` delta, guarded passthrough), verbatim from the bridge manifests (drift-guarded; each wrapper's `--help` prints the same) — except `feedback-triage`, whose record-bound block carries the check with `--excerpts`, the resolved member lines (ready bridge commands, the ready lens brief, or explicit skipped members), and either the record round-table command for a bridge obligation or the no-receipt fact otherwise: the record is the artifact. `--override <slot>=<value>` adjusts one slot per run. Composes with `recipes`; never writes, never commits, never runs a subscription CLI. |
|
|
236
|
+
| `/agent-workflow-kit recipes` | any time | **read-only** orchestration advisor: presents five named recipes for composing the carriers of a step — the bridges and the full-tool executor subagent — into plan → execute → review — **Solo / Reviewed / Council / Delegated / Subagent** — plans + recommends one for your environment (degrading with a stated reason when a backend isn't ready, or when the executor vehicle is missing/unusable), and offers the choice. The activity/slot registry (six activities) is rendered by `procedures` and by `set-recipe --help`. The orchestrator runs it via the bridge skills or the executor vehicle and **always commits**; the kit never executes a recipe, never runs a subscription CLI, never commits. |
|
|
237
|
+
| `/agent-workflow-kit procedures <activity>` | any time | **read-only** activity-procedures advisor: prints a named activity's ordered steps (`plan-authoring` / `plan-execution` / `routine` / `feedback-triage` / `epic` / `task`) 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) + carrier readiness (`plan-authoring`: author, fold, review; default Reviewed when a backend is ready, Council on request; slot-aware incl. Delegated and Subagent) — and, for every dispatched backend, the **full driving contract at the point of use** (exact copy-pasteable invocation, grounding levers like agy's `--facts`/`--decided`, the round-2 `--continue` delta, guarded passthrough), verbatim from the bridge manifests (drift-guarded; each wrapper's `--help` prints the same) — except `feedback-triage`, whose record-bound block carries the check with `--excerpts`, the resolved member lines (ready bridge commands, the ready lens brief, or explicit skipped members), and either the record round-table command for a bridge obligation or the no-receipt fact otherwise: the record is the artifact. `--override <slot>=<value>` adjusts one slot per run. Composes with `recipes`; never writes, never commits, never runs a subscription CLI. |
|
|
238
238
|
| `/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>=<value>` / `--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 or a subagent, never commits**; hand-editing stays fully supported. |
|
|
239
239
|
| `/agent-workflow-kit review-state` | any time | **read-only review-receipt checker** — makes "reviewed ≠ shipped" detectable: the bridge review wrappers append a receipt per successful review (into a file inside the git dir — never committable); this checks that every backend your configured `plan-execution.review` recipe names holds a **fresh, grounded receipt for the current uncommitted tree** (any later edit the payload can see moves the fingerprint and stales the receipt; a review continuation never re-attests a folded tree). `--check` gives a gate exit code to declare in `docs/ai/gates.json` **by hand or via the consent-gated seeder** (preview → your explicit yes; never without consent). `--await [--timeout <s>]` (AD-049) BLOCKS until every recipe-named backend has receipted the current tree — the durable completion signal is the receipt, never a process event — so you wait for the bridges instead of hand-polling. Never writes, never commits, never runs a subscription CLI; it spawns read-only `git` queries to fingerprint the tree — and `git commit --no-verify` stays possible (discipline, not a sandbox). |
|
|
240
240
|
| `/agent-workflow-kit sandbox-masks` | any time | **cosmetic exclude lane for sandbox device masks** — an OS sandbox (Claude Code) injects character-device masks into the work tree as untracked `git status` noise; the review domain already ignores them **by construction** (never-committable untracked classes — char/block devices, FIFOs, sockets — are excluded from the fingerprint, the assembled review payload, and the clean checks). This mode hides them from `git status` too: flagless = read-only probe (derives the CURRENT mask set from the unfiltered walk + lstat — never a frozen list — and revalidates fenced entries, loudly flagging one that became a real path); `--apply` = consent-gated FULL-BLOCK replace of its own fenced block in `git rev-parse --git-path info/exclude` (stale masks drop by construction; `--clear` always means REMOVE the block — it takes precedence over the derivation). Writes ONLY its fence — never `.gitignore`, never global config; symlinked/non-regular exclude paths and malformed fences fail closed. Watch note: a real file at an excluded path is silently skipped by bulk staging (`git add -A`/`git add .`) — delete the stale line first; the probe flags exactly this case. |
|
|
@@ -245,7 +245,7 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
|
|
|
245
245
|
| `/agent-workflow-kit commit-guard` | any time | **the read-only pre-commit guard** (D10) — makes the commit capture the whole current working tree, so «verified» and «about to be committed» are the same bytes (the receipt itself has a stated residual — see the mode doc). FIRST it refuses an **INDEX that lags the verified working tree** (the gates and the fingerprint describe the WORKING tree while `git commit` takes the INDEX alone, and the fingerprint cannot tell them apart — so a lagging index used to ship a strict subset of what was verified): unstaged tracked paths or reviewable untracked-not-ignored paths, named up to a bounded cap with the remainder stated, a dirty tracked **submodule** named separately with its own recovery, and fail-closed on an undecidable probe. This deliberately blocks a partial commit. Then it binds the LATEST completed `run-gates --final` receipt to the EXACT current tree: refuses on a missing/red/stale receipt, fingerprint drift under the run, a dangling later attempt, declaration content drift, evidence-hash or lcov drift, or unsatisfied review obligations (the same review-state decision, recomputed over a sanitized env — forged out-of-repo stores never satisfy). Re-runs NO gate or test. Wire it into `.git/hooks/pre-commit` (the installer writes the RESOLVED invocation). `git commit --no-verify` stays the stated residual. |
|
|
246
246
|
| `/agent-workflow-kit recommendations` | any time (every `upgrade` ends with it) | **read-only deployment advisor** (AD-044) — computes what in THIS deployment is configured sub-optimally (allowlist not seeded, autonomy render drifted, OS sandbox unavailable, gates undeclared, bridge friction, sandbox-mask clutter, an unacknowledged sandbox recipe, a feature-spec layer never adopted) and renders **verdict-first**: one composed verdict line (does anything need attention?), then each item as **{severity · what · one-line benefit · an optional `recipe:` line (the sandbox-lane live recipe, the worktrees-dir hand-apply-first grant advice, the agents hidden-mode reconcile follow-up, or the spec-adoption decline preview) · the exact consent-gated apply one-liner}**. The agent PRESENTS the section in the user's conversational language — every fact and count, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; raw tool block on request — and runs EXACTLY the rendered one-liners only on your yes, surfacing each item's posture note first. Renders **present-even-when-empty** (`no recommendations — flow optimal.`); a failed probe degrades to a stated skip line. Registry strings are fact-true frozen one-line data (posture/risk notes live in the mode doc at the consent moment); the kit never seeds `sandbox.network.allowedDomains` / `filesystem.allowWrite` (**HAND-APPLY** territory), and the sandbox-lane item's convergence is a neutral fingerprint acknowledgement recorded by a consent-gated ack writer into `docs/ai/acks.json` — never a security key (the recipe is documented per bridge in `capability.json` `networkHosts` + `writableDirs`). `--cwd` is required (the target project is explicit); never writes, never commits, never runs a subscription CLI. |
|
|
247
247
|
| `/agent-workflow-kit doc-parity` | any time | **read-only doc-parity lint** (AD-049) — kills the doc-drift class where a mode-contract doc silently lags a code constant (a `--check` doc still reading `300` after the diff cap moved to `400`): a **closed, exported registry** binds each live constant (review caps, schema versions, the ledger's own class/scope vocabulary, and the autonomy-doctor EXIT/status/trusted-dir contract) to the exact token its `references/modes/*.md` contract must carry, and asserts the CURRENT value renders into every bound file — a drifted doc, an unreadable file, or an absent token **fails closed**. The values are sourced from the live imports (never re-typed), so the lint can't itself go stale; adding a binding is adding a checked entry (closed-world, edit-safe). `--check` is a gate exit code for `docs/ai/gates.json`. Never writes, never commits, never runs a subscription CLI. |
|
|
248
|
-
| `/agent-workflow-kit dispatch` | any time | **the delegation engine** — makes "how much does delegating a sub-task actually buy?" a measured number instead of a feeling. `check <file>` validates a sub-task brief's contract block and exits 0/1 naming the first violated field — **form only**: whether the task is genuinely bounded, its design decided and its acceptance adequate stays your judgment, and a well-formed absurdity passes here by construction. `advise --step-class <c>` answers the question that comes BEFORE that one — which vehicle should carry this kind of sub-task, whether it is even present on this machine, and what the ledger has already recorded for threads of that class (finished, failed, closed without a fold, and still open — counted separately) — and it decides nothing: it refuses no dispatch, gates no verb, and a choice that diverges from the advice is noted rather than blocked. It reads the filesystem only: nothing is launched to find out what is installed, an absent ledger prints "no recorded history", an unreadable one prints the store's own words, and either way the advice still prints. The same block appears as a footer under a form-valid `check` — never under a refusal, so it can never hide one. `register` pre-registers an acceptance wave (step classes, pairing key, minimum observations per class, the mean and first-pass thresholds) so the bar can never be chosen after the results it judges — immutable per wave. `observe` records ONE hand-written observation (`solo-construction`, the baseline whose ratio is 1 by construction — except over a scope measuring zero bytes, which has no ratio at all and is recorded ineligible by name — or `self-reported`) — delegated numbers are never hand-written, they are derived. The writer verbs are where that derivation happens: `open` puts a delegated thread on the record with every mint-time field copied from the brief's own header, refusing a deadline the wrapper's cap plus its kill grace would not fit inside, and recording whether the tree it started from was clean against the thread's base — HEAD by default, or the tree `--checkpoint <oid>` names, so the second task of a story is measured over the first one's uncommitted work instead of opening dirty (a dirty one makes the result honestly unmeasurable rather than quietly counted), while `--task <brief>` also records which task brief the thread carries out and the files that brief lists, refusing, since the last commit, a task thread whose files overlap by path prefix those of an open task thread or of a folded thread of another brief (`files-overlap`), and a mix of the two kinds — an untasked open beside an open task thread or, for a `code` open of backend `codex`, after a task fold, and a task open beside an open untasked thread (`mixed-open`); `await` waits for that one dispatch to answer and writes nothing — only the finished receipt satisfies it, a run still holding the nonce means keep waiting, and a wait that runs out says so with its own exit code, names whether the deadline or your own timeout ended it, and authorizes nothing: a wait that ended without an answer is a question for you, never permission to dispatch again; `return` absorbs the receipt the wrapper minted — only a finished one, checked against the contract it actually ran, its deadline and its own report, and refused outright when the tree hides changes from git or moves while the return is being computed — and derives the bytes from git rather than from anyone's claim; `fold` is the acceptance, and it refuses if the tree moved since the return — precisely, it re-confirms **equality of the visible canonical payload**, which is a change detector rather than a cryptographic identity of the tree: under the default head base that payload's untracked section is unframed and carries no file mode, so a content or symlink target that imitates the marker opening the next entry can alias two trees, and making an untracked file executable moves nothing (both named as residuals in the mode doc, with the fix queued); under a checkpoint base it is one indexed diff that carries modes. A change set carrying a binary, a non-regular path, a submodule, or a symlink whose target is not valid UTF-8 is **refused** at `return` and `fold` — CONSERVATIVELY, rather than promise what the default head payload may not be able to follow — and the same refusals hold for a checkpoint thread. `degrade` closes a thread that never earned a fold, on the record and with its reason. `aggregate` prints one wave: the registered thresholds, every observation as context, and per step class the finished threads — a folded success with git-provable bytes contributes its ratio, one whose bytes are unprovable is excluded from the mean but still counts in the first-pass rate, and a failed thread, a degrade-closed one, or one folded after failing acceptance each count as a real zero. Below the registered minimum nothing is computed (insufficient); at or above it is computed and labeled PILOT evidence. It REFUSES rather than guessing: no pre-registration, an unfinished thread in scope, a recorded refusal-to-delegate that never opened a thread, or an ambiguous wave each stop the computation by name. `handoff-return --slug <s>` closes the worktree loop after `land --prepare`: it re-attests that main still holds exactly the prepared tree under the same HEAD (both recorded in the handoff at prepare time), prints the satellite handoff's user-owned content byte for byte with its boundaries, byte lengths and the main-owned destinations each part folds into, prints the handoff digest and both OIDs as its proof, states the after-the-fold order (a fold landed after the gates leaves them stale), and records ONE self-reported worktree-stream observation only when the whole prepared change set is measurable — a deletion, a rename, a symlink, a submodule or a mode-only change ends with a named NOT RECORDED instead, never a partial number. Appends only to its own ledger inside the git dir (never committable); it also writes `handoff-return`'s `write-tree` tree object and, for a checkpoint measurement, the leaf's OWN temporary index file and the blobs its forced adds store — never a ref, never the real index; never commits, never runs a subscription CLI. |
|
|
248
|
+
| `/agent-workflow-kit dispatch` | any time | **the delegation engine** — makes "how much does delegating a sub-task actually buy?" a measured number instead of a feeling. `check <file>` validates a sub-task brief's contract block and exits 0/1 naming the first violated field — **form only**: whether the task is genuinely bounded, its design decided and its acceptance adequate stays your judgment, and a well-formed absurdity passes here by construction. `advise --step-class <c>` answers the question that comes BEFORE that one — which vehicle should carry this kind of sub-task, whether it is even present on this machine, and what the ledger has already recorded for threads of that class (finished, failed, closed without a fold, and still open — counted separately) — and it decides nothing: it refuses no dispatch, gates no verb, and a choice that diverges from the advice is noted rather than blocked. It reads the filesystem only: nothing is launched to find out what is installed, an absent ledger prints "no recorded history", an unreadable one prints the store's own words, and either way the advice still prints. The same block appears as a footer under a form-valid `check` — never under a refusal, so it can never hide one. `register` pre-registers an acceptance wave (step classes, pairing key, minimum observations per class, the mean and first-pass thresholds) so the bar can never be chosen after the results it judges — immutable per wave. `observe` records ONE hand-written observation (`solo-construction`, the baseline whose ratio is 1 by construction — except over a scope measuring zero bytes, which has no ratio at all and is recorded ineligible by name — or `self-reported`) — delegated numbers are never hand-written, they are derived. The writer verbs are where that derivation happens: `open` puts a delegated thread on the record with every mint-time field copied from the brief's own header, refusing a deadline the wrapper's cap plus its kill grace would not fit inside, and recording whether the tree it started from was clean against the thread's base — HEAD by default, or the tree `--checkpoint <oid>` names, so the second task of a story is measured over the first one's uncommitted work instead of opening dirty (a dirty one makes the result honestly unmeasurable rather than quietly counted), while `--task <brief>` also records which task brief the thread carries out and the files that brief lists, refusing, since the last commit, a task thread whose files overlap by path prefix those of an open task thread or of a folded thread of another brief (`files-overlap`), and a mix of the two kinds — an untasked open beside an open task thread or, for a `code` open of backend `codex`, after a task fold, and a task open beside an open untasked thread (`mixed-open`), refusing at open a Files path the snapshot scope can never hold (`task-files-scope`), and measuring a task thread over its files alone, so `return` and `fold` refuse a changed path that no open or folded task thread on the same base claims (`out-of-files`); `await` waits for that one dispatch to answer and writes nothing — only the finished receipt satisfies it, a run still holding the nonce means keep waiting, and a wait that runs out says so with its own exit code, names whether the deadline or your own timeout ended it, and authorizes nothing: a wait that ended without an answer is a question for you, never permission to dispatch again; `return` absorbs the receipt the wrapper minted — only a finished one, checked against the contract it actually ran, its deadline and its own report, and refused outright when the tree hides changes from git or moves while the return is being computed — and derives the bytes from git rather than from anyone's claim; `fold` is the acceptance, and it refuses if the tree moved since the return — precisely, it re-confirms **equality of the visible canonical payload**, which is a change detector rather than a cryptographic identity of the tree: under the default head base that payload's untracked section is unframed and carries no file mode, so a content or symlink target that imitates the marker opening the next entry can alias two trees, and making an untracked file executable moves nothing (both named as residuals in the mode doc, with the fix queued); under a checkpoint base it is one indexed diff that carries modes. A change set carrying a binary, a non-regular path, a submodule, or a symlink whose target is not valid UTF-8 is **refused** at `return` and `fold` — CONSERVATIVELY, rather than promise what the default head payload may not be able to follow — and the same refusals hold for a checkpoint thread. `degrade` closes a thread that never earned a fold, on the record and with its reason. `aggregate` prints one wave: the registered thresholds, every observation as context, and per step class the finished threads — a folded success with git-provable bytes contributes its ratio, one whose bytes are unprovable is excluded from the mean but still counts in the first-pass rate, and a failed thread, a degrade-closed one, or one folded after failing acceptance each count as a real zero. Below the registered minimum nothing is computed (insufficient); at or above it is computed and labeled PILOT evidence. It REFUSES rather than guessing: no pre-registration, an unfinished thread in scope, a recorded refusal-to-delegate that never opened a thread, or an ambiguous wave each stop the computation by name. `handoff-return --slug <s>` closes the worktree loop after `land --prepare`: it re-attests that main still holds exactly the prepared tree under the same HEAD (both recorded in the handoff at prepare time), prints the satellite handoff's user-owned content byte for byte with its boundaries, byte lengths and the main-owned destinations each part folds into, prints the handoff digest and both OIDs as its proof, states the after-the-fold order (a fold landed after the gates leaves them stale), and records ONE self-reported worktree-stream observation only when the whole prepared change set is measurable — a deletion, a rename, a symlink, a submodule or a mode-only change ends with a named NOT RECORDED instead, never a partial number. Appends only to its own ledger inside the git dir (never committable); it also writes `handoff-return`'s `write-tree` tree object and, for a checkpoint measurement, the leaf's OWN temporary index file and the blobs its forced adds store — never a ref, never the real index; never commits, never runs a subscription CLI. |
|
|
249
249
|
| `/agent-workflow-kit worktrees` | any time | **parallel feature worktrees** — run several features in DIFFERENT agent sessions on one repo, zero interference on working-tree files (the ONE exception is the dependency cache, below): `provision <slug> --plan <file>` creates a sibling git worktree on branch `aw/<slug>` and populates it (registry-derived footprint copy-if-missing — a tracked file is never overwritten; EXACTLY ONE seeded feature plan; the `handoff-<slug>.md` record from minute zero; `node_modules` symlinked where the link stays ignored — a shared MUTABLE dependency cache: writes through it hit MAIN's node_modules; for isolation run the printed isolated-install command (`--install` only PRINTS it; on `--resume` run the printed unlink-first recovery first — printed only for a link whose RAW TARGET is MAIN's `node_modules`, since a foreign or unreadable link is reported as such with no removal advised); absolute root-pinned gate commands rebased on untracked copies only, and only while their bytes equal the MAIN source or its rebased form — user-modified copies stay untouched); `list` is read-only (slug, branch, base, dirty, handoff); `prompt <slug>` is read-only too and re-prints the satellite's cold-start prompt — the same text `provision` ends its report with: where the worktree is, its ONE seeded plan, the handoff as the one channel back, MAIN's orientation (shared series index, landing) and, under its own heading because it is probed on the satellite, that checkout's install posture — every value derived LIVE rather than replayed from the frozen provision record, a recorded value that no longer matches NAMED as a divergence (with the cause its source makes likely) instead of printed as the runnable one, every offered command marked with WHO runs it (`MAIN $ …` for the landing, `HERE $ …` for this checkout's own install, a posture with nothing to run staying prose), and a control character in any rendered value a typed STOP rather than a forged prompt line; `land <slug> --prepare` locks the common git dir, fail-closes on divergence or incomplete satellite state, transfers the complete accepted satellite diff onto a CLEAN main, runs sync plus the declared gates, and reports HEAD/TRANSFER/PREPARED OIDs — the commit ALWAYS stays a dialogue ask; `cleanup <slug>` takes the same lock and removes a LANDED worktree only after live landed-verification against main HEAD, while `--abandon` is the ONE destructive arm (destroys unlanded work; **no preview step** on any writer). The parent dir is the `docs/ai/worktrees.json` `parentDir` setting (default: the repo's sibling parent); an unwritable parent degrades to printed maintainer-pasted commands, and the one-time host consent that makes it promptless surfaces via `recommendations`. Never commits, never pushes, never runs a subscription CLI. |
|
|
250
250
|
| `/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. |
|
|
251
251
|
| `/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 runtime residual remains at the settings level — its guard ships as the opt-in `hook` command); a direct commit/push/publish still asks. `--dry-run` first. |
|
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: '14.
|
|
6
|
+
version: '14.3.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-kit
|
package/capability.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sabaiway/agent-workflow-kit",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.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",
|
|
@@ -12,7 +12,7 @@ The opt-in **subagent-vehicle writer** — the family's second `.claude/` writer
|
|
|
12
12
|
|
|
13
13
|
Writing code, running gates, and user-facing copy never move to these four vehicles.
|
|
14
14
|
|
|
15
|
-
**The fifth vehicle, `executor`, is the ONE full-tool one** (model and effort from `docs/ai/vehicles.json` — `opus` / `high` by default — and every tool, a shell included). It is the instrument behind the **Subagent** recipe, dispatched ONLY for a **bounded, file-disjoint slice** the orchestrator verifies afterwards by running its suites: a slice of execution (`plan-execution.execute`), a plan/contract authoring brief (`plan-authoring.author`), an authoring-round fold (`plan-authoring.fold`),
|
|
15
|
+
**The fifth vehicle, `executor`, is the ONE full-tool one** (model and effort from `docs/ai/vehicles.json` — `opus` / `high` by default — and every tool, a shell included). It is the instrument behind the **Subagent** recipe, dispatched ONLY for a **bounded, file-disjoint slice** the orchestrator verifies afterwards by running its suites: a slice of execution (`plan-execution.execute`), a plan/contract authoring brief (`plan-authoring.author`), an authoring-round fold (`plan-authoring.fold`), a bounded chore (`routine.carrier`), an epic brief (`epic.author`), a task brief written from one ledger row (`task.author`), or one stamped task brief run inside its Files (`task.execute`). It **never commits** (no git write at all), is **never a review backend**, is **never a bridge substitute**, and is **never dispatched for read-only work** — a sweep, an inventory or a review rides a read-only vehicle instead.
|
|
16
16
|
|
|
17
17
|
**Its readiness is the vehicle FILE.** `surveyExecutorVehicle` answers exactly one of four states: **`placed`** (bytes equal to the body derived from `docs/ai/vehicles.json` at `.claude/agents/executor.md`), **`customized`** (a readable regular file whose frontmatter names `executor` and whose tools are not read-only), **`unusable`** (a symlink, a non-regular or unreadable file, one failing that check, or an unreadable `docs/ai/vehicles.json` — with the reason), **`missing`**. `placed` and `customized` are dispatchable; on `unusable` or `missing` a `subagent` slot **degrades to Solo** with a reason naming this mode's apply command (and `docs/ai/vehicles.json` when that file is unreadable). `/agent-workflow-kit status` shows the state in its `agents` block and the deployment advisor raises it when a configured slot names `subagent` and the vehicle is `unusable` or `missing` — that item is **`executor-vehicle`** (attention-class: a configured declaration that is broken), a DIFFERENT capability from this mode's placement offer (`agents`), which converges the moment nothing is left to place and therefore can never observe a present-but-unusable vehicle. It is a claim about the FILE, never about the host: a Claude Code lane, like this mode itself.
|
|
18
18
|
|
|
@@ -6,7 +6,7 @@ The **delegation engine** (delegation Plans 1–2): the sub-task **contract chec
|
|
|
6
6
|
|
|
7
7
|
Run **`node ${CLAUDE_SKILL_DIR}/tools/dispatch.mjs <check|advise|register|observe|open|await|return|fold|degrade|handoff-return|aggregate> …`**:
|
|
8
8
|
|
|
9
|
-
1. **`check <dispatch-file>`** — validates the ONE ```` ```aw-dispatch-contract ```` fenced block the dispatch file carries: exit `0` when its form is valid, `1` naming the FIRST violated field. The contract of the whole mode, in one sentence: the contract check is FORM-only — fields present, grammars respected, never boundedness, design-decidedness or acceptance adequacy — and `aggregate` REFUSES instead of computing acceptance for a wave with no pre-registration record, over an OPEN thread in scope, over a PRE-DISPATCH degrade that opens no thread, or across several waves with no `--wave`; the writer verbs add NO second legality door — the store's preflight is the only one, and its refusals travel verbatim — while `open` copies every mint-time field from the contract header and refuses a deadline below the wrapper cap plus the kill grace, `return` absorbs only a TERMINAL exec receipt whose backend, nonce and independently computed contractDigest match the dispatch it answers, and `fold` binds the CURRENT tree to the folded return's postTreeDigest, so a tree that moved between the two never folds, and `await` is satisfied ONLY by the TERMINAL exec receipt of its own dispatch's {backend, nonce} — never by a review receipt, a ledger line or a finding manifest — while an expiry names a supervision question and releases NO writer slot; `open` records the thread's BASE (`head` by default, `checkpoint` under `--checkpoint <oid>`), `return` and `fold` measure against the base the dispatch recorded, never a flag, and the `fold` VERB itself refuses a checkpoint `code` thread the held-session judge names SUBSTITUTED in that thread's own verdict — a precondition like its hidden-path and content-blind guards, the store's preflight staying the only door on the record
|
|
9
|
+
1. **`check <dispatch-file>`** — validates the ONE ```` ```aw-dispatch-contract ```` fenced block the dispatch file carries: exit `0` when its form is valid, `1` naming the FIRST violated field. The contract of the whole mode, in one sentence: the contract check is FORM-only — fields present, grammars respected, never boundedness, design-decidedness or acceptance adequacy — and `aggregate` REFUSES instead of computing acceptance for a wave with no pre-registration record, over an OPEN thread in scope, over a PRE-DISPATCH degrade that opens no thread, or across several waves with no `--wave`; the writer verbs add NO second legality door — the store's preflight is the only one, and its refusals travel verbatim — while `open` copies every mint-time field from the contract header and refuses a deadline below the wrapper cap plus the kill grace, `return` absorbs only a TERMINAL exec receipt whose backend, nonce and independently computed contractDigest match the dispatch it answers, and `fold` binds the CURRENT tree to the folded return's postTreeDigest, so a tree that moved between the two never folds, and `await` is satisfied ONLY by the TERMINAL exec receipt of its own dispatch's {backend, nonce} — never by a review receipt, a ledger line or a finding manifest — while an expiry names a supervision question and releases NO writer slot; `open` records the thread's BASE (`head` by default, `checkpoint` under `--checkpoint <oid>`), `return` and `fold` measure against the base the dispatch recorded, never a flag, and the `fold` VERB itself refuses a checkpoint `code` thread the held-session judge names SUBSTITUTED in that thread's own verdict — a precondition like its hidden-path and content-blind guards, the store's preflight staying the only door on the record; `open --task` records the task, a task thread is measured over its Files and `open`, `return` and `fold` refuse `files-overlap`, `mixed-open` and `out-of-files`. Whether the sub-task is genuinely bounded, whether its design is decided, and whether its acceptance criteria are adequate stay **explicit orchestrator judgment** — a well-formed absurdity passes here by construction.
|
|
10
10
|
2. **`advise --step-class <c>`** — the **vehicle-routing advisory**, and the question that comes BEFORE a contract check: *which vehicle carries this step class on THIS host, and what has the ledger already recorded for it.* It prints one block — the advised vehicle with its availability, the solo fallback, the recorded history, and the note below — and **decides nothing**: the advice never gates a dispatch: which vehicle carries a sub-task stays orchestrator judgment, and a divergence from the advice is recorded as a note rather than refused. Exit `0` for every legal step class, `2` only on usage. Its posture, stated exactly: the advisor module itself writes nothing, spawns nothing and opens no second ledger door; the VERB may run read-only git probes — the delegation store path (unless AW_DELEGATION_STORE names it outright) and the repository top-level the cheap vehicles are anchored at — and it never runs a vehicle, a subscription CLI, or anything that writes. Host capability is read from the filesystem — the execute backend from the bridge install (the detector spawns nothing at all), a cheap vehicle from the presence of `.claude/agents/<name>.md` **at the repository top-level**; where that root is not resolved, the lane answers **`unknown`** rather than claiming a vehicle is unplaced, because an absent file under an unanchored directory is not evidence of absence and a present one there is not evidence it is this repository's vehicle. The recorded history is the ledger's OWN thread walk, over the closed state set `folded | failure-terminal | degrade-closed | open` with **`open` counted separately** (a live thread is not evidence about a finished one). An **absent** ledger prints `no recorded history`; an **unreadable** one prints the store's own words and the advice still prints; neither is a refusal. The same block prints as a **footer on a form-valid `check`** (never under a refusal, so it cannot mask one), where the advised vehicle is compared against the contract's `vehicle.selected` and a difference is printed as a divergence NOTE naming `vehicle.requested` when the pair itself differs.
|
|
11
11
|
|
|
12
12
|
The vehicle-routing matrix — one row per step class, and this copy is held to the code's registry CELL for cell by a structure check (a reorder, a duplicate, a dropped row, a mis-bound vehicle and a drifted availability or returns cell all leave every token present, so a token check would pass every one of them). The check reads only the anchored surface between the two markers below, so a copy of this table anywhere else in the doc can neither stand in for it nor mask its drift:
|
|
@@ -30,7 +30,7 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/dispatch.mjs <check|advise|register|observ
|
|
|
30
30
|
|
|
31
31
|
3. **`register`** — appends the wave's **pre-registration** record (`--wave --step-classes --pairing-key --min-per-class --mean-l-threshold --first-pass-num --first-pass-den`). Acceptance is pre-registered so thresholds can never be chosen after the observations that will be judged against them; a registration is **immutable per wave** and a second one refuses. `--pairing-key` accepts only a key the aggregator actually implements (today `stepClass`) — a wave registered under any other key would record a contract the computation never follows, and the aggregator re-checks the registration independently, since a store can be hand-written.
|
|
32
32
|
4. **`observe`** — appends ONE **observation** (`--wave --step-class --scope --plan --phase --provenance [--denominator-bytes]`). Provenance is `solo-construction` or `self-reported` **only**: delegated accounting is DERIVED from nonce threads and is never hand-appended. The numerator is the post-image bytes of the objects the scope names; a **solo** observation takes that same number as its denominator — `L = 1` by construction, so `--denominator-bytes` is refused — while a self-reported one states its own. One stated exception: a solo scope that measures **zero** bytes has no ratio at all, and is recorded INELIGIBLE by name (`zero-denominator`) rather than as `L = 1` — `0/0` is undefined before it is one, and a named ineligibility is what this family records instead of a silent number. **`--scope` is repeatable**, one repo-relative path per occurrence: no separator is safe inside a POSIX path, so a split list could not express `docs/my file.md` and would silently measure the wrong set wherever its fragments happened to exist. Paths are anchored at the **git top-level**, never at the caller's cwd, and the record carries a **JSON-encoded array of canonical repo-relative paths, carried in the schema's string field** (the record's `scope` is a string by D3, so the array travels encoded). An object's identity IS its canonical path, so two files with identical bytes are two objects and count twice, while one path reached twice (a repeated listing, an in-repo ancestor symlink) is one object and counts once. The run refuses by name outside a git work tree, for an absent or non-regular path, and for a path whose **real** location leaves the repository (an ancestor symlink is not a way out).
|
|
33
|
-
5. **`open`** — appends the **dispatch** record that opens a thread (`--contract <dispatch-file> --wave --backend --rationale --wrapper-cap-s --kill-grace-s [--checkpoint <oid>] [--task <brief>] [--retry-of <nonce>]`). Every mint-time field — `nonce`, `stepClass`, `vehicle`, `deadlineS`, `retry.index`, `retry.cap` — is **COPIED from the contract header** and bound by `contractDigest`, so a dispatch can never disagree with the header it claims to carry. It fingerprints the tree (`preTreeDigest`) and probes it for a CLEAN baseline; a **dirty** one is recorded as such, and the eventual return is then metric-INELIGIBLE by the name `dirty-baseline` — the uncommitted-state fingerprint is blind to the index↔worktree split, so a dirty baseline cannot attribute bytes to a dispatch. It **refuses a `deadlineS` below `--wrapper-cap-s` + `--kill-grace-s`** (both explicit operands: the kit never reads another package's default), because a dispatch that cannot be capped inside its own deadline could never honour the terminal-exit rule. Every retry rule — one successor per thread, the cap read off the chain's ORIGIN, wave and class equality, a changed contract after a `contract-refusal` — is the **store's**, and `open` surfaces its refusals verbatim. `--checkpoint <oid>` records the checkpoint base: the operand must be a git object id of exactly 40 or 64 lowercase hex characters that resolves to a TREE (a commit, a blob, a tag and an unknown id each refuse by name, nothing written), and every measurement of that thread — the clean probe, `preTreeDigest`, the return's bracketing fingerprint and diff, the fold's fingerprint and enumeration — is computed against that tree over the snapshot scope — every work-tree path not ignored by git's standard excludes judged without the real index, plus every present kit-own path, plus every path HEAD's tree or the base tree names, minus `docs/plans/`, `.claude/settings.json`, `.claude/settings.local.json`, `.mcp.json`, every known foreign-tool footprint and `node_modules`; the base tree's non-excluded paths deleted since the snapshot are measured as deletions; without the flag the base is `head` and every byte of the MEASUREMENT is today's (the writer always mints the `baseline` key, so the record itself is not byte-identical to 13.0.0's). The CLEAN line of a checkpoint open names the base. `--task <brief>` records the brief's path and its byte-ordered Files, requires `--checkpoint` (`task-base`), refuses a brief the parser refuses by the parser's name, and the store refuses `files-overlap` and `mixed-open` at append time.
|
|
33
|
+
5. **`open`** — appends the **dispatch** record that opens a thread (`--contract <dispatch-file> --wave --backend --rationale --wrapper-cap-s --kill-grace-s [--checkpoint <oid>] [--task <brief>] [--retry-of <nonce>]`). Every mint-time field — `nonce`, `stepClass`, `vehicle`, `deadlineS`, `retry.index`, `retry.cap` — is **COPIED from the contract header** and bound by `contractDigest`, so a dispatch can never disagree with the header it claims to carry. It fingerprints the tree (`preTreeDigest`) and probes it for a CLEAN baseline; a **dirty** one is recorded as such, and the eventual return is then metric-INELIGIBLE by the name `dirty-baseline` — the uncommitted-state fingerprint is blind to the index↔worktree split, so a dirty baseline cannot attribute bytes to a dispatch. It **refuses a `deadlineS` below `--wrapper-cap-s` + `--kill-grace-s`** (both explicit operands: the kit never reads another package's default), because a dispatch that cannot be capped inside its own deadline could never honour the terminal-exit rule. Every retry rule — one successor per thread, the cap read off the chain's ORIGIN, wave and class equality, a changed contract after a `contract-refusal` — is the **store's**, and `open` surfaces its refusals verbatim. `--checkpoint <oid>` records the checkpoint base: the operand must be a git object id of exactly 40 or 64 lowercase hex characters that resolves to a TREE (a commit, a blob, a tag and an unknown id each refuse by name, nothing written), and every measurement of that thread — the clean probe, `preTreeDigest`, the return's bracketing fingerprint and diff, the fold's fingerprint and enumeration — is computed against that tree over the snapshot scope — every work-tree path not ignored by git's standard excludes judged without the real index, plus every present kit-own path, plus every path HEAD's tree or the base tree names, minus `docs/plans/`, `.claude/settings.json`, `.claude/settings.local.json`, `.mcp.json`, every known foreign-tool footprint and `node_modules`; the base tree's non-excluded paths deleted since the snapshot are measured as deletions; without the flag the base is `head` and every byte of the MEASUREMENT is today's (the writer always mints the `baseline` key, so the record itself is not byte-identical to 13.0.0's). The CLEAN line of a checkpoint open names the base. `--task <brief>` records the brief's path and its byte-ordered Files, requires `--checkpoint` (`task-base`), refuses a brief the parser refuses by the parser's name, refuses `task-files-scope` for a Files path the snapshot domain can never hold, and the store refuses `files-overlap` and `mixed-open` at append time; a task thread is measured over its Files.
|
|
34
34
|
6. **`await`** — watches for ONE dispatch to **answer**, and writes nothing at all (`--nonce [--timeout <s>]`). Satisfaction is the arrival of the **TERMINAL** exec receipt for the dispatch's own `{backend, nonce}`: a `reserved` artifact means the run holds the nonce and has published nothing about how it ended, so the wait continues — the same artifact that is a **supervision refusal** at `return`, because absorbing it would record an outcome nobody observed. Satisfaction is decided **positively**, by the exec-receipt reader itself, so an artifact of a neighbouring family standing at that path — a review receipt, a delegation ledger line, a finding manifest — **refuses** rather than satisfies: only an exec receipt answers an exec dispatch, which is the D10 rule the review waiter states from its own side. The bound is the **ABSOLUTE** deadline, measured from the DISPATCH record's timestamp rather than from whenever this wait began: `--timeout` defaults to the time **remaining**, and one reaching past the deadline is **refused** rather than silently clamped (a shortened wait would let a caller believe they waited longer than they did). An already-expired dispatch is **answered immediately**, never waited on. **Arrival is read first, before EVERY bound** — the two wait bounds and the `--timeout` admissibility check alike, so a receipt already on disk answers `ARRIVED` even when the supplied `--timeout` is inadmissible, and the check runs only once there genuinely IS a wait to bound. A receipt already on disk is a fact this verb reports; whether a *late* one may be absorbed is the absorb door's question, refused there by name — **lateness has exactly one decision site, and it is `return`**. The review waiter checks its deadline first for the opposite reason: a receipt *line* carries no dispatch-bound timestamp at all, so there the clock is the only evidence there is. Each pass consults the clock over the poll that has already happened, then sleeps and polls again, so a receipt landing during the last sleep is reported rather than lost to a cutoff a moment later. An unanswered wait exits **`3`** — its own status so a caller that **branches** on the code can tell it from a refusal, never a defence against one that discards failure wholesale — names whether the **deadline** or the `--timeout` ended it, and states that **no writer slot was released**: a wait that ended without an answer never authorizes the next dispatch. Every artifact read rides the store's own no-follow reader, so a symlinked, FIFO, unreadable or malformed artifact refuses **by class** instead of standing in for an answer.
|
|
35
35
|
7. **`return`** — absorbs the wrapper's exec receipt and appends the **return** record (`--nonce [--outcome <o>] [--no-receipt --exit-status <n>]`). The receipt and its report live **beside the ledger**, in the store's own directory. It reads the **TERMINAL** receipt — a `reserved` one is a **supervision question**, not a timeout, and refuses by saying so — then checks the receipt's independently computed `contractDigest` against the dispatch's (a run that executed a *different* contract would otherwise correlate cleanly), its `{backend, nonce}` body against the dispatch it answers (the filename alone is composed by this side), its `capS + killGraceS` against the recorded `deadlineS`, and its timestamp against the **ABSOLUTE** deadline (`dispatch.timestamp + deadlineS`) — a late return refuses by name. It re-verifies the report's digest and length against the receipt, refuses a change set **hidden from the plain `git diff`** the head-base metric is computed over (assume-unchanged, skip-worktree, `diff.ignoreSubmodules`), and then enumerates the returned objects and frames the canonical integration bundle, **bracketed by the tree fingerprint**: a tree that moves mid-computation refuses rather than mixing two change sets. `--outcome` records an orchestrator judgment under the **closed override form** — a wrapper outcome either stays itself or moves to `contract-refusal | partial-edit | acceptance-failure | stale-return | store-failure`, and `success` is recordable only from a receipt that already says success; the record vocabulary's own cross-field rules cut the remaining incompatible pairs. **`--no-receipt`** means "no TERMINAL receipt", never "no evidence": it absorbs a **reservation ONLY** — over a `terminal` artifact it refuses, because a hand-stated outcome there would discard an exit status, a session id and a report digest the run actually proved, and skip the report check that guards them. It builds the return from that reservation (`wrapperVersion` and `posture`, never hand-typed), requires `--exit-status` and an `--outcome` from `transport-failure | contract-refusal | store-failure | missing-identity` (so `partial-edit` and `stale-return` are inexpressible there by name), and reads the report **if present** — an absent one records length 0 and the metric is then ineligible **by name**: `empty-report` where there IS a diff, and `no-op-diff` where the tree is unchanged too, since the eligibility rule names the diff first. That keeps a failed REPORT write and a failed TERMINAL write two separately named lanes. With **no artifact at all** there is no honest return — `--no-receipt` reads the same path and would refuse the same way — so close the thread with `degrade`.
|
|
36
36
|
8. **`fold`** — appends the integration re-confirmation and CLOSES the thread (`--nonce --verdict <text>`). It runs the **same hidden-path guard** as `return`, and here for a sharper reason: `treeDigestAtFold` is computed from the very payload that is blind to those paths, so under a HEAD base a change made behind an `assume-unchanged` / `skip-worktree` bit between the return and the fold leaves the digest **equal** and the fold would accept bytes nobody returned — the digest cannot catch what the payload cannot see. It then computes the **current** tree digest, which the store binds to the folded return's `postTreeDigest`: a tree that moved between the return and the fold refuses in the store's own words, and the recovery it names is a fresh dispatch, never a fold. Under a HEAD base, staging usually moves the tree too — every change set carrying an untracked path does — so the order is `return` → review (own eyes + the configured review recipe) → a plain gate run → `fold` → `git add`. **The one shape staging does not move** is a tracked-only change passing from the worktree into a **clean** index: the payload concatenates the staged and unstaged diffs, so those bytes are identical either side of `git add` (the uncommitted-state fingerprint's stated blindness to the index↔worktree split). The fold is still honest there — identical payload bytes mean the folded content IS the returned content — so the rule is "**the fold precedes staging**", never "staging refuses the fold by construction". A checkpoint measurement never reads the real index, so staging moves nothing there, while the fold still precedes `git add` by the same rule. `fold` refuses a checkpoint `code` thread the held-session judge names SUBSTITUTED in its own verdict, naming the ledger degrade and retry as recovery, and fails closed on an error epoch or an unreadable ledger.
|
|
@@ -46,6 +46,6 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/dispatch.mjs <check|advise|register|observ
|
|
|
46
46
|
|
|
47
47
|
**Which ledger the tree-binding verbs use.** For `open`, `return` and `fold` the resolved store must be the **canonical** one, exactly — `<git common dir>/agent-workflow-delegation.jsonl` — and every other store refuses. Three failures collapse into that one equality: a store placed inside the work tree is carried by the payload *and enumerated as an object*, so the metric would count its own bookkeeping as delegated work while the append that follows `postTreeDigest` moves the tree every later fold binds; a store belonging to another repository would measure this tree against a foreign thread, the frozen record schema binding no worktree identity; and a **second** ledger in the same git dir would share artifact names with the first, since those are a function of `{backend, nonce}` alone — so a return could absorb the neighbouring ledger's receipt. One repository, one delegation ledger, which is what resolving to the git *common* dir already meant. `register`, `observe`, `await` and `aggregate` keep the unrestricted override — they bind no tree. Path comparison canonicalizes through symlinks and **fails closed** on any error but `ENOENT` (a path this kit cannot resolve is not one it may approve); the check is repeated immediately before every append, which *narrows* the replacement window rather than closing it — a check-then-write pair is not atomic, and this module defends against a buggy or interrupted producer, never a racing adversary. `open` additionally refuses **pre-spend** when either exec artifact name for its `{backend, nonce}` is already taken: one nonce, one artifact pair. **Stated residual:** two *linked worktrees* of one repository share a common dir by design (the ledger is worktree-shared), so this rule cannot separate them — opening in one linked worktree and returning or folding in another measures the wrong tree, is **forbidden** under the D10 one-writer bar, and is named here rather than mechanized, because the frozen record schema carries no worktree identity to bind it with.
|
|
48
48
|
|
|
49
|
-
**What the fold's binding IS, and its stated residuals.** The binding is **equality of the visible payload** between the return and the fold — never an identity of the tree, and the difference is not academic. Under a HEAD base the payload is an unframed concatenation, so **two different trees can produce the same bytes**: probed live, a single file containing the line `untracked:two.txt` yields the same fingerprint as a tree of two files, and a symlink's target can imitate the marker that opens the next untracked entry. Its UNTRACKED section carries **no git-relevant mode**, so `chmod 0644 → 0755` on an untracked file moves neither the fingerprint nor the enumeration — a blind attribute, not a fourth unsupported content class (a TRACKED file's mode flip rides the diff as `old mode` / `new mode` and does move it). Regular-file content and symlink targets are deliberately **not** subtracted: they are present in the payload, only ambiguously framed, and refusing them would refuse `new` and `symlink`, which is every delegated change set there is. The real fix — a framed payload carrying mode bits — is queued against that frozen surface, since it revalues every stored head-base fingerprint in the family. Under a checkpoint base the payload is one indexed diff: a mode change moves it and no untracked marker line exists. A **receipt is forgeable**, exactly like every record in this family, so what the absorb door defends against is a buggy or interrupted producer, not a hostile one; under a head base the numerator **over-counts a rename** (a delegate's rename arrives as a deletion plus a creation, and no identity matching is done — that machinery was built and deliberately subtracted), so the metric reads optimistic, except in the rename-then-recreate case, which is indeterminate and named in the producer's own header; under a checkpoint base git's own rename detection applies inside the one base-relative layer and a detected rename is counted once as `renamed`; and **D10 is a bar, not a mechanism** — at most ONE in-tree exec dispatch runs at a time, and nothing here refuses a second one
|
|
49
|
+
**What the fold's binding IS, and its stated residuals.** The binding is **equality of the visible payload** between the return and the fold — never an identity of the tree, and the difference is not academic. Under a HEAD base the payload is an unframed concatenation, so **two different trees can produce the same bytes**: probed live, a single file containing the line `untracked:two.txt` yields the same fingerprint as a tree of two files, and a symlink's target can imitate the marker that opens the next untracked entry. Its UNTRACKED section carries **no git-relevant mode**, so `chmod 0644 → 0755` on an untracked file moves neither the fingerprint nor the enumeration — a blind attribute, not a fourth unsupported content class (a TRACKED file's mode flip rides the diff as `old mode` / `new mode` and does move it). Regular-file content and symlink targets are deliberately **not** subtracted: they are present in the payload, only ambiguously framed, and refusing them would refuse `new` and `symlink`, which is every delegated change set there is. The real fix — a framed payload carrying mode bits — is queued against that frozen surface, since it revalues every stored head-base fingerprint in the family. Under a checkpoint base the payload is one indexed diff: a mode change moves it and no untracked marker line exists. A **receipt is forgeable**, exactly like every record in this family, so what the absorb door defends against is a buggy or interrupted producer, not a hostile one; under a head base the numerator **over-counts a rename** (a delegate's rename arrives as a deletion plus a creation, and no identity matching is done — that machinery was built and deliberately subtracted), so the metric reads optimistic, except in the rename-then-recreate case, which is indeterminate and named in the producer's own header; under a checkpoint base git's own rename detection applies inside the one base-relative layer and a detected rename is counted once as `renamed`; and **D10 is a bar, not a mechanism, for untasked threads** — at most ONE untasked in-tree exec dispatch runs at a time, and nothing here refuses a second one; for task threads it is a mechanism: file-disjoint task threads on one checkpoint may run as a wave, `files-overlap` and `mixed-open` refuse conflicting opens at append time, and `return` and `fold` refuse `out-of-files`.
|
|
50
50
|
|
|
51
51
|
**Invariants:** writer — appends only to the delegation ledger, `<git common dir>/agent-workflow-delegation.jsonl` (`AW_DELEGATION_STORE` overrides, absolute only), through the store's own lock-serialized append; the store's preflight is the single legality door and this mode adds no second validator · every verb that DERIVES anything from the ledger (`return`, `fold`, `degrade`, `aggregate`) replays the store's preflight over the whole file first and refuses at the first record the append path would have refused, except `files-overlap` and `mixed-open`, which are judged at append time only, naming its physical line — a verb never computes over a "legal prefix" · **never commits**, never runs a subscription CLI, spawns nothing but git READS — with TWO stated exceptions: `handoff-return` attests MAIN's index with `git write-tree`, which may write a tree OBJECT into the odb (the same probe `land --prepare` itself uses), and checkpoint measurement writes the leaf's OWN temporary index file and forced-add blob objects — never a ref, never the real index; the ledger stays the only thing this mode APPENDS to · the ledger is separate from the review receipts and the flow store, and a line of one family never satisfies a reader of another.
|
|
@@ -11,6 +11,6 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/grounding.mjs [--constraints] [--autonomy] [
|
|
|
11
11
|
3. **`--plan <path>`** — extract the plan's three canon sections, verbatim + whole: `## Goal and boundary`, `## Module ledger`, `## Verification` (the engine `planning.md` literal headings; each REQUIRED — a missing or DUPLICATE heading is always a STOP).
|
|
12
12
|
4. **`--extra <text|@file>`** (corpus #88/#95 — the fourth firing of the same pre-dispatch append step) — append orchestrator-supplied facts byte-VERBATIM after the mechanical sections (repeatable, argv order; the `agy-review --facts` convention: literal text, or `@path` read whole through a race-free descriptor). An `@file` must resolve inside the PROVEN git work tree (rev-parse success — no cwd fallback; the git dir itself is refused) or the system temp surface — anything else refuses loudly (the exfil class: this tool is bridge-tier auto-allowable), as does a missing, EMPTY, or non-regular file (a FIFO cannot block the read). The merge happens INSIDE the tool, so the promptless lane is the invocation itself.
|
|
13
13
|
5. **Byte budget** — the output honors the same `AGY_MAX_PROMPT_BYTES` contract the agy wrapper enforces (override may only tighten; the OS argv ceiling is rejected), MINUS **`--reserve-bytes <n>`** — the artifact share the caller expects `agy-review` to add around these facts. Overflow is trimmed tail-first with a loud in-band marker + stderr report — never a silent cut.
|
|
14
|
-
6. Feed the result to the wrapper: `agy-review code --facts @<out>`. The `procedures` advisor renders this
|
|
14
|
+
6. Feed the result to the wrapper: `agy-review code --facts @<out>`. The `procedures` advisor renders this pre-step, with each activity's own operands and review form, when a shorthand review recipe dispatches agy; `feedback-triage` renders its own record block instead.
|
|
15
15
|
|
|
16
16
|
**Invariants:** writer (writes at most the ONE `--out` scratch file — system-temp, or a fresh gitignored in-repo path, exclusive-create) · never commits · never runs a subscription CLI · verbatim slices + verbatim extras (assembly is mechanical; facts judgment stays with the orchestrator — `--extra` carries it, the tool never edits it).
|
|
@@ -4,22 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
Read-only **activity-procedures advisor**. Answers *"what are the steps of this named activity, and which recipe applies at each slot here?"* It composes the orchestration recipes (`${CLAUDE_SKILL_DIR}/references/modes/recipes.md`) into **named activities** with **typed recipe slots**. It **never writes, never commits, never runs a subscription CLI** — the deterministic resolution lives in the kit; the orchestrator runs the resolved recipe via the bridge skills or the executor vehicle and **owns any commit when the activity has a commit boundary** (every other carrier never commits). Not every activity commits: `plan-authoring` ends at approval and produces no commit (plans are ephemeral, never committed); `plan-execution` commits per ledger row.
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The six activities (canon in the **installed engine**, `references/procedures.md`; the registry is `tools/carriers.mjs`):
|
|
8
8
|
|
|
9
9
|
- **`plan-authoring`** (slots: `author`, `fold`, `review`) — research → draft (the resolved `author` carrier drafts: Solo writes it, Subagent drafts from the orchestrator's brief) → self-review with the readers sweep first → **review {recipe}** → consult, then fold/loop through the resolved `fold` carrier → present for approval; enforce the mandatory Cleanup.
|
|
10
10
|
- **`plan-execution`** (slots: `execute`, `review`) — per ledger row: resolve the recipe → if Delegated, dispatch execution first; if Subagent, dispatch file-disjoint slices to the executor vehicle and verify each returned slice → implement → self-review → **review {recipe}** → gates → commit boundary; after the last row, the project-declared stages and Phase: Cleanup run as rows of their own.
|
|
11
11
|
- **`routine`** (slots: `carrier`, `parallel`) — name the chore and its file-disjoint slices → resolve → carry it (Solo, or Subagent: a read-only slice rides a placed read-only vehicle, a write-capable one rides the executor; `parallel` on → concurrently) → verify every returned slice; the commit boundary is unchanged.
|
|
12
12
|
- **`feedback-triage`** (slot: `review`) — record → verify every claim by code on the stamped HEAD → `feedback-record-cli --check` → **review {recipe}** over the record, the excerpts as agy's `--facts` payload → `--rows` renders the queue rows and the ratchet line → fold only a false statement in shipped copy.
|
|
13
|
+
- **`epic`** (slots: `author`, `review`) — brief → draft by the resolved `author` carrier → `epic-shape-cli --check` → **review {recipe}** over the rendered review brief (bridges in plan mode over it; one lens is the tier's roster) → fold through `--fold`, at most two rounds → land.
|
|
14
|
+
- **`task`** (slots: `author`, `execute`) — mint a checkpoint → the resolved `author` carrier writes the brief from one ledger row, stamp and check it → the resolved `execute` carrier runs it inside its Files (Delegated: `dispatch open --checkpoint <oid> --task <brief>`, one session per task) → verify by its Acceptance → return into the story's row; no commit boundary or review of its own.
|
|
13
15
|
|
|
14
|
-
Value sets per slot type: `review` accepts `solo | reviewed | council`; `execute` accepts `solo | delegated | subagent`; a carrier slot (`author`, `fold`, `carrier`) accepts `solo | subagent`; `parallel` is a **switch**, `on | off`, resolved outside the recipe lattice. Defaults when the config is silent: `review` → Reviewed if a review-capable backend is ready, else Solo; `author`, `fold`, `execute`, `carrier` → Solo (a placed executor never flips a default); `parallel` → on. The orchestrator owns every commit; every other carrier — a bridge or a subagent — never commits.
|
|
16
|
+
Value sets per slot type: `review` accepts `solo | reviewed | council`; `execute` (including `task.author` and `task.execute`) accepts `solo | delegated | subagent`; a carrier slot (`plan-authoring.author`, `plan-authoring.fold`, `routine.carrier`, `epic.author`) accepts `solo | subagent`; `parallel` is a **switch**, `on | off`, resolved outside the recipe lattice. Defaults when the config is silent: `review` → Reviewed if a review-capable backend is ready, else Solo; `author`, `fold`, `execute`, `carrier` → Solo (a placed executor never flips a default); `parallel` → on. The orchestrator owns every commit; every other carrier — a bridge or a subagent — never commits.
|
|
15
17
|
|
|
16
18
|
Run **`node ${CLAUDE_SKILL_DIR}/tools/procedures.mjs <activity> [--override <slot>=<value>]… [--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:
|
|
17
19
|
|
|
18
|
-
1. **Config = `docs/ai/orchestration.json`** — strict JSON, **agent-writable via `/agent-workflow-kit set-recipe` (`${CLAUDE_SKILL_DIR}/references/modes/set-recipe.md`) OR hand-edited** (the kit reads + validates it; `procedures`/`recipes` stay read-only — the writer is `set-recipe`). Shape: `{ "<activity>": { "<slot>": "<value>" } }`; all slots optional (an absent slot → its computed default, stated); an optional `"_README"` string is allowed + ignored; a `"flow"` object must carry the NUMERIC `"schema": 1` (the kit's accepted flow schema version) and validates against the CLOSED structural schema-1 key set (unknown flow keys and malformed per-key shapes refuse loudly; deep environment floors stay on the `set-flow` arming path). `review` accepts `solo|reviewed|council`; `execute` accepts `solo|delegated|subagent`; a carrier slot (`author`, `fold`, `carrier`) accepts `solo|subagent`; `parallel` accepts `on|off`. Seeded by `init` (a user-editable template) — see `${CLAUDE_SKILL_DIR}/references/modes/bootstrap.md`.
|
|
20
|
+
1. **Config = `docs/ai/orchestration.json`** — strict JSON, **agent-writable via `/agent-workflow-kit set-recipe` (`${CLAUDE_SKILL_DIR}/references/modes/set-recipe.md`) OR hand-edited** (the kit reads + validates it; `procedures`/`recipes` stay read-only — the writer is `set-recipe`). Shape: `{ "<activity>": { "<slot>": "<value>" } }`; all slots optional (an absent slot → its computed default, stated); an optional `"_README"` string is allowed + ignored; a `"flow"` object must carry the NUMERIC `"schema": 1` (the kit's accepted flow schema version) and validates against the CLOSED structural schema-1 key set (unknown flow keys and malformed per-key shapes refuse loudly; deep environment floors stay on the `set-flow` arming path). `review` accepts `solo|reviewed|council`; `execute` (including `task.author` and `task.execute`) accepts `solo|delegated|subagent`; a carrier slot (`plan-authoring.author`, `plan-authoring.fold`, `routine.carrier`, `epic.author`) accepts `solo|subagent`; `parallel` accepts `on|off`. Seeded by `init` (a user-editable template) — see `${CLAUDE_SKILL_DIR}/references/modes/bootstrap.md`.
|
|
19
21
|
2. **Default resolution (config silent):** `review` → Reviewed if any review-capable backend is `ready`, else Solo (never Council by default); `execute`, `author`, `fold`, `carrier` → Solo (Delegated and Subagent are opt-in; a placed executor never flips a default); `parallel` → on. **Degradation:** a config/computed default degrades **gracefully with a stated reason** (Council → Reviewed → Solo; Delegated → Solo; Subagent → Solo when the executor vehicle is missing or unusable, the reason naming the apply command; a switch never degrades); a per-run **`--override <slot>=<value>`** 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).
|
|
20
22
|
3. **Exit codes:** `0` success; `2` usage (unknown `<activity>` / bad `--override` — a bare `--override <recipe>`, an unknown slot, a value outside the slot's list, 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. **Lagging-kit honesty:** a kit predating the `"flow"` key that reads a config carrying one fails this config load loudly (exit `1`, reddening its full gate matrix); the `set-flow` arming path now enforces the declared `kitMinVersion` floor with a null-guarded comparison (an unparseable version never passes), while tolerate-first ordering remains the only protection for readers older than the `"flow"` key itself — no in-config floor can reach a kit that dies on the unknown key.
|
|
21
23
|
|
|
22
|
-
**The dispatch form (a slot resolved to `subagent`).** A carrier that is only NAMED is a name, not an instruction, so after such a slot's resolved-recipe line the advisor prints — indented under it, in place of the one-line vehicle mention — the form the dispatch must take, in five parts: (1) what a SLICE is for THIS slot — for `execute`, a set of file-disjoint ledger rows, wording copied verbatim where wording is a red line; for `author`, a brief naming the goal, the governing spec(s) and the ledger constraints, whose returned draft the orchestrator reviews as its own; for `fold`, the round's findings with their dispositions, whose edits the orchestrator follows with the self-consistency read; for `routine.carrier`, a bounded mechanical task, where a read-only chore (a sweep, gate triage) rides its placed read-only vehicle — or is carried solo with a stated reason when that vehicle is absent — a write-capable one (a regeneration, a fixture build) rides the executor, and the changelog stays the orchestrator's; (2) the vehicle and its surveyed state — `.claude/agents/executor.md` (`placed` / `customized` / `unusable` / `missing`, from the same survey `status` and the advisor read) — dispatched **in the background**; (3) that the orchestrator **verifies every returned slice by running its suites itself**; (4) that the subagent is **never told to commit, never a review backend, never a bridge substitute**; (5) the **honest limit** — a Claude Code lane: on a host that cannot dispatch the vehicle, follow this form BY HAND and say so, never report it as a subagent dispatch. The wording is the kit's own (`tools/carriers.mjs`) and is printed, never re-worded. The dispatch-form branch is unchanged for a slot resolved to `solo` or `delegated`.
|
|
24
|
+
**The dispatch form (a slot resolved to `subagent`).** A carrier that is only NAMED is a name, not an instruction, so after such a slot's resolved-recipe line the advisor prints — indented under it, in place of the one-line vehicle mention — the form the dispatch must take, in five parts: (1) what a SLICE is for THIS slot — for `plan-execution.execute`, a set of file-disjoint ledger rows, wording copied verbatim where wording is a red line; for `plan-authoring.author`, a brief naming the goal, the governing spec(s) and the ledger constraints, whose returned draft the orchestrator reviews as its own; for `plan-authoring.fold`, the round's findings with their dispositions, whose edits the orchestrator follows with the self-consistency read; for `routine.carrier`, a bounded mechanical task, where a read-only chore (a sweep, gate triage) rides its placed read-only vehicle — or is carried solo with a stated reason when that vehicle is absent — a write-capable one (a regeneration, a fixture build) rides the executor, and the changelog stays the orchestrator's; for `epic.author`, a brief naming the intent, the value, the non-goals and the stories in order, from which the subagent drafts the epic file and the orchestrator runs the shape check on the draft as its own; for `task.author`, one ledger row of the plan with the contracts it reads, from which the subagent writes the task brief and the orchestrator stamps and checks it; for `task.execute`, one stamped brief, run inside its Files with the changed paths reported and the Acceptance commands run by the orchestrator; (2) the vehicle and its surveyed state — `.claude/agents/executor.md` (`placed` / `customized` / `unusable` / `missing`, from the same survey `status` and the advisor read) — dispatched **in the background**; (3) that the orchestrator **verifies every returned slice by running its suites itself**; (4) that the subagent is **never told to commit, never a review backend, never a bridge substitute**; (5) the **honest limit** — a Claude Code lane: on a host that cannot dispatch the vehicle, follow this form BY HAND and say so, never report it as a subagent dispatch. The wording is the kit's own (`tools/carriers.mjs`) and is printed, never re-worded. The dispatch-form branch is unchanged for a slot resolved to `solo` or `delegated`.
|
|
23
25
|
|
|
24
26
|
**Fold lane (an execute slot resolved to `delegated`).** Immediately after that slot's driving contract, the advisor renders `codex-exec --resume <held id> --nonce <nonce> <fold-brief>` under the populated `run:` prefix, with the audited ledger's held id shell-quoted. `<nonce>` and `<fold-brief>` stay placeholders. One `caveat:` line replaces the id in each no-id case: no ledger; no folded code session in the commit epoch; a recorded substitution; an unresolvable, unreadable, malformed or audit-refused ledger (the reader reason verbatim); a failed HEAD read; or an id a one-line render cannot carry. An unborn branch runs the judge and is not a caveat. The block is advisory and never changes the exit code; `foldLane` carries the identical lines under `--json`, and is `[]` outside `plan-execution` or when execute resolves to Solo or Subagent. The sidecar is never read.
|
|
25
27
|
|
|
@@ -10,13 +10,13 @@ The five recipes (defined over each bridge's `provides` roles — `codex`: execu
|
|
|
10
10
|
- **Reviewed** — you execute; **one** backend reviews the result (advisory). Prefers `codex` when both are ready (`agy` carries a standing health caveat).
|
|
11
11
|
- **Council** — **both** backends review independently; you synthesize the two opinions.
|
|
12
12
|
- **Delegated** — you hand a **bounded** execution sub-task to a backend (`codex exec`), then review the returned diff and commit.
|
|
13
|
-
- **Subagent** — a **full-tool frontier subagent**, dispatched from the placed executor vehicle (`.claude/agents/executor.md`), carries a **bounded, file-disjoint** slice — of execution, of plan/contract authoring, of an authoring fold, or of
|
|
13
|
+
- **Subagent** — a **full-tool frontier subagent**, dispatched from the placed executor vehicle (`.claude/agents/executor.md`), carries a **bounded, file-disjoint** slice — of execution, of plan/contract authoring, of an authoring fold, of routine work, of an epic brief (`epic.author`), of a task brief from one ledger row (`task.author`), or of one stamped task brief run inside its Files (`task.execute`); you verify the returned slice by running its suites yourself and you make the commit. It is **never a review backend**, **never a bridge substitute**, and is **never told to commit**; it **degrades to Solo** when the vehicle is `missing` or `unusable`, with the reason. Readiness here is the **vehicle FILE, never the host** — a **Claude Code lane**, like the `agents` writer itself: on a host that cannot dispatch the vehicle, the rendered dispatch form is an instruction you follow by hand and report as such, never as a subagent dispatch.
|
|
14
14
|
|
|
15
15
|
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 five recipes, and prints — for the current environment — a **per-recipe dispatch plan that degrades with a stated reason** when a carrier isn't `ready` (Council → Reviewed → Solo; Delegated → Solo; Subagent → Solo when the executor vehicle is `missing`/`unusable`), plus advisory **quota/health notes** (prefer the cheapest model; Council spends two backends' quota; `agy` may stall on substantive prompts — Issue-001, prefer `codex`).
|
|
16
16
|
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.
|
|
17
17
|
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).
|
|
18
18
|
|
|
19
|
-
**The activities and their slots.** One registry (`tools/carriers.mjs`, re-exported by `recipes.mjs`) names **
|
|
19
|
+
**The activities and their slots.** One registry (`tools/carriers.mjs`, re-exported by `recipes.mjs`) names **six** activities and their typed slots: `plan-authoring` → `author`, `fold`, `review`; `plan-execution` → `execute`, `review`; `routine` → `carrier`, `parallel`; `feedback-triage` → `review`; `epic` → `author`, `review`; `task` → `author`, `execute`. Each slot's accepted values follow its TYPE — `review` (including `epic.review`) accepts `solo|reviewed|council`; `execute` (including `task.author` and `task.execute`) accepts `solo|delegated|subagent`; `carrier` (including `epic.author`) accepts `solo|subagent`. **`parallel` is a flag (`on|off`), not a recipe:** it resolves OUTSIDE the recipe lattice, never degrades, and never reaches the planner. A silent slot takes its **computed default** — `solo` for `author`, `fold`, `execute` and `carrier` (placing the executor vehicle never flips a default; the subagent carrier is opt-in exactly as `delegated` is), `reviewed`/`solo` by readiness for `review`, and `on` for `parallel`.
|
|
20
20
|
|
|
21
21
|
**The configured-recipe line (`--active-line`, read-only).** `node ${CLAUDE_SKILL_DIR}/tools/recipes.mjs --active-line` prints exactly **one** machine-composed line: the **CONFIGURED** recipe of every activity/slot, resolved from the target project's `docs/ai/orchestration.json` (read from the current directory) + live readiness — each slot with its source (configured vs computed default), its degradation stated, and its dispatched wrapper set — explicitly contrasted with the readiness **recommendation** (which is informational; the configured recipes are what runs). Paste it verbatim: it fills the session-start discovery step (the deployed `agent_rules.md` §1.1) and the handover "Active recipes:" slot; `set-recipe` echoes the same line after every successful write. A malformed config fails loud (exit 1), never a silent fallback.
|
|
22
22
|
|
|
@@ -20,7 +20,7 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd <project-root> [--
|
|
|
20
20
|
3. **The apply-through-agent lane — an explicit informed-consent checkpoint:** after presenting, OFFER to apply; the user selects items in plain language; for each selected item you **surface its posture note inline** where one exists (the per-item notes below cover exactly the risk-marked keys; for `sandbox-lane` the note INCLUDES the sandbox-lanes ladder — present the whole ladder inline at the consent moment, never as a bare pointer). The user **explicitly confirms**, and **only then** — **no command runs before confirmation** — do you run the rendered command. Do NOT infer safety from the presence or absence of an `--apply` flag: most items' rendered command IS the mutation and completes on that one run, **including a no-`--apply` mutation** such as `family-freshness`'s `npx … init`. Some items instead render a **dry-run preview** that changes nothing and prints an explicit follow-up `--apply`/mutating command to run NEXT (e.g. `sandbox-lane`'s ack-write — a NEUTRAL recipe fingerprint into the family-owned `docs/ai/acks.json`, never a security key — and the `gates-declaration` seeder): after the SAME confirmation you run that printed follow-up command — no second ask, no improvisation (each writer keeps its own consent semantics: previews, `--apply` flags, refusals). An item marked **HAND-APPLY** (e.g. the `read-lane` stale/missing arms) is **never run by you and never written by the kit** — hand the user its rendered line together with its posture note; HAND-APPLY is **maintainer territory wherever it renders** — the apply slot or the `recipe:` line. For `worktrees-dir` the two classes COMPOSE in one item and the ORDER is part of the contract: its `recipe:` line is the HAND-APPLY grant advice, its apply one-liner is the dry-run ack preview, and you **wait for the maintainer to confirm the grant is applied (or the terminal fallback chosen)** before running that preview and the exact `--apply` command it prints — the ack RECORDS a choice that must already have been made, and against a trusted host NO the item renders no ack at all.
|
|
21
21
|
4. Registry strings (benefits + item texts) are frozen tool data, fact-true, ONE line under the pinned shape cap — posture/risk detail lives in the notes below at the consent moment, never inline in the overview. The dual velocity+security wording (`safer — blast radius bounded by the OS sandbox, not human attention`) rides ONLY the items with a real security delta (the autonomy render, the sandbox provisioning); the bridge-wrappers item claims **velocity only**.
|
|
22
22
|
|
|
23
|
-
**The `executor-vehicle` item (the carrier the project already CONFIGURED — beside the `agents` offer, never the same item).** It fires on ONE pair of facts: a slot in `docs/ai/orchestration.json` names `subagent` while the executor vehicle (`.claude/agents/executor.md`) is `missing` or `unusable` — so every such slot silently degrades to solo. That is a configured declaration that is broken, hence **`attention`**, not an offer; its text names the state, its reason and how many configured slots are affected across the
|
|
23
|
+
**The `executor-vehicle` item (the carrier the project already CONFIGURED — beside the `agents` offer, never the same item).** It fires on ONE pair of facts: a slot in `docs/ai/orchestration.json` names `subagent` while the executor vehicle (`.claude/agents/executor.md`) is `missing` or `unusable` — so every such slot silently degrades to solo. That is a configured declaration that is broken, hence **`attention`**, not an offer; its text names the state, its reason and how many configured slots are affected across the six activities (`plan-authoring`, `plan-execution`, `routine`, `feedback-triage`, `epic`, `task`), covering the subagent-capable slots `plan-authoring.author`, `plan-authoring.fold`, `plan-execution.execute`, `routine.carrier`, `epic.author`, `task.author` and `task.execute`. **`placed` and `customized` render NOTHING** (a working vehicle is not a recommendation), a config naming no `subagent` slot renders nothing, and a config the validated reader refuses is a stated **skip**, never an item computed over a shape nothing accepted. It is deliberately DISTINCT from its two neighbours, neither of which can observe this state: the `agents` offer converges the moment nothing is left to PLACE — which a present-but-unusable executor also satisfies — and the review-recipe probe skips a slot configured `subagent` by construction. Its apply is the agents writer's own `cheap-agents.mjs --apply` (the same writer the `agents` item previews; here the rendered line IS the mutation, so read the item's state before confirming), and its `recipe:` line is the hidden-mode reconcile follow-up (`hide-footprint --reconcile`), for a hidden deployment only. Honest limit on convergence: the apply places an ABSENT vehicle, so it clears `missing`; it STOPs on a symlink, so on `unusable` the item's apply line carries a `HAND-APPLY:` precondition naming each refusal the advisor observes; an executor whose frontmatter is invalid is re-derived by the apply itself. Risk profile: writes under `.claude/agents/` only — the executor's body re-derived from `docs/ai/vehicles.json`, every other vehicle create-only — never `settings.json`, never a commit.
|
|
24
24
|
|
|
25
25
|
**Per-item posture notes (the consent moment — surface BEFORE running or handing over the apply):**
|
|
26
26
|
|
|
@@ -15,13 +15,13 @@ mapping their wording onto them is your job, not a shipped phrase list.
|
|
|
15
15
|
| "both review" | `--set <activity>.review=council` | **disambiguate**: which activity? If both, pass `--set plan-authoring.review=council --set plan-execution.review=council`. |
|
|
16
16
|
| "one reviewer" | `--set <activity>.review=reviewed` | per the named activity, else ask |
|
|
17
17
|
| "delegate execution" | `--set plan-execution.execute=delegated` | execution only (a **bridge** runs the change) |
|
|
18
|
-
| "let a subagent do it" | `--set <activity>.<slot>=subagent` | **disambiguate**: which work? `--set plan-execution.execute=subagent` (a slice of the change), `--set plan-authoring.author=subagent` (a plan/contract brief), `--set plan-authoring.fold=subagent` (the round's findings and dispositions), `--set routine.carrier=subagent` (a bounded chore) |
|
|
18
|
+
| "let a subagent do it" | `--set <activity>.<slot>=subagent` | **disambiguate**: which work? `--set plan-execution.execute=subagent` (a slice of the change), `--set plan-authoring.author=subagent` (a plan/contract brief), `--set plan-authoring.fold=subagent` (the round's findings and dispositions), `--set routine.carrier=subagent` (a bounded chore), `--set epic.author=subagent` (an epic brief), `--set task.author=subagent` (a task brief), `--set task.execute=subagent` (one stamped task brief) |
|
|
19
19
|
| "one slice at a time" | `--set routine.parallel=off` | `routine` only — `parallel` is a **flag**, not a recipe |
|
|
20
20
|
| "revert / do it myself" | `--unset <activity>.<slot>` | the named slot → its computed default |
|
|
21
21
|
|
|
22
22
|
Run **`node ${CLAUDE_SKILL_DIR}/tools/set-recipe.mjs [--set <activity>.<slot>=<value>]… [--unset <activity>.<slot>]… [--write] [--json]`**:
|
|
23
23
|
|
|
24
|
-
1. **Grammar — always fully-qualified `<activity>.<slot>`** (the kit never guesses the activity; a bare `review=council` is rejected). The writer takes **every slot of the
|
|
24
|
+
1. **Grammar — always fully-qualified `<activity>.<slot>`** (the kit never guesses the activity; a bare `review=council` is rejected). The writer takes **every slot of the six activities**, and `--help` prints the registry (`tools/carriers.mjs`) as two blocks:
|
|
25
25
|
|
|
26
26
|
```
|
|
27
27
|
Activities and their slots:
|
|
@@ -29,6 +29,8 @@ Run **`node ${CLAUDE_SKILL_DIR}/tools/set-recipe.mjs [--set <activity>.<slot>=<v
|
|
|
29
29
|
plan-execution → execute, review
|
|
30
30
|
routine → carrier, parallel
|
|
31
31
|
feedback-triage → review
|
|
32
|
+
epic → author, review
|
|
33
|
+
task → author, execute
|
|
32
34
|
|
|
33
35
|
Accepted values per slot type:
|
|
34
36
|
review slots accept solo | reviewed | council
|
|
@@ -13,7 +13,7 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/family-registry.mjs --json [--dir <project>]
|
|
|
13
13
|
> **Status reads `refresh`; the shared version block + the bootstrap/upgrade footers stay `notes`-based (unchanged this release).** `${CLAUDE_SKILL_DIR}/references/modes/status.md` has its OWN status-only render (above), keyed on `installed[].refresh.behind` / `refresh.recommend`. The shared **version block** (under *The version block + welcome mat* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`) 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`.
|
|
14
14
|
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. When `project.adrLayout` is **`old`** or **`old-unrotated`**, add a plain-language note that the project still uses an **older ADR layout** and should run the opt-in **`/agent-workflow-kit migrate-adr-store`** to move to the one-file-per-ADR store (preview first; it never commits) — the note is the SAME for both, they differ only in how the older layout was detected (`old` = a retired archive file is still on disk; `old-unrotated` = the project's deployed rotation script predates the store); `migrated` / `none` need no note. Then **one `specs` line, always** (from `project.specs` — the feature-spec layer's adoption state, judged from the store alone): `not adopted` (no `docs/ai/specs/` — the layer was never seeded), `adopting (N draft)` (a store with no live contract yet), `adopted (N live, M draft)`, or `could not be read — <reason>` (the store or a document in it could not be observed; never counted as any of the other three). A recorded decline (`project.specs.declined`) appends ` — declined` to the first two. The internal tokens are `not-adopted` / `adopting` / `adopted` / `unreadable`; render the plain phrases above, never the tokens. An envelope without the field says the installed kit predates it — say so rather than inventing a state.
|
|
15
15
|
3. **Settings (`--dir`, one line each)** (from `project.settings`):
|
|
16
|
-
- **recipes** — the effective recipe per slot, **one line per slot** over the
|
|
16
|
+
- **recipes** — the effective recipe per slot, **one line per slot** over the six activities (`plan-authoring.author` / `.fold` / `.review`, `plan-execution.execute` / `.review`, `routine.carrier` / `.parallel`, `feedback-triage.review`, `epic.author` / `.review`, `task.author` / `.execute`); each line also carries **where the value came from** (`source` — the project's config, an explicit override, or a computed default) and, when the resolved recipe is not the one that was asked for, **what it degraded from** (`degradedFrom`). Say both in plain words (never the field names): an effective recipe alone cannot tell a deliberate choice from a default, nor a degrade from a config that really names the resolved recipe — and a slot showing `solo` after a degrade from `subagent` is exactly the case the **subagents** line below explains. Detail → `/agent-workflow-kit procedures` / `recipes`; a `recipes.detectError` → say the backends couldn't be checked, so bridge-backed recipes floored at solo; the executor vehicle is unaffected.
|
|
17
17
|
- **attribution** — `includeCoAuthoredBy` effective; call out a **local override** only when `local` is non-null **and** differs from `project` (a `null` `local` means the key is absent there, so the project value stands — that is not an override).
|
|
18
18
|
- **velocity** — the effective `permissions.defaultMode` + whether an allowlist is seeded (detail → `/agent-workflow-kit velocity`).
|
|
19
19
|
- **subagents** — how many of the kit's subagent vehicles are placed (`agents.placed` of `agents.bundled`; zero placed → the optional `/agent-workflow-kit agents` opt-in), then the **split the line always states separately**: the **read-only vehicles** (`agents.readOnly` — four; none of them grants a shell, three ride a cheap model for mechanical work and one is a read-only review lens) and the **ONE full-tool `executor`**, whose own state is `agents.executor`: *placed* / *customized* (both dispatchable) / *unusable* (`agents.executorReason` carries the reason — say it) / *missing*. That state is what decides whether a slot configured `subagent` can ride it: on **unusable** or **missing** every such slot runs solo instead, so surface it plainly beside the recipes lines and point at `/agent-workflow-kit agents` to place it. It is a claim about the FILE, never about the host. An envelope with no executor state says the installed kit predates the field — say so rather than inventing a state.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
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.
|
|
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. Six activities are configured independently, and so is each slot within them: 'plan-authoring' (slots author, fold, review), 'plan-execution' (slots execute, review), 'routine' (slots carrier, parallel), 'feedback-triage' (slot review), 'epic' (slots author, review) and 'task' (slots author, execute). 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), or an explicit roster array such as [\"codex-review\", \"agy-review\", \"review-lens\"] in hand-edit form; an 'execute' slot accepts solo | delegated | subagent (you implement / a backend runs a bounded sub-task / a full-tool frontier subagent carries a bounded slice you verify); the carrier slots 'plan-authoring.author', 'plan-authoring.fold', 'routine.carrier' and 'epic.author' accept solo | subagent, and the task slots 'task.author' and 'task.execute' take the execute values. 'routine.parallel' is a flag rather than a recipe: it accepts on | off and decides whether file-disjoint subagent slices dispatch concurrently. Every slot seeded below is 'solo' — no execution backend required. A slot the seed leaves silent takes the computed default stated further down: 'feedback-triage.review' is reviewed as soon as a review backend is ready (solo until then), and so is 'epic.review'; 'plan-authoring.author', 'plan-authoring.fold', 'routine.carrier', 'epic.author', 'task.author' and 'task.execute' stay 'solo', and 'routine.parallel' stays 'on'. 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. 'subagent' needs the executor vehicle placed in this project — the composition root's `agents` writer places it; without it the slot resolves to solo with the reason stated. Remove a slot's line, or a whole activity block (or run `set-recipe --unset <activity>.<slot>`), to fall back to the computed default: reviewed when a review backend is ready and otherwise solo for a review slot, solo for author, fold, execute and carrier, on for parallel. Run the read-only procedures advisor to see an activity's steps plus the recipe resolved for your environment. Strict JSON — no comments.",
|
|
3
3
|
"plan-authoring": {
|
|
4
4
|
"review": "solo"
|
|
5
5
|
},
|
package/tools/carriers.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// moves. The carrier half declares the `subagent` recipe, appends the executor vehicle to a
|
|
4
4
|
// readiness array as the single provider of the `carry` role, words the degrade a missing or
|
|
5
5
|
// unusable vehicle causes, and holds the dispatch-form wording every render prints (one source, a
|
|
6
|
-
// red line where it is a red line). Governing contract: docs/ai/specs/kit/carriers.md.
|
|
6
|
+
// red line where it is a red line). Governing contract: docs/ai/specs/kit/carriers/index.md.
|
|
7
7
|
// Leaf — imports only the direct-run guard (recipes.mjs imports THIS), no fs, nothing on import.
|
|
8
8
|
import { refuseDirectRun } from './direct-run.mjs';
|
|
9
9
|
|
|
@@ -16,6 +16,8 @@ export const ACTIVITIES = {
|
|
|
16
16
|
'plan-execution': { slots: { execute: 'execute', review: 'review' }, policy: true },
|
|
17
17
|
routine: { slots: { carrier: 'carrier', parallel: 'switch' }, policy: false },
|
|
18
18
|
'feedback-triage': { slots: { review: 'review' }, policy: false },
|
|
19
|
+
epic: { slots: { author: 'carrier', review: 'review' }, policy: false },
|
|
20
|
+
task: { slots: { author: 'execute', execute: 'execute' }, policy: false },
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
export const POLICY_ACTIVITIES = Object.fromEntries(
|
|
@@ -109,6 +111,9 @@ export const SLICE_BY_SLOT = {
|
|
|
109
111
|
'plan-authoring.fold': "a slice is the round's findings with their dispositions; the subagent edits the plan or the contract in place and returns; the orchestrator runs the self-consistency read itself",
|
|
110
112
|
'plan-execution.execute': 'a slice is a set of file-disjoint ledger rows; wording is copied verbatim where wording is a red line',
|
|
111
113
|
'routine.carrier': "a slice is a bounded mechanical task; a read-only one (a sweep, gate triage) rides its placed read-only vehicle, or is carried solo with a stated reason when that vehicle is absent; a write-capable one (a regeneration, a fixture build) rides the executor; the changelog stays the orchestrator's",
|
|
114
|
+
'epic.author': 'a slice is a brief naming the intent, the value, the non-goals and the stories in order; the subagent drafts the epic file from it, and the orchestrator runs the shape check on the draft as its own',
|
|
115
|
+
'task.author': 'a slice is one ledger row of the plan with the contracts it reads; the subagent writes the task brief from it, and the orchestrator stamps and checks the brief itself',
|
|
116
|
+
'task.execute': 'a slice is one stamped brief; the subagent runs it inside the Files the brief names and reports the paths it changed, and the orchestrator runs the Acceptance commands itself',
|
|
112
117
|
};
|
|
113
118
|
|
|
114
119
|
export const VEHICLE_STATE_TOKEN = '<state>';
|