@sabaiway/agent-workflow-kit 14.2.0 → 14.4.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 +58 -0
- package/README.md +2 -2
- 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/grounding.md +1 -1
- package/references/modes/procedures.md +7 -5
- package/references/modes/recipes.md +2 -2
- package/references/modes/recommendations.md +1 -1
- package/references/modes/review-state.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/inject-methodology.mjs +6 -4
- package/tools/orchestration-readme.mjs +10 -2
- package/tools/procedures.mjs +17 -18
- package/tools/review-state.mjs +11 -11
- package/tools/task-brief.mjs +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,64 @@ 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.4.0 — a delegated task engages the held session: `review-state --check` reads a configured `task.execute`, the fold lane follows a resolved one, and `task-brief check` admits a lone suite (AD-148)
|
|
8
|
+
|
|
9
|
+
**A task set to `delegated` is now gated and advised on its own.** In 14.3.0 the held-session gate and the fold lane
|
|
10
|
+
keyed only on `plan-execution.execute`, so a delegated task was covered only when the rows not carried as tasks were
|
|
11
|
+
delegated as well. 14.4.0 reads the task's own slot. Under a config that leaves `task.execute` unset or not
|
|
12
|
+
delegated, the gate and the lane behave exactly as before, except that `procedures task --override execute=delegated`
|
|
13
|
+
now renders the lane when the override resolves to delegated. Story S10 of the epic `EPICS-STORIES-TASKS-AS-THE-UNIT-OF-WORK`; contracts
|
|
14
|
+
`docs/ai/specs/kit/carriers/` revision 7, `held-session` revision 4, `checkpoint/` revision 4.
|
|
15
|
+
|
|
16
|
+
- **The gate (`tools/review-state.mjs`).** `--check` audits the delegation ledger when the configured
|
|
17
|
+
`plan-execution.execute` or the configured `task.execute` is `delegated`, each read on its own: a solo or subagent
|
|
18
|
+
value in one slot never masks the other. It reads the configuration, never a degraded recipe or a per-run override.
|
|
19
|
+
The judge, the refusal and the report line are unchanged. The tool header, `--help` and `modes/review-state.md` say so.
|
|
20
|
+
- **The fold lane (`tools/procedures.mjs`).** `procedures plan-execution` renders the lane once when its own `execute`
|
|
21
|
+
or `task.execute` resolves to delegated; a per-run `--override` moves only the rendered activity's own slot.
|
|
22
|
+
`procedures task` renders it when `task.execute` resolves to delegated. `task.author` never counts, and `foldLane`
|
|
23
|
+
stays `[]` for every other activity. The lane's lines and caveats are unchanged; `modes/procedures.md` says so.
|
|
24
|
+
- **A lone suite is briefable (`tools/task-brief.mjs`).** A slice with no `impl` line may carry the co-located test of
|
|
25
|
+
the row's path or of one of its sweep expansions. A slice with `impl` lines still admits only tests of its own `impl`
|
|
26
|
+
paths, and a test of any other path still refuses `row`.
|
|
27
|
+
- **Tests.** `review-state-task-execute.test.mjs` (new; carriers S19), `procedures-fold-lane.test.mjs` (S20) and
|
|
28
|
+
`task-brief.test.mjs` (checkpoint S11). The pinned cells of `review-state-held-session.test.mjs` pass unedited.
|
|
29
|
+
|
|
30
|
+
Published with engine 5.9.0, whose `task` step 5 states the same rule.
|
|
31
|
+
|
|
32
|
+
## 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)
|
|
33
|
+
|
|
34
|
+
**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
|
|
35
|
+
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
|
|
36
|
+
registry, so `set-recipe`, `procedures`, `recipes`, `status` and the config validator all accept them with no second
|
|
37
|
+
list. A config without the new rows reads and resolves exactly as before. Story S7 of the epic
|
|
38
|
+
`EPICS-STORIES-TASKS-AS-THE-UNIT-OF-WORK`; contract `docs/ai/specs/kit/carriers/` revision 6 (part `activity-tiers`).
|
|
39
|
+
|
|
40
|
+
- **Two registry rows (`tools/carriers.mjs`).** `epic` has `author` (`solo | subagent`) and `review`
|
|
41
|
+
(`solo | reviewed | council`); `task` has `author` and `execute`, both `solo | delegated | subagent`. Neither row
|
|
42
|
+
carries an autonomy policy. A silent `epic.review` is reviewed as soon as a review backend is ready (solo until then);
|
|
43
|
+
the other three slots default to solo. `SLICE_BY_SLOT` gains the subagent slice sentence of `epic.author`,
|
|
44
|
+
`task.author` and `task.execute`.
|
|
45
|
+
- **The epic render (`tools/procedures.mjs`).** When `epic.review` is a shorthand recipe that dispatches agy, the
|
|
46
|
+
grounding pre-step carries no `--plan` and the review line is `agy-review plan <brief-file>`: plan mode over the
|
|
47
|
+
rendered epic brief, never the code form.
|
|
48
|
+
- **The orchestration note refreshes (`tools/orchestration-readme.mjs`).** The `_README` that 14.2.0 wrote is now a
|
|
49
|
+
known prior, and the current note names six activities and the new slots' values and defaults, so a deployed
|
|
50
|
+
`docs/ai/orchestration.json` that still carries that note refreshes on its next write. Both seed templates carry the new note.
|
|
51
|
+
- **The methodology pointer (`tools/inject-methodology.mjs`).** The four-activity fragment is a known prior and
|
|
52
|
+
refreshes to six. A customized fragment kept as is gets an upgrade note naming the current canon unless it carries
|
|
53
|
+
the six-activity token `feedback-triage, epic, task`.
|
|
54
|
+
- **Copy.** Every restatement of the activity list and of the subagent-capable slots names the two rows: the README,
|
|
55
|
+
and the `agents`, `procedures`, `recipes`, `recommendations`, `set-recipe` and `status` mode docs.
|
|
56
|
+
- **Tests.** Scenario cases S11–S18 of the carriers contract in `carriers.test.mjs`, `orchestration-config.test.mjs`,
|
|
57
|
+
`set-recipe.test.mjs`, `family-registry.test.mjs`, `recipes-shorthand.test.mjs`, `procedures-roster.test.mjs` and
|
|
58
|
+
`inject-methodology.test.mjs` (S17 is in the engine's canon test).
|
|
59
|
+
- **Stated limit.** The held-session gate of `review-state` and the fold lane of `procedures` still key on
|
|
60
|
+
`plan-execution.execute`, so they cover a delegated task only when that slot is delegated as well; the engine canon
|
|
61
|
+
says so.
|
|
62
|
+
|
|
63
|
+
Needs engine 5.8.0: `procedures epic` and `procedures task` exit 1 against an engine without the two sections.
|
|
64
|
+
|
|
7
65
|
## 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)
|
|
8
66
|
|
|
9
67
|
**Tasks can now run side by side.** In 14.1.0 a delegation thread could name its task, but it was still measured over
|
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. |
|
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.4.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.4.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
|
|
|
@@ -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,24 +4,26 @@
|
|
|
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
|
-
**Fold lane (an execute slot resolved to `delegated`).**
|
|
26
|
+
**Fold lane (an execute slot the activity reads resolved to `delegated`).** `procedures plan-execution` reads `plan-execution.execute` and `task.execute`, `procedures task` reads `task.execute` alone, and `task.author` never counts; a per-run `--override` moves only the rendered activity's own slot. The lane renders once, immediately after the rendered activity's `execute` slot block (after its driving contract when that slot itself resolves to `delegated`), as `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 `[]` for every other activity and whenever no slot the activity reads resolves to `delegated`. The sidecar is never read.
|
|
25
27
|
|
|
26
28
|
**`routine`'s `parallel` switch renders against the EFFECTIVE carrier.** The flag always renders with its source (`parallel: on` / `parallel: off`); the concurrency claim — *file-disjoint slices dispatch concurrently* — renders **only** while the resolved `carrier` is `subagent`. Under a `solo` carrier the line states its own inertness instead, `(no effect while the carrier is solo)`: a switch never degrades, so the flag keeps the value you set and the render simply stops promising a concurrency nothing can perform. That makes four cells (`on`/`off` x `subagent`/`solo`), and only the `subagent`+`on` cell claims concurrency.
|
|
27
29
|
|
|
@@ -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
|
|
|
@@ -7,7 +7,7 @@ Read-only **review-receipt checker** (AD-038) — it makes *"reviewed ≠ shippe
|
|
|
7
7
|
Run `node ${CLAUDE_SKILL_DIR}/tools/review-state.mjs [--check] [--json]`:
|
|
8
8
|
|
|
9
9
|
1. Plain run → the human report: resolved recipe + source, plan-in-flight, tree fingerprint, the `held session: <id> — <n> fold(s) rode it` / `none` / substitution line when configured delegated execution arms it (with a task `code` thread of backend `codex` in the commit epoch and no unresolved substitution, `held sessions: <k> chain(s) — <label>: <id> (<n>) · …` is printed instead, one entry per chain, labelled by its brief or `untasked`, with `none` for a chain with no held session), and per-backend receipt state (current / stale / ungrounded / probe / rejected / missing) with verdict + grounding + timestamp.
|
|
10
|
-
2. **`--check`** → the gate exit code. Before the review-recipe early return, a configured `plan-execution.execute
|
|
10
|
+
2. **`--check`** → the gate exit code. Before the review-recipe early return, a configured `plan-execution.execute` or `task.execute` of `delegated` (each read on its own) with a plan in flight and a dirty, fingerprintable tree audits the delegation ledger and refuses a substituted held session; an absent ledger is inert, while an unreadable, malformed, foreign, audit-refused ledger or failed HEAD read fails closed with its own reason. For a head-base thread, the accepted-replacement escape is a `codex-exec` degrade at the substituted return's tree, standing after every later fold, never the review receipt id `codex`. A checkpoint-based thread's substitution closes only by its own ledger `degrade` (which also withdraws the expectation, so the next fold establishes HELD) — no core-evidence degrade lifts it, and the report's recovery hint says so. The remaining **normative exit contract lives in the tool header** (the single home — do not re-enumerate it elsewhere): exit 0 for a CONFIGURED solo recipe (after the held-session arm above) (a computed readiness-degrade NEVER silently becomes solo — it needs the explicit degrade record below), no plan in flight (the `docs/plans` naming convention: `queue.md` and `EXECUTE-`/`FEEDBACK-`/`TASK-`-prefixed or `PROMPT`/`prompt`/`handoff`-carrying names are scratch), a clean tree, a cwd where git ITSELF answers not-a-repository under both discoveries (the ONLY non-work-tree location that passes — `error`, `redirected`, `no-work-tree` and `env-only` refuse by their state name once a receipt could be required), or every recipe-named backend SATISFIED for the current tree. **A clean-tree PASS under a NON-SOLO review obligation is never silent about a latent arm:** when a `reviewed` or `council` recipe is configured, it NAMES every plan in flight and states that this gate arms as soon as the tree is dirty — the condition is discoverable BEFORE it blocks, instead of surfacing at the worst moment (a pending commit, or the landing of a feature worktree when main first turns dirty). Nothing is announced under a configured `solo` recipe or a not-a-repository cwd, where the gate can never arm. **Satisfaction is ship-class-only on the LATEST NORMAL receipt (D3(b)):** per backend, the latest probe-free current-fingerprint receipt is selected FIRST and THEN verdict-checked — only the recognized ship-class vocabulary (`ship` / `ship with nits`) satisfies; a recognized NEGATIVE (`revise` / `rethink` / `rework`) is an authoritative VETO (an earlier ship never survives a later revise); an UNRECOGNIZED verdict (e.g. `unknown` from a dead run) fails CLOSED unconditionally — a later `unknown` never lets an earlier SHIP stand, and a fresh normal re-run supersedes it. **The ONLY review-backend escape is an explicit degrade RECORD** (`core-evidence.mjs degrade --backend <name> --reason "…"`, fingerprint-bound to the current tree) — and never all backends: ≥1 non-degraded ship-class receipt is required whenever ≥1 backend is configured; a malformed evidence store denies the escape fail-closed but never fails an independently-satisfied tree. Exit 1 otherwise — missing, **stale** (every edit the payload can see moves the fingerprint, and no more), ungrounded, vetoed, or unrecognized. Plan/diff receipts and continuations (`agy-review --continue`) are **informational-only**: after a fold, only a **fresh grounded re-run** (`codex-review code`; `agy-review code --facts @f`) restores green. **Probe receipts never attest either:** a `CODEX_PROBE=1` / `AGY_PROBE=1` review runs with the frontier-model/max-effort guard OFF, so the wrapper stamps `probe:true` and this checker excludes it — per receipt, so a real review at the same fingerprint still satisfies. **Silence is not a declaration:** a malformed *or* absent probe marker is rejected fail-closed and stated in the check line. Honest bound: receipts are **not authenticated** (a forger could write `probe:false` as easily as any other field) — like the rest of the receipt this is a self-discipline mechanism, not a security boundary.
|
|
11
11
|
3. **Wire it as a gate by hand OR via the explicit-consent init preview — never without consent (AD-021/D9).** The candidate line for your own `docs/ai/gates.json`: `{ "id": "review-state", "title": "Review receipts current for the uncommitted tree", "cmd": "node <path-to-this-skill>/tools/review-state.mjs --check" }` — with the path your project actually reaches the kit by, QUOTED so a path with spaces survives, executable from the project root. The consent-gated gates-init preview — `node ${CLAUDE_SKILL_DIR}/tools/gates-init.mjs --cwd <project>` (dry-run: it prints the derived entries and writes NOTHING; `--apply --only review-state` writes exactly this one on your explicit yes) — offers exactly this entry, path resolved and quoted, ONLY when your `docs/ai/orchestration.json` declares `reviewed`/`council` on `plan-execution.review` (the slot this checker enforces). The full consent-fill contract is in `${CLAUDE_SKILL_DIR}/references/modes/gates.md`. Once declared, the opt-in `${CLAUDE_SKILL_DIR}/references/modes/hook.md` auto-approves it like any other declared gate — and `run-gates --final` requires this check among its canonical core gates.
|
|
12
12
|
4. **`--await [--timeout <s>]`** (BUGFREE-3 / AD-049) → BLOCK until every recipe-named backend is SATISFIED for the current tree (i.e. until `--check` would PASS), or the bounded timeout elapses (a loud exit 1; default 900s). Run it after dispatching the review bridges to WAIT for their receipts to land instead of hand-polling a pid: the durable completion signal is the **receipt**, never a process event (a harness "completed" notification fires early; a bridge's output late-flushes). It inherits the `--check` decision whole — a backend with a current-tree degrade RECORD stops being waited on (the shared decideCheck), so you never hand-`--await` around a known degrade. A held-session refusal and an **AUTHORITATIVE veto terminate the wait loudly BEFORE the deadline**: neither can be moved by waiting; only the held-session retry/degrade lane or a fresh review can move its corresponding refusal. Still read-only (it re-reads the receipts + the evidence store); solo / no-plan / clean-tree resolve instantly. For waiting on **one dispatch's arrival** (never obligation satisfaction) use the receipt-arrival deadline runner, `${CLAUDE_SKILL_DIR}/references/modes/receipt-deadline.md`.
|
|
13
13
|
|
|
@@ -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>';
|
|
@@ -90,6 +90,8 @@ export const KNOWN_PRIOR_METHODOLOGY_SLOT = [
|
|
|
90
90
|
'> **Workflow methodology** — plan → execute → review. Plans are ephemeral `docs/plans/*.md` (gitignored, **never committed**); every Plan ends with a mandatory **Phase: Cleanup**; series order lives in `docs/plans/queue.md`. The plan shape, its caps and lifecycle live in the project\'s **planning skill** (it overrides the generic `writing-plans`); summary in `docs/ai/agent_rules.md` §5. Named activities (plan-authoring, plan-execution) have procedures — see `/agent-workflow-kit procedures <activity>` for the steps + resolved recipe. **Communication:** user-facing messages deliver the artifact inline (paste the prompt / diff / command — never "see §X" as a substitute), lead with the result, show exactly what was asked, and never read as mockery (a large artifact: a real summary inline + a link).',
|
|
91
91
|
// engine 4.6.0 — the three-activity pointer, before feedback-triage joined the named activities.
|
|
92
92
|
'> **Workflow methodology** — plan → execute → review. Plans are ephemeral `docs/plans/*.md` (gitignored, **never committed**); every Plan ends with a mandatory **Phase: Cleanup**; series order lives in `docs/plans/queue.md`. The plan shape, its caps and lifecycle live in the project\'s **planning skill** (it overrides the generic `writing-plans`); summary in `docs/ai/agent_rules.md` §5. Named activities (plan-authoring, plan-execution, routine) have procedures — see `/agent-workflow-kit procedures <activity>` for the steps + resolved recipe. **Communication:** user-facing messages deliver the artifact inline (paste the prompt / diff / command — never "see §X" as a substitute), lead with the result, show exactly what was asked, and never read as mockery (a large artifact: a real summary inline + a link).',
|
|
93
|
+
// engine 5.7.0 — the four-activity pointer, before epic and task joined the named activities.
|
|
94
|
+
'> **Workflow methodology** — plan → execute → review. Plans are ephemeral `docs/plans/*.md` (gitignored, **never committed**); every Plan ends with a mandatory **Phase: Cleanup**; series order lives in `docs/plans/queue.md`. The plan shape, its caps and lifecycle live in the project\'s **planning skill** (it overrides the generic `writing-plans`); summary in `docs/ai/agent_rules.md` §5. Named activities (plan-authoring, plan-execution, routine, feedback-triage) have procedures — see `/agent-workflow-kit procedures <activity>` for the steps + resolved recipe. **Communication:** user-facing messages deliver the artifact inline (paste the prompt / diff / command — never "see §X" as a substitute), lead with the result, show exactly what was asked, and never read as mockery (a large artifact: a real summary inline + a link).',
|
|
93
95
|
];
|
|
94
96
|
export const KNOWN_PRIOR_ORCH_SLOT = [
|
|
95
97
|
// v1.3.0 — pre-read-at-start orchestration pointer (recipes vocabulary, no orchestration.json clause).
|
|
@@ -113,9 +115,9 @@ export const METHODOLOGY_DESCRIPTOR = {
|
|
|
113
115
|
markerName: 'methodology',
|
|
114
116
|
anchorLabel: 'methodology anchor (the "Read it before any code change." Session-Protocols line)',
|
|
115
117
|
knownPriorCanonicals: KNOWN_PRIOR_METHODOLOGY_SLOT,
|
|
116
|
-
upgradeSignature: '
|
|
118
|
+
upgradeSignature: 'feedback-triage, epic, task',
|
|
117
119
|
upgradeAdvice:
|
|
118
|
-
'the workflow-methodology pointer predates the communication-contract clause (deliver the artifact inline, lead with the result) — refresh it to the current canon, or add
|
|
120
|
+
'the workflow-methodology pointer predates the current canon — six named activities (plan-authoring, plan-execution, routine, feedback-triage, epic, task) with the communication-contract clause (deliver the artifact inline, lead with the result) — refresh it to the current canon, or add what it lacks by hand; the contract still applies.',
|
|
119
121
|
};
|
|
120
122
|
export const ORCHESTRATION_DESCRIPTOR = {
|
|
121
123
|
startMarker: ORCH_START_MARKER,
|
|
@@ -443,8 +445,8 @@ export const runCli = async (argv, deps = {}) => {
|
|
|
443
445
|
'present-filled': 'workflow-methodology pointer already present',
|
|
444
446
|
}[methResult.status];
|
|
445
447
|
// Read-only upgrade advisories for a CUSTOMIZED methodology pointer that reconcile preserved verbatim
|
|
446
|
-
// (a refreshed/filled/inserted slot already carries the current canon, so it gets none): the AD-019
|
|
447
|
-
//
|
|
448
|
+
// (a refreshed/filled/inserted slot already carries the current canon, so it gets none): the AD-019 procedures route
|
|
449
|
+
// AND the current-canon hint, keyed on the six-activity token (it names the §1.9 clause too). No mutation — notes only.
|
|
448
450
|
const notes = [];
|
|
449
451
|
if (methResult.status === 'present-filled') {
|
|
450
452
|
const p = methodologyProceduresHint(afterMeth); if (p) notes.push(p);
|
|
@@ -60,12 +60,20 @@ const FOUR_README = FOLD_README.replace(
|
|
|
60
60
|
"Four 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) and 'feedback-triage' (slot review).",
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
const FOUR_SEED_README = FOUR_README.replace(
|
|
64
64
|
"The default below is 'solo' for every recipe and carrier slot, and 'on' for the parallel switch — no execution backend required.",
|
|
65
65
|
"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); 'plan-authoring.author', 'plan-authoring.fold' and 'routine.carrier' stay 'solo', and 'routine.parallel' stays 'on'.",
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
-
export const
|
|
68
|
+
export const CANON_README = FOUR_SEED_README
|
|
69
|
+
.replace("Four 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) and 'feedback-triage' (slot review).",
|
|
70
|
+
"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).")
|
|
71
|
+
.replace("the carrier slots 'plan-authoring.author', 'plan-authoring.fold' and 'routine.carrier' accept solo | subagent.",
|
|
72
|
+
"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.")
|
|
73
|
+
.replace("'feedback-triage.review' is reviewed as soon as a review backend is ready (solo until then); 'plan-authoring.author', 'plan-authoring.fold' and 'routine.carrier' stay 'solo',",
|
|
74
|
+
"'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',");
|
|
75
|
+
|
|
76
|
+
export const KNOWN_PRIOR_README = Object.freeze([V1_README, V2_README, V3_README, ROSTER_README, FOLD_README, FOUR_README, FOUR_SEED_README]);
|
|
69
77
|
|
|
70
78
|
export const refreshReadme = (config) => {
|
|
71
79
|
if (config == null || typeof config !== 'object' || Array.isArray(config)) return { config, changed: false };
|
package/tools/procedures.mjs
CHANGED
|
@@ -276,6 +276,7 @@ export const REVIEW_ROUNDS_TOOL = join(dirname(fileURLToPath(import.meta.url)),
|
|
|
276
276
|
export const REPO_SEARCH_TOOL = join(dirname(fileURLToPath(import.meta.url)), 'repo-search.mjs');
|
|
277
277
|
export const FEEDBACK_RECORD_TOOL = join(dirname(fileURLToPath(import.meta.url)), 'feedback-record-cli.mjs');
|
|
278
278
|
const FEEDBACK_TRIAGE = 'feedback-triage';
|
|
279
|
+
const EPIC = 'epic';
|
|
279
280
|
const GROUNDING_FACTS_OUT = '/tmp/review-facts.md';
|
|
280
281
|
const MINTS_RECEIPT = Object.freeze({ mintsReceipt: true });
|
|
281
282
|
const FEEDBACK_BRIDGE_LINES = Object.freeze({
|
|
@@ -380,25 +381,28 @@ const groundingPreStepAdvice = (activity, slots, plans) => {
|
|
|
380
381
|
if (activity === FEEDBACK_TRIAGE) return [];
|
|
381
382
|
if (!slots.some((s) => (s.backends ?? []).includes('agy-review'))) return [];
|
|
382
383
|
const operand = populatedPlan(plans);
|
|
383
|
-
const planArg = operand === null ? '--plan <path>' :
|
|
384
|
+
const planArg = activity === EPIC ? '' : operand === null ? ' --plan <path>' : ` --plan ${operand}`;
|
|
384
385
|
const reviewOperand = populatedPlan(plans, MINTS_RECEIPT);
|
|
385
386
|
// plan-authoring reviews the plan FILE — a plain name in flight renders the review command populated;
|
|
386
387
|
// the renderability and receipt-carriability fallbacks are the only placeholders a known path produces.
|
|
387
388
|
const reviewForm =
|
|
388
|
-
activity ===
|
|
389
|
-
?
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
389
|
+
activity === EPIC
|
|
390
|
+
? 'agy-review plan <brief-file>'
|
|
391
|
+
: activity === 'plan-authoring'
|
|
392
|
+
? reviewOperand === null
|
|
393
|
+
? 'agy-review plan <plan-file>'
|
|
394
|
+
: `agy-review plan ${reviewOperand}`
|
|
395
|
+
: 'agy-review code';
|
|
393
396
|
// `run:`/`then:` prefixes keep these POPULATED command lines machine-distinguishable from the
|
|
394
397
|
// verbatim contract DESCRIPTORS above (the descriptor drift guard set-equals bare wrapper lines).
|
|
395
398
|
// The TOOL path stays double-quoted (the bridge tier seeds that exact byte-form); the plan operand
|
|
396
399
|
// rides shellQuoteArg — bare when safe, single-quoted otherwise.
|
|
397
400
|
const lines = [
|
|
398
401
|
'Grounding pre-step (agy is dispatched — assemble the verified facts BEFORE the review; grounding.mjs slices verbatim, judgment additions stay yours):',
|
|
399
|
-
` run: node "${GROUNDING_TOOL}" --constraints --autonomy
|
|
402
|
+
` run: node "${GROUNDING_TOOL}" --constraints --autonomy${planArg} --out ${GROUNDING_FACTS_OUT}`,
|
|
400
403
|
` then: ${reviewForm} --facts @${GROUNDING_FACTS_OUT}`,
|
|
401
404
|
];
|
|
405
|
+
if (activity === EPIC) return lines;
|
|
402
406
|
const fellBack = [operand === null ? '--plan' : null, activity === 'plan-authoring' && reviewOperand === null ? 'agy-review plan' : null].filter(Boolean);
|
|
403
407
|
lines.push(...planDiscoveryCaveat(
|
|
404
408
|
plans,
|
|
@@ -625,17 +629,10 @@ const contractLines = ({ cmd, contract, settings }) => {
|
|
|
625
629
|
return lines;
|
|
626
630
|
};
|
|
627
631
|
|
|
628
|
-
const foldLaneAdvice = ({
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
env,
|
|
633
|
-
resolveStore,
|
|
634
|
-
readStore,
|
|
635
|
-
audit,
|
|
636
|
-
readHead,
|
|
637
|
-
}) => {
|
|
638
|
-
if (activity !== 'plan-execution' || slots.find((slot) => slot.slot === 'execute')?.recipe !== 'delegated') return [];
|
|
632
|
+
const foldLaneAdvice = ({ activity, slots, config, detection, cwd, env, resolveStore, readStore, audit, readHead }) => {
|
|
633
|
+
const own = slots.find((slot) => slot.slot === 'execute')?.recipe;
|
|
634
|
+
const task = activity === 'plan-execution' ? resolveActivityRecipe({ config: config ?? {}, readiness: detection, activity: 'task', slot: 'execute' }).recipe : null;
|
|
635
|
+
if (!['plan-execution', 'task'].includes(activity) || ![own, task].includes('delegated')) return [];
|
|
639
636
|
const ledger = readDelegationLedger(cwd, env, { resolveStore, readStore, audit, readHead });
|
|
640
637
|
return foldLaneLines(judgeLedger(ledger, { backend: HELD_RECEIPT_BACKEND, degrades: [] }));
|
|
641
638
|
};
|
|
@@ -805,6 +802,8 @@ export const main = (argv, ctx = {}) => {
|
|
|
805
802
|
const foldLane = foldLaneAdvice({
|
|
806
803
|
activity,
|
|
807
804
|
slots,
|
|
805
|
+
config,
|
|
806
|
+
detection,
|
|
808
807
|
cwd,
|
|
809
808
|
env,
|
|
810
809
|
resolveStore: ctx.resolveDelegationStorePath,
|
package/tools/review-state.mjs
CHANGED
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
// `--check` turns the report into a gate exit code (declare it in docs/ai/gates.json).
|
|
10
10
|
//
|
|
11
11
|
// Normative `--check` exit contract (the single home of this list — SKILL.md points here):
|
|
12
|
-
// Before the review-recipe exits, configured plan-execution.execute
|
|
13
|
-
// dirty, fingerprintable tree audits the delegation ledger.
|
|
14
|
-
// unavailable ledger or a HEAD error refuses. A SUBSTITUTED held session
|
|
15
|
-
// a codex-exec degrade at the substituted return's tree, standing after
|
|
16
|
-
// or the fold of that thread's retry lifts it (codex never grants it); a
|
|
17
|
-
// substitution closes only by its own ledger degrade.
|
|
12
|
+
// Before the review-recipe exits, a configured plan-execution.execute or task.execute of delegated
|
|
13
|
+
// (each read on its own) with a plan and a dirty, fingerprintable tree audits the delegation ledger.
|
|
14
|
+
// An absent ledger is inert; an unavailable ledger or a HEAD error refuses. A SUBSTITUTED held session
|
|
15
|
+
// refuses: for a head-base thread, a codex-exec degrade at the substituted return's tree, standing after
|
|
16
|
+
// every later fold, accepts it, or the fold of that thread's retry lifts it (codex never grants it); a
|
|
17
|
+
// checkpoint-based thread's substitution closes only by its own ledger degrade.
|
|
18
18
|
// exit 0 when the CONFIGURED plan-execution.review recipe is solo (or the computed default is —
|
|
19
19
|
// absent config with no reviewer backend ready); when no plan is in flight (docs/plans/
|
|
20
20
|
// holds no top-level .md that is not queue.md and not scratch by the naming convention:
|
|
@@ -382,7 +382,7 @@ export const buildState = ({ cwd, env = process.env, detect = detectBackends, su
|
|
|
382
382
|
const heldSession = buildHeldSessionState({
|
|
383
383
|
cwd,
|
|
384
384
|
env,
|
|
385
|
-
configuredExecute: config?.[ACTIVITY]?.execute,
|
|
385
|
+
configuredExecute: [config?.[ACTIVITY]?.execute, config?.task?.execute].find((recipe) => recipe === 'delegated'),
|
|
386
386
|
plans,
|
|
387
387
|
fingerprint,
|
|
388
388
|
clean,
|
|
@@ -786,10 +786,10 @@ The ONLY escape for an unavailable backend under council is an explicit current-
|
|
|
786
786
|
record (node core-evidence.mjs degrade) — and never all backends.
|
|
787
787
|
|
|
788
788
|
--check exits 0/1 per the normative contract in the tool header. FIRST, before any of the arms
|
|
789
|
-
below, a configured plan-execution.execute
|
|
790
|
-
fingerprintable tree audits the delegation ledger: an absent
|
|
791
|
-
malformed, foreign or audit-refused ledger, a failed HEAD read,
|
|
792
|
-
exits 1. THEN: 0 for solo / no plan in flight /
|
|
789
|
+
below, a configured plan-execution.execute or task.execute of delegated (each read on its own)
|
|
790
|
+
with a plan in flight and a dirty, fingerprintable tree audits the delegation ledger: an absent
|
|
791
|
+
ledger is inert; an unreadable, malformed, foreign or audit-refused ledger, a failed HEAD read,
|
|
792
|
+
or a SUBSTITUTED held session exits 1. THEN: 0 for solo / no plan in flight /
|
|
793
793
|
a clean tree (under a non-solo review obligation the PASS names every plan in flight and its arm) /
|
|
794
794
|
a cwd where git ITSELF answers not-a-repository (the only passing non-work-tree state; the four others exit 1 by name) / obligations satisfied (reviewed: >=1 ship-class attestation;
|
|
795
795
|
council: every backend ship-class or degrade-recorded, >=1 real ship); 1 on a veto, an
|
package/tools/task-brief.mjs
CHANGED
|
@@ -167,7 +167,8 @@ const checkRow = (context, brief, row) => {
|
|
|
167
167
|
const allowed = isSweep(row.path) ? expandSweepPaths(context.top, [row.path])[row.path] : [row.path];
|
|
168
168
|
if (implementations.some((path) => !allowed.includes(path))) reject(NAMES.row, row.id);
|
|
169
169
|
const tests = files.filter(({ tag }) => tag === TEST);
|
|
170
|
-
|
|
170
|
+
const bases = implementations.length > START ? implementations : allowed;
|
|
171
|
+
if (tests.some(({ path }) => TEST_RE.test(row.path) ? path !== row.path : !bases.some((impl) => {
|
|
171
172
|
const stem = impl.replace(EXTENSION_RE, EMPTY);
|
|
172
173
|
return path === `${stem}${TEST_SUFFIX}` || path.startsWith(`${stem}${TEST_DIRECTORY}`);
|
|
173
174
|
}))) reject(NAMES.row, row.id);
|