@sabaiway/agent-workflow-kit 1.35.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,76 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
4
4
  is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
5
5
  every `migrations/<version>-<slug>.md` newer than it, in semver order.
6
6
 
7
+ ## 1.37.0 — Fold-safety completion: a fixable-bug requires its test, and a coverage gate attests the fold against the changed code (AD-046)
8
+
9
+ A **feature** release (deployment-lineage head stays `1.3.0` — no migration). AD-045's ledger computed
10
+ WHEN a review loop stops; this release mechanizes **"a fold carries no new bug"** — M2 + M3a of
11
+ DEBT-TEST-COMPLETENESS. **No mutation testing ships** — that half was researched and shelved (see the
12
+ honest-limits note below).
13
+
14
+ - **M2 — testId enforcement (ledger schema v2).** A `fixable-bug` triage classification now REQUIRES a
15
+ `testId` (`<test-file>#<test-name-pattern>` — a `#` separator with both halves non-empty; the writer
16
+ validates FORMAT only, staying hermetic). Schema 1→2 with per-version validation: historical v1
17
+ records stay valid on read, a mixed ledger reads back clean; the writer emits v2 only; `decideStop`
18
+ is untouched.
19
+ - **M3a — the fold-completeness tool pair (read/run split, mirroring the ledger's read/write split).**
20
+ `tools/fold-completeness-run.mjs` — the SOLE tree-toucher + result writer: ONE suite run under
21
+ `NODE_V8_COVERAGE` (the coverage dir lives OUTSIDE the work tree), the changed surface classified by
22
+ a CLOSED extension rule (assessable JS · unsupported TS/JSX fails the gate closed · out-of-domain
23
+ docs/config listed loudly, never blocking), every bound testId probed shell-free for resolvability +
24
+ a GREEN baseline, and ONE machine-only record bound to BOTH the tree fingerprint AND the sorted
25
+ fixable-bug testId set — either moving makes the record stale. `tools/fold-completeness.mjs` — the
26
+ read-only `--status` / `--check` gate (fail-closed; the normative exit contract lives in its header,
27
+ the single home) that never imports the runner (import-split test).
28
+ - **Command surface** — the `fold-completeness` catalog entry (a writer) + `### Mode: fold-completeness`
29
+ + its mode reference. **Consumer seeding is deliberately ON HOLD**: the signal is JS/V8-only in v1,
30
+ so the consent-gated seeder does not offer this gate yet — wire it by hand (the mode-ref carries the
31
+ candidate `gates.json` line and the hold's reason).
32
+ - **Activity-aware canon pointer (with engine 1.14.0)** — the procedures advisor renders the ledger
33
+ pointer (record / `--status` / `--check`) for `plan-execution` ONLY, plus an unconditional
34
+ triage-classification bullet (`fixable-bug / inherent-layer-residual / escalate`) for every
35
+ review-backed activity.
36
+ - **Honest limits (stated in the tool headers, like `review-state`'s):** coverage proves EXECUTION, not
37
+ assertion — the per-fold proof remains the red→green test discipline (M2), the coverage run is the
38
+ whole-surface prefilter; records/testIds are forgeable (a self-discipline mechanism, not a security
39
+ boundary); line-entry granularity (same-line branch gaps are out of scope without an AST).
40
+ **Mutation (M3b) was researched and SHELVED** — bounded local-boundary mutation did not catch the
41
+ motivating interaction bug and is not language-independent; records carry a reserved EMPTY `mutation`
42
+ shape and the checker fails CLOSED on any record carrying mutation data.
43
+
44
+ ## 1.36.0 — Review-round ledger: the prose crossover-stop becomes a computed signal (AD-045)
45
+
46
+ A **feature** release (deployment-lineage head stays `1.3.0` — no migration). The review-loop
47
+ crossover-stop that `planning.md` §9 and `procedures.md` describe in prose — "cap ≤2 rounds", the
48
+ crossover, "fold-at-altitude vs residual", "{round N · finding-origin tally · per-backend verdict} …
49
+ a computed signal, not a remembered rule" — was **prose with no checker** and broke under load. This
50
+ ships it as a **mechanism** (DEBT-REVIEW-CAP): a review-round **LEDGER** that protects every consumer
51
+ project's `plan-execution` review loop.
52
+
53
+ - **`tools/review-ledger.mjs`** (read-only) — the record schema (two kinds, `round` / `triage`,
54
+ internally-consistency-validated), a tolerant reader (malformed lines counted + surfaced, never
55
+ dropped), the pure **`decideStop`** truth table returning exactly one state under a fixed precedence
56
+ (**converged > resolved-residual > triage-required > continue**) from machine fields only, the
57
+ integrity receipt cross-check, and the **`--check`** gate — **fail-CLOSED** on every unknown state
58
+ (detector failure · unreadable / malformed ledger · a corrupt round sequence · more than one plan
59
+ in flight).
60
+ - **`tools/review-ledger-write.mjs`** (the sole writer, over the hardened `atomic-write` core) —
61
+ `record` / `classify` with **the teeth**: it refuses a round while triage is required, beyond the
62
+ hard-max ceiling of 3, or without a grounded review receipt, and enforces round-sequence integrity +
63
+ round-bound classifications. The read/write split is pinned by an import-split test; the ledger lives
64
+ in the git dir (uncommittable by construction, mirroring the receipts precedent).
65
+ - **Command surface** — a `review-ledger` catalog entry + `### Mode: review-ledger` + its mode
66
+ reference; the conditional `seed-gates` candidate (offered only when `plan-execution.review` is
67
+ reviewed / council).
68
+ - **Honest residual** (stated in the tool header, like `review-state`'s): the ledger attests a review
69
+ occurred and its ship-class is consistent; it does not prove the recorded counts are truthful nor
70
+ that a self-reported `degraded` is real — a self-discipline mechanism, not a security boundary.
71
+
72
+ Self-arming dogfood: this release's own review loop was recorded through the ledger it builds
73
+ (`--check` exits 0 via the `converged` branch). The optional per-fold `testId` slot exists but stays
74
+ **unenforced** — enforcement + a fold-completeness signal + the canon-pointer mechanization are the
75
+ next plan (DEBT-TEST-COMPLETENESS).
76
+
7
77
  ## 1.35.0 — Host-level bridge settings surface + Codex Fast tier as configuration (AD-043)
8
78
 
9
79
  A **feature** release (deployment-lineage head stays `1.3.0` — no migration). Bridge knobs like the
package/README.md CHANGED
@@ -236,6 +236,8 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
236
236
  | `/agent-workflow-kit set-recipe` | any time | **config writer** for `docs/ai/orchestration.json`: tell the agent your preference in plain language and it maps it to explicit `--set <activity>.<slot>=<recipe>` / `--unset` ops; the kit validates, **previews by default**, and writes only on `--write` (deployment-gated, atomic, symlink/TOCTOU-safe), resolving the effective recipe vs live readiness. Writes **only** that file — **never runs a backend, never commits**; hand-editing stays fully supported. |
237
237
  | `/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 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). 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). |
238
238
  | `/agent-workflow-kit grounding` | any time | **grounded-review facts assembler** — mechanizes populating `agy-review --facts @f`: slices your entry-point's **Hard Constraints** section verbatim (exactly one match, else a loud stop) and/or a plan's decision-bearing sections (`## Approach` + `## Verification` required, `## Decisions (locked)` when present; duplicates stop), under the same byte budget the agy wrapper enforces (minus `--reserve-bytes` for the artifact share), with a loud tail-trim on overflow. Prints to stdout; `--out` writes **one scratch file only** (gitignored / outside the repo — a tracked or not-ignored in-repo path is refused). Never commits, never runs a subscription CLI. |
239
+ | `/agent-workflow-kit review-ledger` | any time | **review-round ledger** — turns the review-loop stop rule into a **computed** signal: record each plan-execution review round + its triage into a JSONL ledger inside the git dir (never committable), and read the stop decision (`converged > resolved-residual > triage-required > continue`) from the records — never from a remembered rule. `--status` replaces the hand-composed per-round tally; `--check` is a fail-closed gate exit code for `docs/ai/gates.json` (by hand or via the consent-gated seeder). A `fixable-bug` triage **requires its red→green `testId`** (schema v2; older records stay valid on read). The writer refuses a round past the hard-max, while a triage is pending, or without a grounded review receipt. Honest residual: records are forgeable — self-discipline, not a security boundary. Never commits, never runs a subscription CLI. |
240
+ | `/agent-workflow-kit fold-completeness` | any time | **fold-completeness gate** — attests the review loop's folded fixes against the changed code: the runner executes your suite ONCE under `NODE_V8_COVERAGE`, checks every changed executable line is **executed** and every bound `testId` resolves + starts GREEN, and appends one result record bound to BOTH the tree fingerprint AND the sorted testId set (either moving stales it — re-run after the last edit); the separate read-only checker (`--status` / `--check`) turns the record into a fail-closed gate. Honest residuals: coverage proves **execution, not assertion** (the per-fold proof stays the red→green `testId` discipline), and records are forgeable — self-discipline, not a security boundary. v1 scope is JS/V8: changed TS/JSX fails closed, docs/config changes are listed but never block, and **no mutation testing ships**. Wire the gate by hand — the consent-gated seeder deliberately does not offer it yet (JS-only hold). Never commits, never runs a subscription CLI. |
239
241
  | `/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. |
240
242
  | `/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. |
241
243
  | `/agent-workflow-kit agents` | Claude Code · opt-in | **cheap-lane subagents** — places bundled subagent definitions (`.claude/agents/`) pinned to a **cheap model** (haiku, low effort, read-only tools) for mechanical work: extraction sweeps, changelog fact-skeletons, gate-failure triage. Judgment, review, and real code stay on your main lane — these vehicles only extract and draft, and their output is verified. Preview by default (`--apply` writes); an existing customized file is **preserved, never overwritten**; never touches `settings*.json`, never commits. |
package/SKILL.md CHANGED
@@ -3,12 +3,12 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.35.0'
6
+ version: '1.37.0'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
10
10
 
11
- Deploys a **portable AI-agent memory-and-workflow system** into a project, and upgrades it as the kernel evolves — so any future agent can reconstruct project context in ~60 seconds and avoid repeating past mistakes.
11
+ Deploys a **portable AI-agent memory-and-workflow system** into a project, and upgrades it as the kernel evolves — so any future agent can reconstruct project context fast and avoid repeating past mistakes.
12
12
 
13
13
  **Posture:** never leak kit internals — translate tool outcomes to plain language; Gotchas: `${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md`.
14
14
 
@@ -23,14 +23,13 @@ when it is present and healthy, and otherwise uses its **own bundled copy** (`re
23
23
  `migrations/`) — so the existing one-command install keeps working with **no new dependency on the
24
24
  memory substrate**. (The methodology slot is a separate axis: its fragment is read **live from the
25
25
  installed `agent-workflow-engine`**, which `npx @sabaiway/agent-workflow-kit@latest init` installs — a
26
- runtime dependency placed by `init` and read live; see `${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md`.)
26
+ runtime dependency read live; see `${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md`.)
27
27
  `init` also **refreshes the installed memory substrate** (best-effort — a miss is a loud DEGRADED
28
- success: a warning with the exact recovery command + exit 0, never silent, never the engine's hard
29
- STOP; `--no-memory` skips it), so a returning `init` leaves **no stale core member**. The
28
+ success: warn + the exact recovery command + exit 0, never silent, never the engine's hard STOP;
29
+ `--no-memory` skips it), so a returning `init` leaves **no stale core member**. The
30
30
  execution-backend bridges are still never **placed** by `init` (placed on demand by `setup`, opt-in);
31
- **once placed**, `init` **refreshes** them from the kit's own bundled copies (refresh-only, local
32
- files, never a downgrade; `--no-bridges` skips it) — so a returning `init` leaves no stale placed
33
- bridge either.
31
+ **once placed**, `init` **refreshes** them from the kit's own bundled copies (refresh-only, never a
32
+ downgrade; `--no-bridges` skips it) — so a returning `init` leaves no stale placed bridge either.
34
33
 
35
34
  **Detection (kit-owned, decided BEFORE any project write).** Run the kit's **own shipped**
36
35
  validator — `node ${CLAUDE_SKILL_DIR}/tools/manifest/validate.mjs <memory-skill-dir>` — never a
@@ -38,9 +37,8 @@ validator shipped by the candidate (which could itself be broken). Delegate only
38
37
  hold:
39
38
  - result is **valid** and `kind` is `memory-substrate`;
40
39
  - **every required asset is present** in the candidate, at its real path:
41
- `references/templates/`, **`references/templates/orchestration.json`** (the orchestration-config
42
- template a memory too old to ship it, pre-`1.2.0`, can't seed `docs/ai/orchestration.json`, so it
43
- falls back to the kit's own bundled substrate, which does), `references/contracts.md`,
40
+ `references/templates/`, **`references/templates/orchestration.json`** (a pre-`1.2.0` memory can't
41
+ ship it, so it falls back to the kit's bundled substrate), `references/contracts.md`,
44
42
  `references/scripts/`, `scripts/stamp-takeover.mjs`, `migrations/`, `capability.json`. A partial
45
43
  install (manifest + `SKILL.md` only) is treated as **invalid**.
46
44
 
@@ -81,9 +79,9 @@ Before acting, read `docs/ai/.workflow-version` (the project's stamp) to decide
81
79
  **Two independent version axes — never conflate them:**
82
80
 
83
81
  1. **Project deployment** — `docs/ai/.workflow-version` vs the lineage head (`1.3.0`). This is the **only** axis this skill compares.
84
- 2. **Kit freshness** — this skill's own files vs the published npm package. That is the **npx installer's** job: `npx @sabaiway/agent-workflow-kit@latest init` (it refuses a stale-cache downgrade by comparing the version on disk — **no network**). This skill never checks npm, and the package version (e.g. `1.x`) is **not** the lineage head.
82
+ 2. **Kit freshness** — this skill's own files vs the published npm package. That is the **npx installer's** job: `npx @sabaiway/agent-workflow-kit@latest init` (it refuses a stale-cache downgrade by comparing the version on disk — **no network**). This skill never checks npm, and the package version is **not** the lineage head.
85
83
 
86
- **Refreshed the kit but nothing changed?** The skill you are running is whatever was on disk when the session started. After `npx @sabaiway/agent-workflow-kit@latest init` updates `~/.claude/skills/agent-workflow-kit/`, **restart the session** so the agent reloads the new skill files (the slash command + this `SKILL.md`).
84
+ **Refreshed the kit but nothing changed?** After `npx @sabaiway/agent-workflow-kit@latest init` updates `~/.claude/skills/agent-workflow-kit/`, **restart the session** so the agent reloads the new skill files.
87
85
 
88
86
  ### Mode: help
89
87
 
@@ -125,6 +123,10 @@ read-only — read `${CLAUDE_SKILL_DIR}/references/modes/procedures.md` before a
125
123
 
126
124
  writer — read `${CLAUDE_SKILL_DIR}/references/modes/set-recipe.md` before acting.
127
125
 
126
+ ### Mode: set-autonomy
127
+
128
+ writer — read `${CLAUDE_SKILL_DIR}/references/modes/set-autonomy.md` before acting.
129
+
128
130
  ### Mode: uninstall
129
131
 
130
132
  guarded — read `${CLAUDE_SKILL_DIR}/references/modes/uninstall.md` before acting.
@@ -153,11 +155,19 @@ read-only — read `${CLAUDE_SKILL_DIR}/references/modes/review-state.md` before
153
155
 
154
156
  writer — read `${CLAUDE_SKILL_DIR}/references/modes/grounding.md` before acting.
155
157
 
158
+ ### Mode: review-ledger
159
+
160
+ writer — read `${CLAUDE_SKILL_DIR}/references/modes/review-ledger.md` before acting.
161
+
162
+ ### Mode: fold-completeness
163
+
164
+ writer — read `${CLAUDE_SKILL_DIR}/references/modes/fold-completeness.md` before acting.
165
+
156
166
  ---
157
167
 
158
168
  ## References
159
169
 
160
- - [`references/modes/`](${CLAUDE_SKILL_DIR}/references/modes/) — one file per mode (the router lines above point here); [`references/shared/`](${CLAUDE_SKILL_DIR}/references/shared/) — the shared point-of-use contracts (report footer · composition hand-off · deploy tail).
170
+ - [`references/modes/`](${CLAUDE_SKILL_DIR}/references/modes/) — one file per mode; [`references/shared/`](${CLAUDE_SKILL_DIR}/references/shared/) — the shared point-of-use contracts (report footer · composition hand-off · deploy tail).
161
171
  - [`references/contracts.md`](${CLAUDE_SKILL_DIR}/references/contracts.md) — the three setup contracts.
162
172
  - [`references/templates/`](${CLAUDE_SKILL_DIR}/references/templates/) — the `AGENTS.md` + `docs/ai/` templates + seeded configs; [`references/scripts/`](${CLAUDE_SKILL_DIR}/references/scripts/) — the Node enforcement scripts; [`migrations/`](${CLAUDE_SKILL_DIR}/migrations/) — per-version upgrade steps; [`launchers/`](${CLAUDE_SKILL_DIR}/launchers/) — non-Claude agent launchers.
163
173
  - [`tools/`](${CLAUDE_SKILL_DIR}/tools/) — the family-wide tooling; each tool's contract lives with its mode file and its own header; bridge mirrors under [`bridges/`](${CLAUDE_SKILL_DIR}/bridges/).
package/capability.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "agent-workflow-kit",
5
5
  "kind": "composition-root",
6
- "version": "1.35.0",
6
+ "version": "1.37.0",
7
7
  "provides": [],
8
8
  "roles": {},
9
9
  "detect": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sabaiway/agent-workflow-kit",
3
- "version": "1.35.0",
3
+ "version": "1.37.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",
@@ -0,0 +1,22 @@
1
+ ### Mode: fold-completeness
2
+
3
+ The FOLD-COMPLETENESS gate (M3a / AD-046, DEBT-TEST-COMPLETENESS) — the sibling of the review-round ledger: the ledger computes WHEN the plan-execution review loop stops; this tool pair verifies that the tests the loop's folds bind to ACTUALLY pin the changed code. One recorded coverage run proves (a) every changed executable line is executed by the suite and (b) every `fixable-bug` bound testId resolves and starts GREEN; a read-only checker turns the recorded result into a gate exit code.
4
+
5
+ **Two tools — the read/run split:**
6
+
7
+ 1. **Runner** — `node ${CLAUDE_SKILL_DIR}/tools/fold-completeness-run.mjs [--suite "<cmd>"] [--cwd <dir>]` — the SOLE tree-toucher and the SOLE result writer. One run over the in-flight plan-execution loop's dirty tree: resolve the loop (the single in-flight plan stem — 0 or >1 plans is a typed refusal), classify the changed surface by a CLOSED extension rule (assessable JS / unsupported TS-JSX / out-of-domain), run the suite ONCE under `NODE_V8_COVERAGE` (the coverage dir lives OUTSIDE the work tree — no repo artifacts), map every changed executable line to covered/uncovered from the V8 report itself, probe each bound testId once (shell-free spawn) for resolvability + a green baseline, and append ONE machine-only record — bound to BOTH the tree fingerprint AND the sorted `fixable-bug` testId set — to `<git dir>/agent-workflow-fold-completeness.jsonl` (never committable by construction; `AW_FOLD_RESULTS` overrides).
8
+ 2. **Read-only checker** — `node ${CLAUDE_SKILL_DIR}/tools/fold-completeness.mjs [--check | --status | --json]` — never runs tests, never touches the tree, never imports the runner (an import-split test pins the structural split). `--status` (default) is the human report; **`--check` is the gate exit code — the normative exit contract lives in the CHECKER's tool header (the single home — do not re-enumerate it elsewhere)**; `--json` is the structured state + decision.
9
+
10
+ **Wire the gate BY HAND, once, BEFORE the round's runner run.** The candidate line for your own `docs/ai/gates.json`: `{ "id": "fold-completeness", "title": "Fold-completeness — every changed executable line executed by tests (M3a)", "cmd": "node \"<path-to-this-skill>/tools/fold-completeness.mjs\" --check" }` — the path your project reaches the kit by, kept inside the escaped quotes so a path with spaces survives. Wiring comes FIRST because where `docs/ai` is tracked, the gate-file edit itself moves the tree fingerprint — wiring after a run stales the record you just wrote. The consent-gated seeder does NOT offer this entry yet — a deliberate v1 hold: the signal is JS/V8-only, and offering it to a project whose source the runner cannot assess would seed a gate that can only fail closed; seeder offering arrives with a language-aware verification profile.
11
+
12
+ **Run-then-check usage (each plan-execution round):** run the runner AFTER the round's LAST edit — any later tree edit (a source fix, a doc touch, a gate-file tweak) moves the fingerprint and requires a re-run — then the wired `--check` attests it. Staleness is by BOTH bindings: a tree edit moves the fingerprint, and a new `fixable-bug` triage moves the bound-testId set — either makes the previous record STALE, so a green check always attests the CURRENT tree against the CURRENT fold set.
13
+
14
+ **Suite + bound-test commands:** the suite command defaults to the `unit-tests` gate `cmd` in the project's `docs/ai/gates.json`; absent that, `--suite "<cmd>"` (or `AW_FOLD_SUITE_CMD`) is REQUIRED — refused loudly otherwise. Bound-test probes default to the `node --test --test-name-pattern` shape over the testId halves (`<test-file>#<test-name-pattern>`); a consumer on another runner sets `AW_FOLD_BOUND_CMD` — a JSON ARRAY of argv strings with `{file}` / `{pattern}` placeholder substitution, spawned WITHOUT a shell (testId content never reaches a shell). Note: the suite's own child processes must inherit `NODE_V8_COVERAGE` for their lines to count (node child spawns inherit it by default; a test runner that scrubs its child env needs consumer configuration).
15
+
16
+ **v1 scope (stated):** assessable = `.mjs` / `.cjs` / `.js`, excluding test files (`*.test.*` / `*.spec.*`); changed `.ts` / `.tsx` / `.jsx` / `.mts` / `.cts` files are recorded as unsupported and FAIL the gate CLOSED — the signal never vouches for JS-family source it cannot assess; everything else (docs/config the suite does not execute) is recorded out-of-domain and LOUDLY listed, never gate-blocking. Executability is V8-derived: a changed assessable file entirely absent from the coverage report is RED at file level ("never imported" must not read as "nothing executable").
17
+
18
+ **Mutation is NOT shipped (v1).** The result record carries a reserved, always-empty `mutation` shape; the shipped runner performs NO mutation and never modifies a source file, and the checker FAILS CLOSED on a record carrying ANY mutation data (such a record was not produced by this runner version). The researched mutation half was shelved: a bounded operator set tests local expression boundaries, not the cross-module interactions that produce real fold bugs, and it is not language-independent. The `AW_FOLD_MUTANTS_MAX` / `AW_FOLD_HUNK_MUTANTS_MAX` / `AW_FOLD_TIME_BUDGET_S` budgets are parsed and recorded but inert in v1 (reserved).
19
+
20
+ **Honest residuals (stated, accepted — exactly like review-state's / review-ledger's):** coverage proves EXECUTION, not assertion — an executed-but-unasserted line still reads covered; the per-fold proof remains the M2 discipline (a `fixable-bug` testId written red→green, probed green here), the coverage run is the whole-surface prefilter; the result records, testIds, and ledgers are forgeable (`git commit --no-verify`, file editing) — a self-discipline mechanism against silent process drift, NOT a security boundary.
21
+
22
+ **Invariants:** the checker is read-only · never commits · never runs a subscription CLI · spawns read-only `git` queries only · the SOLE tree-toucher + result writer is `fold-completeness-run.mjs`, which the checker NEVER imports (read/run split, import-split test) · the runner's only writes land OUTSIDE the work tree (the coverage temp dir + the git-dir result ledger) — the tree fingerprint is byte-identical before and after a run.
@@ -0,0 +1,28 @@
1
+ ### Mode: review-ledger
2
+
3
+ The review-round **LEDGER** (DEBT-REVIEW-CAP / AD-045) — it turns the prose review-loop crossover-stop (`planning.md` §9 "cap ≤2 / crossover-stop / fold-at-altitude"; `procedures.md` "{round N · finding-origin tally · per-backend verdict} … computed signal, not a remembered rule") into a **COMPUTED** signal. The orchestrator records **one round per review round** to a JSONL ledger **inside the git dir** (`<git dir>/agent-workflow-review-ledger.jsonl` — never committable by construction; `AW_REVIEW_LEDGER` overrides), and a read-only checker computes the stop decision from the recorded rounds + triage classifications, never from a remembered rule. It is the read-only sibling of `review-state` (presence vs convergence are distinct axes) — the read module **never imports the writer** (an import-split test pins it).
4
+
5
+ **Two tools — the read/write split (Decision 3):**
6
+
7
+ 1. **Read-only checker** — `node ${CLAUDE_SKILL_DIR}/tools/review-ledger.mjs [--check | --status | --json]`:
8
+ - `--status` (default) → the human report: resolved `plan-execution.review` recipe, plan-in-flight, per-round tally with `findings[]`, per-backend counts + verdict, the `decideStop` verdict. **This printed render REPLACES the remembered per-round `{round N · finding-origin tally · per-backend verdict}` emission** — run it each round instead of composing the tally by hand.
9
+ - **`--check`** → the gate exit code. The **normative exit contract lives in the tool header** (the single home — do not re-enumerate it). It enforces the **plan-execution (code) loop** (the loop that produces the committable artifact), filtered to `activity==="plan-execution"` AND the in-flight plan's filename stem: exit 0 for solo / no plan in flight / a clean tree / a non-git cwd / a `converged` or `resolved-residual` loop; exit 1 for a dirty non-converged loop (`triage-required`, `continue`, or **no round/receipt recorded at all** — a dirty active plan with an empty/stale ledger is a FAILURE, not a fail-open pass), more than one plan in flight (ambiguous loop id), a recorded 0/0 coexisting with a non-ship receipt verdict, or a non-degraded recorded backend missing its receipt. **Fail-CLOSED** on a detector failure — the only detector-independent green is an EXPLICIT configured solo.
10
+ - `--json` → the structured state + decision.
11
+
12
+ 2. **Writer** — `node ${CLAUDE_SKILL_DIR}/tools/review-ledger-write.mjs record|classify --json '<payload>'` (the SOLE writer, over the shared `atomic-write` core):
13
+ - `record` appends one round — `{ loop, round, origins, backends, findings }` (activity defaults to `plan-execution`). **The teeth (Decision 5):** it REFUSES (typed STOP) to append a round WHILE `decideStop` on the existing records is `triage-required` (an UNCLASSIFIED surviving blocking finding at/after the cap), and refuses ANY round beyond the **hard-max ceiling of 3** unconditionally. **Integrity binding (Decision 7):** each NON-degraded backend needs a grounded **code** receipt (from `codex-review code` / `agy-review code --facts @f`) for the current tree — a round cannot be recorded for a tree no bridge reviewed.
14
+ - `classify` appends one triage — each surviving blocking finding classified `fixable-bug` / `inherent-layer-residual` / `escalate`. **A `fixable-bug` REQUIRES a `testId`** (M2/AD-046, schema v2) — the red→green test that pins the fold, formatted `<test-file>#<test-name-pattern>` (a `#` separator, both halves non-empty; no file-suffix rule); `inherent-layer-residual` / `escalate` may omit it. The writer validates the FORMAT only. **This is what BREAKS the deadlock:** once every surviving blocking finding is classified, `record` permits the next round (a `fixable-bug` classification lets the fix round run — no deadlock).
15
+
16
+ **The computed stop (`decideStop`, precedence `converged > resolved-residual > triage-required > continue`).** Machine fields only (counts, `class`, `accepted`, `fingerprint`), never free-text:
17
+ - **converged** — every recipe-named backend present, **non-degraded, at 0 blockers + 0 majors** in the latest round, at the current tree fingerprint. **"Surviving blocking finding" = a blocker OR a major** (a minor never forces triage).
18
+ - **resolved-residual** — at/after the cap (or a recurrence auto-trip), every surviving blocking finding classified `inherent-layer-residual` (document + raise to an acceptance criterion → NEVER folded again) OR `escalate` with `accepted:true`, and the triage's own fingerprint equals the current tree (a doc edit after the triage → a fresh round).
19
+ - **triage-required** (the writer HARD STOP) — a surviving blocking finding is UNCLASSIFIED at/after the cap, or a blocking finding recurred in ≥2 rounds still unclassified (even under the cap). `fixable-bug` → fold ONCE, re-review; `escalate` needs an accepted maintainer outcome.
20
+ - **continue** — the catch-all: under the cap, or a classified-but-not-resolved loop (fold the `fixable-bug` / obtain the `escalate` outcome, then a fresh round).
21
+
22
+ **"Every named backend" = "every NON-degraded named backend" (Decision 4).** A backend recorded `degraded:true` (agy is Issue-001-degraded on large diffs) is EXCLUDED from the 0/0 convergence requirement AND from the receipt cross-check (it ran no real review, mints no receipt), but is RECORDED (verdict `degraded`, a required `reason`) — it can never FAKE convergence. A recipe-named backend with NO entry is `missing` (≠ degraded) and BLOCKS convergence. Because the `degraded` mark is self-reported, `--check` surfaces every degraded backend loudly.
23
+
24
+ **Wire `--check` as a gate by hand OR via the explicit-consent seeder — never without consent.** The candidate line for your own `docs/ai/gates.json`: `{ "id": "review-ledger", "title": "Review-round ledger: the in-flight loop is converged or accepted-residual", "cmd": "node <path-to-this-skill>/tools/review-ledger.mjs --check" }` — the path your project reaches the kit by, QUOTED. The consent-gated seeder offers exactly this entry ONLY when `docs/ai/orchestration.json` declares `reviewed`/`council` on `plan-execution.review`.
25
+
26
+ **Human residual (stated, accepted — like `review-state`'s):** the ledger attests a review occurred and its ship-class is consistent; it does NOT prove the recorded COUNTS are truthful, nor that a self-reported `degraded:true` is real (`git commit --no-verify`, ledger-file editing, and forged counts remain possible). The ledger lives in the git dir (never committable) — a self-discipline mechanism against silent process drift, not a security boundary.
27
+
28
+ **Invariants:** the read module is read-only · never commits · never runs a subscription CLI · spawns read-only `git` queries only · the SOLE writer is `review-ledger-write.mjs`, which the read module NEVER imports (structural read/write split, import-split test) · `hardMax` is a writer-only ceiling, never a `decideStop` input.
@@ -0,0 +1,29 @@
1
+ ### Mode: set-autonomy
2
+
3
+ The **policy writer** for `docs/ai/autonomy.json` — the answer to *"set my autonomy policy without hand-editing JSON."* **Division of labor:** YOU turn the user's plain language into explicit ops; the KIT does the deterministic validate → merge → preview → write. It **previews by default** (writes nothing); `--write` applies. It **never renders enforcement** (that is the separate velocity autonomy mode — this writer touches only the policy file), **never runs a backend, and never commits**. Hand-editing `docs/ai/autonomy.json` stays fully supported — an offered convenience, never a lock.
4
+
5
+ **The policy** has two parts: **red-lines** (always hold, segment-independent) + a **per-activity autonomy level**.
6
+
7
+ - **red-lines** (`redlines.<key>` = `ask` | `deny`): the outward/irreversible actions. `commit` / `push` / `publish` (default **ask** — commit stays the human checkpoint); `network` / `credentials` / `fs_outside_repo` (default **deny** — the conservative floor).
8
+ - **autonomy** (`<activity>.autonomy` = `sandbox` | `prompt`) per activity (`plan-authoring`, `plan-execution`): `sandbox` ⇒ auto-allow confined commands + accept edits; `prompt` ⇒ conservative prompting (the sandbox still confines). An absent activity floors at `prompt`.
9
+
10
+ **Map the user's plain language → explicit ops** (the kit ships no NL parser; it performs no `all`-magic, so you expand scope explicitly, asking when unclear — localize the interpretation to the user's language at narration time, but keep the ops exact):
11
+
12
+ | user intent | op |
13
+ |---|---|
14
+ | more autonomous when executing | `--set plan-execution.autonomy=sandbox` |
15
+ | prompt while planning | `--set plan-authoring.autonomy=prompt` |
16
+ | always ask before commit | `--set redlines.commit=ask` |
17
+ | block the network | `--set redlines.network=deny` |
18
+ | revert / do it as before | `--unset <section>.<key>` (→ its computed default) |
19
+
20
+ Run **`node ${CLAUDE_SKILL_DIR}/tools/set-autonomy.mjs [--set <section>.<key>=<value>]… [--unset <section>.<key>]… [--write] [--json]`**:
21
+
22
+ 1. **Grammar — always fully-qualified `<section>.<key>`** (the kit never guesses the section; a bare `commit=ask` is rejected). Sections/keys: `redlines.{commit,push,publish,network,credentials,fs_outside_repo}` (each `ask|deny`); `plan-authoring.autonomy`, `plan-execution.autonomy` (each `sandbox|prompt`).
23
+ 2. **Preview by default** — prints `current → proposed` for the **changed** keys only, plus each key's **effective value** (an `--unset` shows its computed default). It writes **nothing**. Re-run with **`--write`** to apply. A no-op `--set` (value already equals) writes nothing and never re-seeds the onboarding note.
24
+ 3. **`--write`** applies via a hardened, atomic write (deployment-gated — refuses to scatter a policy into a repo with no `docs/ai`; exclusive-create temp + rename; symlink/TOCTOU-safe; last-writer-wins). It preserves the onboarding note + every untouched key, normalizing to canonical 2-space JSON. After a write it points at the **velocity autonomy render** as the next step (rendering the policy into `.claude/settings.json` is a separate, previewed step — this writer never touches settings).
25
+ 4. **Exit codes:** `0` success; `2` usage (a bare/duplicate op, or `--write` with no ops); `1` config error (malformed/unreadable policy — the file is left **untouched**, never clobbered) or a write STOP (no deployment / a symlinked policy). A `1`/`2` failure is loud; on a malformed policy, offer to show the parse error so you can help the user fix the JSON.
26
+
27
+ Output is **English/structured** — **localize it to the user's conversational language** when you narrate.
28
+
29
+ **Invariants:** writer (writes only `docs/ai/autonomy.json`) · never renders enforcement · never runs a backend · never commits · previews by default · hand-edit stays first-class.
@@ -31,3 +31,16 @@ Honesty notes: tier entries get **NO PreToolUse-hook residual coverage** — the
31
31
  **Invariants:** creates `.claude/` if absent and writes **only** `.claude/settings.json` (no other file); **never** allowlists commit/push/publish; **never** writes `settings.local.json`; never commits; opt-in `acceptEdits`, never silent.
32
32
 
33
33
  **Exit codes:** `0` done / dry-run; `1` a precondition STOP (stamp not current, unsafe mode, malformed settings, symlinked `.claude` / non-regular target); `2` bad arguments.
34
+
35
+ ---
36
+
37
+ ## The `--autonomy` render (separate mode — AD-044)
38
+
39
+ `--autonomy` is a **separate mode** from the allowlist seeding above: it renders the per-project autonomy policy (`docs/ai/autonomy.json`, written by `set-autonomy` — `${CLAUDE_SKILL_DIR}/references/modes/set-autonomy.md`) into the `.claude/settings.json` blocks it **owns** — the `sandbox` block, `permissions.ask`/`permissions.deny` red-lines, and `permissions.defaultMode`. It is **policy-only**: it never seeds the read-only allowlist and leaves `permissions.allow` untouched as a value. Run **`node ${CLAUDE_SKILL_DIR}/tools/velocity-profile.mjs --autonomy [--apply] [--cwd <dir>]`**:
40
+
41
+ 1. **Preview by default** (writes nothing); **`--apply`** merges the render-owned blocks into `.claude/settings.json` (merge-don't-clobber — foreign top-level keys, existing `permissions.allow`, and foreign ask/deny entries preserved; a policy flip MOVES a red-line rule between ask/deny rather than duplicating it). It **refuses an absent policy** loudly (seed one first with `set-autonomy`). It **never writes `settings.local.json`**; a `settings.local.json` `defaultMode` that would mask the render is reported (local > project).
42
+ 2. **`--autonomy --check`** is a **read-only drift gate**: it recomputes the render and compares against the live render-owned blocks — exit `0` in sync, exit `1` on drift (naming the exact key). A hand-edit OUTSIDE those blocks never flags.
43
+ 3. **Version-sensitive (characterized against the real claude 2.1.185).** Sandbox keys are `sandbox.enabled` + `sandbox.autoAllowBashIfSandboxed`; `sandbox` level ⇒ auto-allow + `defaultMode: acceptEdits`, `prompt` level ⇒ auto-allow OFF + `defaultMode: default` (the sandbox stays enabled as a confine floor either way). Red-lines use the argument-matching `:*` wildcard (`Bash(git commit:*)` / `Bash(git push:*)` / `Bash(npm publish:*)`). Where 2.1.185 cannot express a red-line distinctly — a **network hard-block** (regular settings only prompt on egress), **credential denial** (`sandbox.credentials` is 2.1.187+ / mask 2.1.199+), or a **prompt-on-outside-write** — the render **DEGRADES LOUDLY** (never a silent allow, never pretend-security). A missing Linux dependency (`socat`/`bwrap`) or an unsupported platform degrades the WHOLE sandbox to unsandboxed — the render still lands the red-lines + `defaultMode` and caveats that ad-hoc scripts will still prompt.
44
+ 4. **`--autonomy` cannot combine** with `--accept-edits` or `--kit-tools` (allowlist-mode flags) — a loud usage error.
45
+
46
+ **Autonomy invariants:** policy-only (never seeds the allowlist, leaves `permissions.allow` untouched) · writes only `.claude/settings.json` (never `settings.local.json`) · refuses an absent policy · merge-don't-clobber · degrades loudly where 2.1.185 can't enforce · previews by default · never commits.