@sabaiway/agent-workflow-kit 1.43.0 → 1.45.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/README.md +8 -4
  3. package/SKILL.md +20 -8
  4. package/bridges/antigravity-cli-bridge/SKILL.md +1 -1
  5. package/bridges/antigravity-cli-bridge/bin/agy-review.sh +87 -16
  6. package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +3 -0
  7. package/bridges/antigravity-cli-bridge/bin/agy.test.mjs +4 -2
  8. package/bridges/antigravity-cli-bridge/capability.json +3 -2
  9. package/bridges/codex-cli-bridge/SKILL.md +1 -1
  10. package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +3 -0
  11. package/bridges/codex-cli-bridge/bin/codex-review.sh +90 -19
  12. package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +4 -0
  13. package/bridges/codex-cli-bridge/capability.json +3 -2
  14. package/bridges/codex-cli-bridge/references/driving-codex.md +3 -2
  15. package/bridges/codex-cli-bridge/references/sandbox-and-flags.md +3 -2
  16. package/capability.json +1 -1
  17. package/package.json +1 -1
  18. package/references/modes/autonomy-doctor.md +21 -0
  19. package/references/modes/bootstrap.md +1 -1
  20. package/references/modes/doc-parity.md +2 -1
  21. package/references/modes/grounding.md +8 -7
  22. package/references/modes/recommendations.md +14 -0
  23. package/references/modes/review-state.md +1 -1
  24. package/references/modes/sandbox-masks.md +15 -0
  25. package/references/modes/upgrade.md +10 -7
  26. package/references/modes/velocity.md +13 -2
  27. package/references/shared/composition-handoff.md +21 -16
  28. package/references/shared/report-footer.md +5 -1
  29. package/references/templates/AGENTS.md +2 -1
  30. package/references/templates/autonomy.json +3 -0
  31. package/tools/autonomy-config.mjs +13 -3
  32. package/tools/autonomy-doctor.mjs +488 -0
  33. package/tools/commands.mjs +24 -3
  34. package/tools/delegation.mjs +9 -5
  35. package/tools/detect-backends.mjs +2 -2
  36. package/tools/doc-parity.mjs +31 -2
  37. package/tools/engine-source.mjs +6 -0
  38. package/tools/family-registry.mjs +21 -7
  39. package/tools/fold-completeness-run.mjs +5 -0
  40. package/tools/grounding.mjs +139 -22
  41. package/tools/inject-methodology.mjs +117 -28
  42. package/tools/manifest/schema.md +20 -0
  43. package/tools/manifest/validate.mjs +26 -0
  44. package/tools/procedures.mjs +61 -8
  45. package/tools/recipes.mjs +94 -15
  46. package/tools/recommendations.mjs +469 -0
  47. package/tools/review-ledger-write.mjs +14 -0
  48. package/tools/review-ledger.mjs +3 -2
  49. package/tools/review-state.mjs +101 -24
  50. package/tools/run-gates.mjs +3 -0
  51. package/tools/sandbox-masks.mjs +370 -0
  52. package/tools/set-recipe.mjs +13 -1
  53. package/tools/velocity-profile.mjs +231 -24
@@ -13,8 +13,9 @@
13
13
  #
14
14
  # For `code`, the wrapper PRECOMPUTES the full change set (repo map, git status,
15
15
  # staged + unstaged diffs, untracked file CONTENTS — binaries skipped, symlinks
16
- # shown as targets, other non-regular paths skipped) and feeds it in, so codex does
17
- # not burn a run rediscovering it by roaming the filesystem. A clean tree exits 0
16
+ # shown as targets, directories/vanished paths noted; never-committable untracked
17
+ # paths (devices/FIFOs/sockets) are excluded from the review domain entirely) and
18
+ # feeds it in, so codex does not burn a run rediscovering it. A clean tree exits 0
18
19
  # BEFORE a run is spent; an oversized payload goes via a git-dir-local temp file
19
20
  # (never silently truncated). Optionally (CODEX_REVIEW_SCHEMA=1) the findings come
20
21
  # back as a validated JSON object, with a raw-text fallback.
@@ -56,7 +57,9 @@ Receipt:
56
57
  side effect — a successful review appends one JSON receipt line to
57
58
  <git dir>/agent-workflow-review-receipts.jsonl (AW_REVIEW_RECEIPTS overrides): fingerprint =
58
59
  sha256 over the canonical uncommitted-state payload (staged diff + unstaged diff +
59
- untracked-not-ignored contents — the review-payload domain) in code mode, the artifact-file
60
+ untracked-not-ignored contents — the review-payload domain; never-committable untracked paths
61
+ character/block devices, FIFOs, sockets — are excluded from the domain entirely, untracked
62
+ symlinks/directories ride as name-only notes) in code mode, the artifact-file
60
63
  sha256 in plan mode; verdict parsed from the mandated literal verdict line (schema mode: the
61
64
  verdict field); always fresh:true (one-shot) + grounded:true (native AGENTS.md auto-merge,
62
65
  factsHash null); a write failure warns, never fails the review
@@ -169,7 +172,7 @@ DEFAULT_CODEX_EFFORT="xhigh"
169
172
  # Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
170
173
  # version (drift-guarded by codex-review.test.mjs against capability.json).
171
174
  AW_RECEIPT_BACKEND="codex"
172
- AW_BRIDGE_VERSION="2.3.0"
175
+ AW_BRIDGE_VERSION="2.4.0"
173
176
  CODEX_MODEL="${CODEX_MODEL:-$DEFAULT_CODEX_MODEL}"
174
177
  CODEX_EFFORT="${CODEX_EFFORT:-$DEFAULT_CODEX_EFFORT}"
175
178
  # Generous hard cap for a slow xhigh review (subscription latency varies).
@@ -292,11 +295,76 @@ sha256_stdin() {
292
295
  fi
293
296
  }
294
297
 
298
+ # Never-committable untracked stat class (Decision 1, AD-044 Plan 4): character/block devices,
299
+ # FIFOs, sockets — git content can never carry them, so they are excluded from the ENTIRE review
300
+ # domain (fingerprint payload, assembled change set, status section, no-diff preflight). Symlinks
301
+ # (checked first, never followed) and directories (an embedded repo lists as `dir/` — a committable
302
+ # gitlink) STAY in the domain. The class surfaces where a sandbox injects device masks whose dirent
303
+ # LIES to git's walk; the stat here sees the truth.
304
+ is_never_committable_untracked() {
305
+ [[ ! -L "$1" && ( -p "$1" || -S "$1" || -c "$1" || -b "$1" ) ]]
306
+ }
307
+
308
+ # The ONE untracked-not-ignored walk every review-domain surface iterates (fingerprint payload,
309
+ # assembled change set, no-diff preflight): NUL-delimited paths with the never-committable classes
310
+ # filtered out.
311
+ emit_untracked_paths_z() {
312
+ local path
313
+ while IFS= read -r -d '' path; do
314
+ if is_never_committable_untracked "$path"; then continue; fi
315
+ printf '%s\0' "$path"
316
+ done < <(git ls-files --others --exclude-standard -z)
317
+ }
318
+
319
+ # True when at least one untracked-not-ignored path survives the never-committable filter — the
320
+ # no-diff preflight twin of the fingerprint walk (a tree whose ONLY untracked paths are
321
+ # device/FIFO/socket masks reads clean).
322
+ has_reviewable_untracked() {
323
+ [[ "$(emit_untracked_paths_z | wc -c)" -gt 0 ]]
324
+ }
325
+
326
+ # `git status --porcelain=v1` with never-committable untracked records dropped, so the assembled
327
+ # review payload is byte-identical with and without a device mask (the fingerprint==payload domain
328
+ # identity). Quote/space-safe: each filtered path's DISPLAYED line comes from git itself (never a
329
+ # re-implemented C-quoting), then exact whole-line removal — only untracked (??) records can match
330
+ # by construction. A mask nested in an otherwise-empty untracked directory leaves the collapsed
331
+ # `?? dir/` record (a directory is not in the filtered class); the real sandbox masks land beside
332
+ # tracked content, where status lists them individually.
333
+ emit_status_porcelain_filtered() {
334
+ local path line drop=""
335
+ while IFS= read -r -d '' path; do
336
+ if is_never_committable_untracked "$path"; then
337
+ line="$(git status --porcelain=v1 -- ":(literal)$path")"
338
+ if [[ -n "$line" ]]; then drop+="$line"$'\n'; fi
339
+ fi
340
+ done < <(git ls-files --others --exclude-standard -z)
341
+ if [[ -z "$drop" ]]; then
342
+ git status --porcelain=v1
343
+ else
344
+ git status --porcelain=v1 | grep -Fvxf <(printf '%s' "$drop") || true
345
+ fi
346
+ }
347
+
348
+ # ONE non-failing advisory when the walk observes never-committable untracked paths: they are
349
+ # ignored by the review domain BY CONSTRUCTION; the kit's sandbox-masks lane can hide them from
350
+ # `git status` too. Never an error, never a detector.
351
+ warn_never_committable_untracked() {
352
+ local path n=0
353
+ while IFS= read -r -d '' path; do
354
+ if is_never_committable_untracked "$path"; then n=$((n + 1)); fi
355
+ done < <(git ls-files --others --exclude-standard -z)
356
+ if (( n > 0 )); then
357
+ echo "notice: $n never-committable untracked path(s) (device/FIFO/socket) ignored by the review domain — for a clean 'git status' see the kit's sandbox-masks lane (/agent-workflow-kit sandbox-masks)." >&2
358
+ fi
359
+ }
360
+
295
361
  # The canonical uncommitted-state fingerprint payload (code mode). Domain == the review payload:
296
- # tracked staged + unstaged changes + untracked-not-ignored file contents (binary/symlink/non-regular
297
- # untracked paths ride as name-only notes, mirroring the assembled change set). The prose definition
298
- # lives in capability.json roles.review.contract.receipt (both bridges, lockstep); the kit checker
299
- # (tools/review-state.mjs) implements the SAME serialization in node — cross-checked by the kit's
362
+ # tracked staged + unstaged changes + untracked-not-ignored file contents (binary untracked files,
363
+ # symlinks, and directories/gitlinks ride as name-only notes, mirroring the assembled change set;
364
+ # never-committable untracked paths devices/FIFOs/sockets are EXCLUDED entirely, see
365
+ # emit_untracked_paths_z). The prose definition lives in capability.json
366
+ # roles.review.contract.receipt (both bridges, lockstep); the kit checker (tools/review-state.mjs)
367
+ # implements the SAME serialization in node — cross-checked by the kit's
300
368
  # review-fingerprint-parity.test.mjs.
301
369
  emit_fingerprint_payload() {
302
370
  git diff --cached --no-ext-diff
@@ -313,7 +381,7 @@ emit_fingerprint_payload() {
313
381
  printf 'untracked:%s\n' "$path"
314
382
  cat -- "$path"
315
383
  fi
316
- done < <(git ls-files --others --exclude-standard -z)
384
+ done < <(emit_untracked_paths_z)
317
385
  }
318
386
 
319
387
  # sha256 of the canonical payload, emitted from the work-tree ROOT (a subdir invocation hashes the
@@ -355,17 +423,18 @@ write_review_receipt() {
355
423
  fi
356
424
  }
357
425
 
358
- # Emit the full review surface to stdout: repo map, status, staged + unstaged
359
- # diffs, and the CONTENTS of every untracked REGULAR file (NUL-safe iteration).
360
- # Symlinks are shown as their target (never followedno out-of-repo leak); other
361
- # non-regular paths (FIFO/socket/device) are skipped (a `cat` on a FIFO would hang
362
- # BEFORE the codex hard timeout applies).
426
+ # Emit the full review surface to stdout: repo map, status (never-committable untracked records
427
+ # filtered), staged + unstaged diffs, and the CONTENTS of every untracked REGULAR file (NUL-safe
428
+ # iteration over the SAME filtered walk as the fingerprint the payload is byte-identical with
429
+ # and without a device mask). Symlinks are shown as their target (never followed no out-of-repo
430
+ # leak); directories/vanished paths are noted, never read (a `cat` on a FIFO would hang BEFORE the
431
+ # hard timeout applies — that class never reaches this loop).
363
432
  assemble_code_diff() {
364
433
  echo "=== repo file map (git ls-files) ==="
365
434
  git ls-files
366
435
  echo
367
436
  echo "=== git status (porcelain) ==="
368
- git status --porcelain=v1
437
+ emit_status_porcelain_filtered
369
438
  echo
370
439
  echo "=== staged diff (git diff --cached) ==="
371
440
  git diff --cached --no-ext-diff
@@ -387,7 +456,7 @@ assemble_code_diff() {
387
456
  cat -- "$path"
388
457
  printf '\n'
389
458
  fi
390
- done < <(git ls-files --others --exclude-standard -z)
459
+ done < <(emit_untracked_paths_z)
391
460
  }
392
461
 
393
462
  mode="${1:-}"
@@ -416,12 +485,14 @@ case "$mode" in
416
485
  prompt="${directive}"$'\n\nPLAN:\n'"$(cat -- "$target")"
417
486
  ;;
418
487
  code)
419
- # No-diff preflight — never spend a subscription run on a clean tree.
420
- if git diff --quiet && git diff --cached --quiet \
421
- && [[ -z "$(git ls-files --others --exclude-standard)" ]]; then
488
+ # No-diff preflight — never spend a subscription run on a clean tree. Never-committable
489
+ # untracked masks do not count: the FILTERED domain is the review surface.
490
+ if git diff --quiet && git diff --cached --quiet && ! has_reviewable_untracked; then
422
491
  echo "codex-review: no uncommitted changes to review — the working tree is clean." >&2
492
+ warn_never_committable_untracked
423
493
  exit 0
424
494
  fi
495
+ warn_never_committable_untracked
425
496
  # The canonical fingerprint of the tree codex is about to review — computed at assembly time
426
497
  # (BEFORE the EXIT trap can fire), so the receipt attests exactly the reviewed state.
427
498
  REVIEW_ARTIFACT="code"
@@ -106,6 +106,10 @@ const run = ({ repo, bin }, { args = ['code'], env = {}, path, cwd } = {}) => {
106
106
  env: {
107
107
  PATH: path || `${bin}:${process.env.PATH}`,
108
108
  HOME: repo,
109
+ // The wrapper's mktemp must keep working when the suite itself runs inside an OS sandbox
110
+ // whose /tmp is read-only (only $TMPDIR is writable there) — the built-from-scratch env
111
+ // would otherwise drop it and fail every spawn.
112
+ TMPDIR: process.env.TMPDIR ?? '/tmp',
109
113
  CODEX_HOME: codexHome,
110
114
  CODEX_FAKE_ARGV: argvFile,
111
115
  CODEX_FAKE_ENV: envFile,
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "codex-cli-bridge",
5
5
  "kind": "execution-backend",
6
- "version": "2.3.0",
6
+ "version": "2.4.0",
7
7
  "provides": ["execute", "review"],
8
8
  "roles": {
9
9
  "execute": {
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "grounding": "automatic — the wrapper precomputes the full working-tree change set (repo map, status, diffs, untracked contents) and codex auto-merges the root AGENTS.md; no grounding flags",
41
41
  "continue": [],
42
- "receipt": "side effect — a successful review appends one JSON receipt line to <git dir>/agent-workflow-review-receipts.jsonl (AW_REVIEW_RECEIPTS overrides): fingerprint = sha256 over the canonical uncommitted-state payload (staged diff + unstaged diff + untracked-not-ignored contents — the review-payload domain) in code mode, the artifact-file sha256 in plan mode; verdict parsed from the mandated literal verdict line (schema mode: the verdict field); always fresh:true (one-shot) + grounded:true (native AGENTS.md auto-merge, factsHash null); a write failure warns, never fails the review"
42
+ "receipt": "side effect — a successful review appends one JSON receipt line to <git dir>/agent-workflow-review-receipts.jsonl (AW_REVIEW_RECEIPTS overrides): fingerprint = sha256 over the canonical uncommitted-state payload (staged diff + unstaged diff + untracked-not-ignored contents — the review-payload domain; never-committable untracked paths — character/block devices, FIFOs, sockets — are excluded from the domain entirely, untracked symlinks/directories ride as name-only notes) in code mode, the artifact-file sha256 in plan mode; verdict parsed from the mandated literal verdict line (schema mode: the verdict field); always fresh:true (one-shot) + grounded:true (native AGENTS.md auto-merge, factsHash null); a write failure warns, never fails the review"
43
43
  }
44
44
  }
45
45
  },
@@ -71,6 +71,7 @@
71
71
  "effect": "codex-review code: above this assembled-payload size (bytes) the diff rides via a git-dir temp file instead of inline — never truncated."
72
72
  }
73
73
  ],
74
+ "networkHosts": ["chatgpt.com", "*.chatgpt.com"],
74
75
  "detect": {
75
76
  "installed": {
76
77
  "env": "CODEX_CLI_BRIDGE_DIR",
@@ -38,8 +38,9 @@ mis-ordered steps, scope creep, missing gates).
38
38
 
39
39
  Use **`codex-review code`** for advisory, severity-tagged findings on uncommitted changes. The wrapper
40
40
  **precomputes the whole change set** — repo map, `git status`, staged + unstaged diff, and the
41
- **contents of untracked files** (binaries noted but skipped, symlinks shown as targets, other
42
- non-regular paths skipped) and feeds it in, so codex does not burn a run roaming the filesystem to
41
+ **contents of untracked files** (binaries noted but skipped, symlinks shown as targets;
42
+ never-committable untracked paths — devices/FIFOs/sockets excluded from the review domain
43
+ entirely) — and feeds it in, so codex does not burn a run roaming the filesystem to
43
44
  rediscover it. A clean tree exits 0 *before* a run is spent. An oversized payload (over
44
45
  `CODEX_REVIEW_MAX_TOTAL_BYTES`, default 1.5 MB) is written to a git-dir temp file and referenced by
45
46
  path — never silently truncated. Set `CODEX_REVIEW_SCHEMA=1` to get findings back as a validated JSON
@@ -108,8 +108,9 @@ This is defence-in-depth beside the prompt contract; the orchestrator still revi
108
108
 
109
109
  `code` mode does NOT make codex discover the diff. The wrapper assembles the full surface — repo file
110
110
  map (`git ls-files`), `git status`, staged + unstaged diff, and the **contents** of every untracked
111
- regular file (NUL-safe; binaries noted but skipped, symlinks shown as targets, other non-regular paths
112
- skipped)into a git-dir-local temp file (600 perms), then feeds it in. A **clean tree exits 0** before
111
+ regular file (NUL-safe; binaries noted but skipped, symlinks shown as targets; never-committable
112
+ untracked paths devices/FIFOs/sockets excluded from the review domain entirely) into a
113
+ git-dir-local temp file (600 perms), then feeds it in. A **clean tree exits 0** before
113
114
  a run is spent. If the assembled payload exceeds `CODEX_REVIEW_MAX_TOTAL_BYTES` (default `1500000`) it is
114
115
  passed **by path** (read-fence carve-out) instead of inline — **never truncated**. `-s read-only` is
115
116
  kept so codex may still read surrounding in-repo files for context.
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.43.0",
6
+ "version": "1.45.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.43.0",
3
+ "version": "1.45.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,21 @@
1
+ ### Mode: autonomy-doctor
2
+
3
+ The **sandbox provisioner "doctor"** — the answer to *"can this machine run the Claude sandbox, and can you fix it?"* (AD-044: macOS Seatbelt built-in / Linux+WSL2 `bwrap`+`socat` / native Windows → WSL2). **Division of labor:** YOU narrate the diagnosis and relay the consent question; the KIT does the deterministic detect → consent-gated install → verify. It is **guarded**: the privileged lane runs ONLY with the per-run consent tuple, always faces the harness permission prompt (the mode sits outside every velocity auto-approve tier), **never auto-runs, never writes repo files, and never commits**.
4
+
5
+ Run **`node ${CLAUDE_SKILL_DIR}/tools/autonomy-doctor.mjs [--verify | --apply <pm>:<pkg[,pkg...]>]`**:
6
+
7
+ 1. **Flagless = FS-only preview** (the default; runs NO subprocesses): the diagnosis, the exact absolute-path command the doctor WOULD run, and the exact `--apply <pm>:<pkgs>` consent line. It **never claims "ready"** — binaries present without proof render `present-unverified`, never exit `0`.
8
+ 2. **`--verify`** — the unprivileged diagnostic: a `bwrap` user-namespace smoke plus `socat -V` (captured stdio). This is the ONLY source of a Linux **ready-verified** claim. Honesty split: a green verify proves the **OS primitives, not Claude-init** — the output always states the restart step. Under root/`SUDO_UID` the verified claim is REFUSED (`root-unproven`); a namespace-denied smoke with present binaries reports a loud `indeterminate` (nested sandboxing / already inside a container — re-run from an unsandboxed shell).
9
+ 3. **`--apply <pm>:<pkgs>`** — the consent-gated privileged install: the tuple must EQUAL the re-derived plan (consent binds to the previewed plan; a mismatch or a bare `--apply` refuses with `2` usage and runs NOTHING), the exact resolved command is re-printed immediately before execution, then the verify lane runs automatically. Sudo boundary: root drops sudo; a passwordless sudo proceeds with a LOUD note; a password-needing sudo without a controlling terminal runs NOTHING and prints the exact command to run in the USER's terminal (`handoff-required`).
10
+
11
+ **Trust gate:** everything executed resolves to an ABSOLUTE path inside the fixed trusted dirs `/usr/bin:/bin:/usr/sbin:/sbin` (`/usr/local/bin` deliberately excluded); a binary or package manager found only outside is a loud `untrusted-path` / `unknown-pm` degrade, never executed. The privileged child gets a minimal scrubbed env (trusted-dir PATH + LANG), an argv array, no shell. Package names come from a frozen internal map (`bubblewrap`, `socat`); apt runs through the env trampoline (`env DEBIAN_FRONTEND=noninteractive …`) so non-interactivity survives sudo's `env_reset`.
12
+
13
+ **Exit codes (frozen):** `0` ready (`ready-verified` / `ready-assumed`; Linux only via the verify oracle) · `1` precondition STOP (`no-deployment`) · `2` usage (bare `--apply`, tuple mismatch, unknown flag) · `3` not-ready diagnosis (`missing-binaries` offer / `present-unverified` / `handoff-required`) · `4` install failed (`install-failed`) · `5` verify failed (`verify-failed` / `indeterminate` / `root-unproven`) · `6` unsupported / untrusted (`unsupported-platform` win32 / `unknown-pm` / `untrusted-path`). The machine summary line prints LAST in every diagnosis outcome (`--help` prints the help text alone): `[autonomy-doctor] status=<token> platform=<p> missing=<csv> pm=<name|none>`.
14
+
15
+ **Stamp EXEMPTION (stated, deliberate):** the doctor runs behind the docs/ai presence gate ahead of every lane (`--help` and parse-time usage errors return earlier) but has **NO `.workflow-version` stamp gate** — it provisions the OS, never lineage-bound repo content, so the global stale-deployment→upgrade routing does not apply to this mode.
16
+
17
+ **Residuals (disclosed in the preview):** a root-owned hostile binary inside the trusted dirs is out of the threat model; Claude itself resolves `bwrap`/`socat` via PATH at session init (the doctor warns on a PATH shadow, never fixes PATH); the harness permission prompt shows the `--apply` tuple, not the absolute-path command — bridged by the apply-time re-print.
18
+
19
+ Output is **English/structured** — **localize it to the user's conversational language** when you narrate.
20
+
21
+ **Invariants:** guarded (the MUTATING lane only via `--apply` with the matching tuple, exactly once) · preview-first · never auto-runs · outside every velocity auto-approve tier · never writes repo files · never commits · loud degrades, never silent.
@@ -18,7 +18,7 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
18
18
  3. **Choose conversational language — answered in the step-2 batch.** Which language should the agent *talk to them* in — questions, explanations, summaries, status updates? Offer the language they're already writing in as the default. Carry the answer into the `{{COMM_LANGUAGE}}` slot of the *Communication language* block when `AGENTS.md` is created (step 5). See [Communication contract](${CLAUDE_SKILL_DIR}/references/contracts.md#communication-contract). This sets the **dialogue** language only — never the files.
19
19
  4. **Choose agent attribution — answered in the step-2 batch.** May the agent attribute work to itself / to AI — `Co-Authored-By` trailers, "Generated with …" footers, "AI"/agent/model mentions in code, comments, commit messages, PR titles/bodies, or docs? **Default to `off`** (no agent/AI mention anywhere) unless they opt in — people are routinely surprised to find an AI listed as a repo contributor. Carry the answer into the `{{AGENT_ATTRIBUTION}}` slot of the *Attribution* block when `AGENTS.md` is created (step 5). **If `off` and the project uses Claude Code**, also set `"includeCoAuthoredBy": false` in the project's `.claude/settings.json` (create it if absent) — the trailer is added by the harness, so a doc directive alone won't stop it. See [Attribution contract](${CLAUDE_SKILL_DIR}/references/contracts.md#attribution-contract).
20
20
  5. **Entry-point doc.** If `AGENTS.md` / `CLAUDE.md` already exist (step-1 recon), do **not** overwrite — show the user and ask whether to merge or replace. Otherwise create `AGENTS.md` (the cross-agent standard — Codex / Cursor / Devin Desktop / Copilot read it natively) from `${CLAUDE_SKILL_DIR}/references/templates/AGENTS.md`, and symlink `CLAUDE.md -> AGENTS.md` (`ln -s AGENTS.md CLAUDE.md`) for Claude Code — single source, no duplication. For nested context, add a subdir `AGENTS.md` (+ a `CLAUDE.md` symlink beside it for Claude Code).
21
- 6. **Deploy `docs/ai/`.** Create every `docs/ai/` file + `pages/` + the seed `adr/` store from `${CLAUDE_SKILL_DIR}/references/templates/` (the template loop deploys each non-`AGENTS.md`, non-`adr-record.md` template — `adr-record.md` is a skill-home ADR authoring reference, never deployed). This deploys the HOT ADR window **`docs/ai/decisions.md`** and the seed navigator **`docs/ai/adr/log.md`** (its `adr/` subdir copies in wholesale), the `.md` docs, **and** the three seeded, user-editable strict-JSON configs: **`docs/ai/orchestration.json`** (the per-project recipe defaults the `procedures` advisor reads), **`docs/ai/gates.json`** (the project's gate declaration — an empty list to fill with its own verification commands, consumed by `${CLAUDE_SKILL_DIR}/references/modes/gates.md`), and **`docs/ai/verification-profile.json`** (the OPTIONAL fold-completeness verification profile — its seeded default reproduces the composition root's V8 + node:test behaviour, so a project deletes it to fall back to exactly that, or edits it for another language/runner)). Keep each `.md` file's frontmatter (`type / lastUpdated / scope / staleAfter / owner / maxLines`); the `.json` seeds carry no frontmatter (the docs cap-validator globs `*.md` only, so they are inherently skipped).
21
+ 6. **Deploy `docs/ai/`.** Create every `docs/ai/` file + `pages/` + the seed `adr/` store from `${CLAUDE_SKILL_DIR}/references/templates/` (the template loop deploys each non-`AGENTS.md`, non-`adr-record.md` template — `adr-record.md` is a skill-home ADR authoring reference, never deployed). This deploys the HOT ADR window **`docs/ai/decisions.md`** and the seed navigator **`docs/ai/adr/log.md`** (its `adr/` subdir copies in wholesale), the `.md` docs, **and** the four seeded, user-editable strict-JSON configs: **`docs/ai/orchestration.json`** (the per-project recipe defaults the `procedures` advisor reads), **`docs/ai/gates.json`** (the project's gate declaration — an empty list to fill with its own verification commands, consumed by `${CLAUDE_SKILL_DIR}/references/modes/gates.md`), **`docs/ai/verification-profile.json`** (the OPTIONAL fold-completeness verification profile — its seeded default reproduces the composition root's V8 + node:test behaviour, so a project deletes it to fall back to exactly that, or edits it for another language/runner), and **`docs/ai/autonomy.json`** (the per-project autonomy policy — seeded SPARSE with the onboarding note only, so it is exactly the computed defaults until the user declares levels via `/agent-workflow-kit set-autonomy` or by hand). Keep each `.md` file's frontmatter (`type / lastUpdated / scope / staleAfter / owner / maxLines`); the `.json` seeds carry no frontmatter (the docs cap-validator globs `*.md` only, so they are inherently skipped).
22
22
  7. **Fill templates** per the table below.
23
23
  8. **Install enforcement (Node projects).** Copy `${CLAUDE_SKILL_DIR}/references/scripts/*.mjs` (+ `*.test.mjs`) into the project's `scripts/`. They self-configure (project name from `package.json`, hierarchical/on-demand sections auto-discovered). **If the project has no Node runtime** (step-1 recon), skip this step and the hook in step 9 — follow the cap/archive/index policy manually, or port the scripts to the project's language.
24
24
  9. **Wire / hide** per visibility (see [Visibility contract](${CLAUDE_SKILL_DIR}/references/contracts.md#visibility-contract)). Install the pre-commit hook (Node projects): `node scripts/install-git-hooks.mjs`. If the installer reports a pre-existing non-marker hook, stop and ask the user to merge it manually rather than overwriting.
@@ -9,7 +9,8 @@ The DOC-PARITY lint (BUGFREE-3 / AD-049, session-economics item (b)) — the det
9
9
 
10
10
  **What it checks (the closed registry).** The numeric/version tokens are IMPORTED live from the tools — never re-typed in the lint — so the registry itself can never go stale:
11
11
  - `references/modes/review-ledger.md` carries `SCHEMA_VERSION` (schema v4), `HARD_MAX` (the hard-max ceiling of 3), `DEFAULT_DIFF_CAP` (the default 400 diff cap), `REVIEW_CAP` (cap ≤2), and the ledger vocabulary sourced from the schema's own `V4_CLASSES` / `V4_OVERRIDE_SCOPES` Sets plus the `gate-run` kind (`size-cap`, `refuted`, `gate-run`, `red-proof`, `oracle-change`, `fixable-bug`, `inherent-layer-residual`, `escalate`);
12
- - `references/modes/fold-completeness.md` carries `RESULT_SCHEMA_VERSION` (fold RESULT schema v4).
12
+ - `references/modes/fold-completeness.md` carries `RESULT_SCHEMA_VERSION` (fold RESULT schema v4);
13
+ - `references/modes/autonomy-doctor.md` carries the doctor's frozen D7 contract (AD-044 Plan 2): every live EXIT-table phrase (`` `0` ready `` … `` `6` unsupported / untrusted ``), every status token (sourced from the exported `STATUS`), and the trusted-dir allowlist (`TRUSTED_DIRS`).
13
14
 
14
15
  **Why the modes/*.md docs and NOT the tool HELP strings.** Every tool's HELP INTERPOLATES the same constant (`the ${DEFAULT_DIFF_CAP}-line diff cap`), so it can never drift from the code — there is nothing to check there. The hand-authored contract prose in `references/modes/*.md` is the surface that DOES drift, so that is exactly what this lint pins. Change a constant and the current-value token stops appearing in the lagging doc → the gate fails, forcing the doc update **in the same edit as the code** (the §2.6 "contract docs change in the same edit as code" rule, mechanized).
15
16
 
@@ -1,13 +1,14 @@
1
1
  ### Mode: grounding
2
2
 
3
- The **grounded-review facts assembler** (AD-038) — an ungrounded `agy` review GUESSES, and while the grounding contract is mechanized (`agy-review code --facts @f`), populating the facts file was a manual chore. This mode emits the two **mechanical** halves of a facts payload; the orchestrator still owns any judgment-bearing additions. **Catalogued honestly as a WRITER** — `--out <path>` writes one file — with the invariant: `--out` accepts **only gitignored / out-of-repo scratch destinations** and REFUSES a tracked path AND an in-repo not-ignored path (a new untracked file would itself move the review fingerprint the facts are about to ground); **stdout is the default**. It never commits and never runs a subscription CLI.
3
+ The **grounded-review facts assembler** (AD-038) — an ungrounded `agy` review GUESSES, and while the grounding contract is mechanized (`agy-review code --facts @f`), populating the facts file was a manual chore. This mode emits the **mechanical** facts sources of a payload (constraints / autonomy / plan / ledger digest); the orchestrator still owns any judgment-bearing additions. **Catalogued honestly as a WRITER** — `--out <path>` writes one file — with the invariant: `--out` accepts **only system-temp destinations outside the repo ($TMPDIR / /tmp — rewritable scratch) or a FRESH gitignored in-repo path (create-only, exclusive write)** and REFUSES everything else: a tracked path, an in-repo not-ignored path (a new untracked file would itself move the review fingerprint the facts are about to ground), an EXISTING in-repo file even when gitignored (the `.env` clobber class — this writer is bridge-tier auto-allowable), any other outside-repo destination, and symlink/non-regular leaves; **stdout is the default**. It never commits and never runs a subscription CLI.
4
4
 
5
- Run `node ${CLAUDE_SKILL_DIR}/tools/grounding.mjs [--constraints] [--plan <path>] [--ledger-summary] [--reserve-bytes <n>] [--out <path>]`:
5
+ Run `node ${CLAUDE_SKILL_DIR}/tools/grounding.mjs [--constraints] [--autonomy] [--plan <path>] [--ledger-summary] [--reserve-bytes <n>] [--out <path>]`:
6
6
 
7
7
  1. **`--constraints`** — slice the root `AGENTS.md` **Hard Constraints** section, verbatim and whole (exactly ONE matching heading; zero or several is a loud STOP, never a guess — the marker-slot discipline).
8
- 2. **`--plan <path>`**extract the plan's decision-bearing canonical sections, verbatim + whole: `## Approach` (REQUIRED its "What we are NOT doing" text rides inside; it is not a heading in canon) and `## Verification` (REQUIRED STOP if missing), plus `## Decisions (locked)` when present (the optional engine §7 heading); a DUPLICATE heading is always a STOP.
9
- 3. **`--ledger-summary`** (BUGFREE-3 / AD-049) append a COMPUTED review-ledger digest for the SINGLE in-flight `plan-execution` segment: the round/origin/classification/verdict/override counts (filtered to that loop + base unrelated loops excluded) plus a terse per-round render. "Computed, not remembered" facts the reviewer sees the loop's own history without the orchestrator hand-copying it. A loud STOP unless exactly one plan is in flight; read-only (the ledger is never written here).
10
- 4. **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.
11
- 5. Feed the result to the wrapper: `agy-review code --facts @<out>`. The `procedures` advisor renders this invocation as a concrete pre-step whenever the resolved review dispatch includes agy populated with the in-flight plan path when exactly one plan is in flight.
8
+ 2. **`--autonomy`** (AD-044 Plan 3) append the COMPUTED effective autonomy policy: the shared resolver (`resolveAutonomy`) over the **git-top** `docs/ai/autonomy.json` renders every red-line + per-activity level with a stated source line. An ABSENT file is exit 0 the computed defaults ARE the effective policy (unlike `velocity-profile --autonomy`, which writes settings and refuses an undeclared policy); a malformed/unreadable policy fails CLOSED (exit 1). Informational for the reviewing backend enforcement stays the OS sandbox + the orchestrator. Rides between the constraints and the plan sections.
9
+ 3. **`--plan <path>`**extract the plan's decision-bearing canonical sections, verbatim + whole: `## Approach` (REQUIRED its "What we are NOT doing" text rides inside; it is not a heading in canon) and `## Verification` (REQUIRED STOP if missing), plus `## Decisions (locked)` when present (the optional engine §7 heading); a DUPLICATE heading is always a STOP.
10
+ 4. **`--ledger-summary`** (BUGFREE-3 / AD-049) append a COMPUTED review-ledger digest for the SINGLE in-flight `plan-execution` segment: the round/origin/classification/verdict/override counts (filtered to that loop + base unrelated loops excluded) plus a terse per-round render. "Computed, not remembered" facts — the reviewer sees the loop's own history without the orchestrator hand-copying it. A loud STOP unless exactly one plan is in flight; read-only (the ledger is never written here).
11
+ 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.
12
+ 6. Feed the result to the wrapper: `agy-review code --facts @<out>`. The `procedures` advisor renders this invocation as a concrete pre-step whenever the resolved review dispatch includes agy — populated with the in-flight plan path when exactly one plan is in flight.
12
13
 
13
- **Invariants:** writer (writes at most the ONE `--out` scratch file — gitignored / out-of-repo only) · never commits · never runs a subscription CLI · verbatim slices only (assembly is mechanical; facts judgment stays with the orchestrator).
14
+ **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 only (assembly is mechanical; facts judgment stays with the orchestrator).
@@ -0,0 +1,14 @@
1
+ ### Mode: recommendations
2
+
3
+ The **read-only deployment advisor** — the deterministic section every `upgrade` run ends with, also invocable on its own. It computes what in THIS deployment is configured sub-optimally (allowlist not seeded, autonomy render drifted, sandbox unavailable, gates undeclared, bridge friction, sandbox-mask clutter) and renders each item as **{what is sub-optimal · the benefit in ONE plain line · the exact consent-gated apply one-liner}**. The tool computes; **you paste the section VERBATIM** (the `composeStatusLine` precedent) — you compose nothing factual.
4
+
5
+ Run `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd <project-root> [--json]`:
6
+
7
+ 1. **`--cwd` is REQUIRED** — the target project is explicit, never inferred from the shell's current directory (a subdirectory invocation still advises on the named root).
8
+ 2. **Paste the whole rendered section verbatim**, starting at its `## Recommendations (agent-workflow)` header. It renders **present-even-when-empty**: with everything optimal the body is exactly `no recommendations — flow optimal.` A failed probe renders as a stated `⚠ skipped item …` line — never a crash, never a fabricated item.
9
+ 3. **The apply-through-agent lane (consent-first):** after pasting, OFFER to apply; the user picks items in plain language; you run **EXACTLY the rendered one-liners — no improvisation** (each writer keeps its own consent semantics: previews, `--apply` flags, refusals). An item marked **HAND-APPLY** (the network-allowlist item) is **never run by you and never written by the kit** — the user pastes it by hand if they accept the stated risk; the hosts come from each bridge's `capability.json` `networkHosts` (the single documentation source).
10
+ 4. Benefit lines are frozen tool data, fact-true: 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**, and risk-bearing items state their risk in the same line.
11
+
12
+ **Invariants:** read-only (never writes, never commits, never runs a subscription CLI) · `--cwd` required · present-even-when-empty · probe failures degrade to stated skip lines · apply one-liners are cwd-independent (absolute tool paths + a pinned `--cwd`; the sandbox-provision item pins via a `cd <root> &&` prefix — the doctor reads its cwd; the ONE exception is the `set-autonomy` item, a conversational skill invocation explicitly labeled *run IN the target project*) · the kit never seeds `sandbox.network.allowedDomains` / `sandbox.filesystem.allowWrite` (hand-apply territory, risk stated).
13
+
14
+ **Exit codes:** `0` report rendered (items or the empty state); `1` error (e.g. `--cwd` is not a directory); `2` usage.
@@ -1,6 +1,6 @@
1
1
  ### Mode: review-state
2
2
 
3
- Read-only **review-receipt checker** (AD-038) — it makes *"reviewed ≠ shipped"* mechanically detectable. The bridge review wrappers (`codex-review` / `agy-review`, from bridge version 2.2.0) append one receipt line per **successful** review to a file **inside the git dir** (`<git dir>/agent-workflow-review-receipts.jsonl` — never committable by construction; `AW_REVIEW_RECEIPTS` overrides). This mode resolves the effective `plan-execution.review` recipe (the SAME config + read-only detector the `procedures` advisor reads), recomputes the canonical **uncommitted-state fingerprint** (staged + unstaged + untracked-not-ignored contents — exactly the review-payload domain; the prose definition lives in each bridge's `capability.json` review contract, implementations cross-checked by the kit's fingerprint-parity test), and reports, per recipe-named backend, whether a **fresh, grounded, current-fingerprint** receipt exists. It **never writes, never commits, never runs a subscription CLI**; it does spawn **read-only `git` queries** to compute the fingerprint — stated honestly (that is still read-only, but it is a subprocess).
3
+ Read-only **review-receipt checker** (AD-038) — it makes *"reviewed ≠ shipped"* mechanically detectable. The bridge review wrappers (`codex-review` / `agy-review`, from bridge version 2.2.0) append one receipt line per **successful** review to a file **inside the git dir** (`<git dir>/agent-workflow-review-receipts.jsonl` — never committable by construction; `AW_REVIEW_RECEIPTS` overrides). This mode resolves the effective `plan-execution.review` recipe (the SAME config + read-only detector the `procedures` advisor reads), recomputes the canonical **uncommitted-state fingerprint** (staged + unstaged + untracked-not-ignored contents — exactly the review-payload domain; never-committable untracked paths — character/block devices, FIFOs, sockets — are excluded from the domain entirely, so sandbox-injected device masks can never move the fingerprint; the prose definition lives in each bridge's `capability.json` review contract, implementations cross-checked by the kit's fingerprint-parity test), and reports, per recipe-named backend, whether a **fresh, grounded, current-fingerprint** receipt exists. It **never writes, never commits, never runs a subscription CLI**; it does spawn **read-only `git` queries** to compute the fingerprint — stated honestly (that is still read-only, but it is a subprocess).
4
4
 
5
5
  Run `node ${CLAUDE_SKILL_DIR}/tools/review-state.mjs [--check] [--json]`:
6
6
 
@@ -0,0 +1,15 @@
1
+ ### Mode: sandbox-masks
2
+
3
+ **Cosmetic exclude lane for sandbox-injected device masks** (AD-044). An OS sandbox (Claude Code) injects character-device masks into the work tree (`.bashrc`, `.gitconfig`, `.vscode`, …); git lists them as untracked noise. The **review domain already ignores them by construction** — never-committable untracked classes (character/block devices, FIFOs, sockets) are excluded from the fingerprint, the assembled review payload, and the clean checks in both bridge wrappers and the kit checker. This mode is the optional **cosmetic** half: it hides the masks from `git status` (and every other `--exclude-standard` untracked walk) via **one managed fenced block** in the file `git rev-parse --git-path info/exclude` names.
4
+
5
+ Run `node ${CLAUDE_SKILL_DIR}/tools/sandbox-masks.mjs [--cwd <project-root>]`:
6
+
7
+ 1. **Flagless → READ-ONLY probe/preview.** Derives the CURRENT mask set from the **unfiltered** untracked walk (`git ls-files --others -z`, without standard excludes — an already-hidden mask stays visible to a rerun) plus lstat classification. Only the never-committable classes are ever candidates; tracked / regular / directory / symlink / gitlink / missing paths can never enter the block **by construction**. The probe also **revalidates** the existing fenced entries and loudly flags any that became a REAL path. It prints the exact apply one-liner.
8
+ 2. **`--apply` → consent-gated FULL-BLOCK REPLACE** from a fresh derivation — stale masks drop by construction, never append-only. Run it **inside the sandbox** (masks are visible only there). An apply whose derivation is EMPTY while a non-empty block exists refuses loudly (you are probably outside the sandbox) unless `--clear` is also given; an empty derivation with no block is a stated no-op. `--clear` always means **remove the managed block** — it takes precedence over the derivation, even while masks are visible.
9
+ 3. **Writes ONLY its own fenced block** — never `.gitignore`, never a global excludesFile, never outside the fence. A malformed fence (start without end, duplicated markers) **fails closed**: loud report, file untouched. The fence is separate from the hidden-mode reconcile's block.
10
+
11
+ **Where the need surfaces on its own (no standing detector):** `review-state --check` prints one non-failing notice with this mode's apply one-liner whenever it observes filtered-class untracked paths, and the upgrade **Recommendations** section carries the same item (the probe is exported to the advisor — `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`) — a NEW mask appearing after a sandbox update surfaces its own fix at the next check or upgrade.
12
+
13
+ **Watch note (D5):** an exclude rule hides a path from `git status` **AND from bulk staging** — a real file at an excluded path is silently skipped by `git add -A`/`git add .` (an explicit `git add <path>` refuses without `-f`), so it would stay out of your commits; `.git/info/exclude` never warns. Before creating a REAL file at a masked path (e.g. a real `.vscode/`), delete the matching line from the managed block first — the probe flags exactly this case.
14
+
15
+ **Invariants:** flagless run is read-only · `--apply` writes only the managed block in the repo-local exclude file · probe-derived membership, never a hardcoded list · fail-closed on a malformed fence · never commits, never touches `.gitignore` or any global git config.
@@ -4,17 +4,17 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
4
4
 
5
5
  1. Read `docs/ai/.workflow-version` (the project's stamped lineage). If missing, treat as a pre-versioned deployment and offer to re-bootstrap conservatively.
6
6
  2. **Never-downgrade gate — FIRST, before any write.** Compare the stamp to the **deployment-lineage head** (`2.0.0` — NOT this kit's package version). If the stamp is **greater than the head** or unparseable → **STOP and report**; do not touch a newer / unknown deployment at all (not even the methodology slot). This STOP is one of the few places the number is actionable (*Version disclosure* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`): show the user **the `docs/ai` structure version** their deployment carries versus the one this kit expects, plus the plain one-line two-axes note — naming it the structure version, **never** "lineage head".
7
- 3. **Reconcile the bounded pointers — stamp-independent, BEFORE the equal-head short-circuit.** Reached only when the stamp **≤ head**. Run `node ${CLAUDE_SKILL_DIR}/tools/inject-methodology.mjs reconcile <project>/AGENTS.md`. ONE call reconciles **two** pointers — the **workflow-methodology** pointer and, right below it, the **orchestration-recipes** pointer (Solo / Reviewed / Council / Delegated, routing to `/agent-workflow-kit recipes`) — and is filled on **every** upgrade, idempotently (zero-diff when both are already present + filled), so even a legacy / current **`2.0.0`** deployment gains them **without a lineage-head bump or a migration** (the deployment-lineage head stays `2.0.0`; the `agent-workflow-memory` **package** template did get a docs-only headroom trim for the second pointer, but no deployed-`docs/ai` structure changed). Per slot it inserts an empty pair at its anchor if absent, preserves a customized pair verbatim, and STOPs (never edits) on a malformed pair, a missing / duplicate anchor, or **when a fill is needed but the installed `agent-workflow-engine` is absent/invalid** (both fragments are read live from it — see the distinct outcomes below).
7
+ 3. **Reconcile the bounded pointers — stamp-independent, BEFORE the equal-head short-circuit.** Reached only when the stamp **≤ head**. Run `node ${CLAUDE_SKILL_DIR}/tools/inject-methodology.mjs reconcile <project>/AGENTS.md`. ONE call reconciles **three** pointers — the **workflow-methodology** pointer, the **orchestration-recipes** pointer (Solo / Reviewed / Council / Delegated, routing to `/agent-workflow-kit recipes`) right below it, and the **autonomy-policy** pointer (the `docs/ai/autonomy.json` read contract, routing to `/agent-workflow-kit set-autonomy`) below that — and is filled on **every** upgrade, idempotently (zero-diff when all are already present + filled), so even a legacy / current **`2.0.0`** deployment gains them **without a lineage-head bump or a migration** (the deployment-lineage head stays `2.0.0`; the `agent-workflow-memory` **package** template did get docs-only headroom trims for the chained pointers, but no deployed-`docs/ai` structure changed). Per slot it inserts an empty pair at its anchor if absent, preserves a customized pair verbatim, and STOPs (never edits) on a malformed pair, a missing / duplicate anchor, or **when a fill is needed but the installed `agent-workflow-engine` is absent/invalid** (the fragments are read live from it — see the distinct outcomes below).
8
8
 
9
9
  **Classify the exit — there are THREE non-zero exits + one soft in-band skip; handle each differently:**
10
10
 
11
- (a) **Soft, reported skip of the orchestration pointer (CONTINUE the upgrade).** The orchestration pointer is the less-critical second pointer; when it can't be added right now `reconcile` exits **zero**, keeps the methodology pointer, and **reports the skip on stdout** (the `… skipped …` line) — never silent (Hard Constraint). Two reasons: **(i)** the methodology pointer fits but adding the orchestration pointer would push the file past the `AGENTS.md` 100-line cap; or **(ii)** the installed `agent-workflow-engine` is **present but too old** to ship the recipes fragment (`<1.2.0`) — it can still supply the methodology pointer, so only the recipes pointer is withheld. Report it in the successful-exit report (**step 4** equal-head, else **step 8**) in plain language, e.g. *"The orchestration-recipes pointer wasn't added — the entry point is at its 100-line limit / your methodology engine is older than the recipes feature. The recipes are still available any time via `/agent-workflow-kit recipes`; to add the pointer, trim the entry point and/or refresh the engine with `npx @sabaiway/agent-workflow-engine@latest init`, then re-run upgrade."* (The separate case where the **methodology** pointer ITSELF can't fit the cap is a non-zero exit that changes nothing — continue without either pointer, same plain-language framing.)
11
+ (a) **Soft, reported skip of a CHAINED pointer — orchestration and/or autonomy (CONTINUE the upgrade).** The chained pointers are the less-critical ones; when one can't be added right now `reconcile` exits **zero**, keeps every prior fill, and **reports each skip on stdout** (the `… skipped …` line) — never silent (Hard Constraint). Three reasons: **(i)** the prior pointers fit but adding this one would push the file past the `AGENTS.md` 100-line cap; **(ii)** the installed `agent-workflow-engine` is **present but too old** to ship that fragment (`<1.2.0` lacks the recipes one; every engine before the autonomy release lacks the autonomy one) — it can still supply the earlier pointers, so only that pointer is withheld; or **(iii)** — autonomy only — its **anchor is absent** because the orchestration pair is itself absent or was skipped, so the autonomy pointer has nowhere to chain (add the orchestration pointer first, then re-run). Report it in the successful-exit report (**step 4** equal-head, else **step 8**) in plain language, e.g. *"The orchestration-recipes / autonomy pointer wasn't added — the entry point is at its 100-line limit / your methodology engine is older than that feature. The recipes stay available via `/agent-workflow-kit recipes` and the autonomy policy via `/agent-workflow-kit set-autonomy`; to add the pointer, trim the entry point and/or refresh the engine with `npx @sabaiway/agent-workflow-engine@latest init`, then re-run upgrade."* (The separate case where the **methodology** pointer ITSELF can't fit the cap is a non-zero exit that changes nothing — continue without the pointers, same plain-language framing.)
12
12
 
13
- (b) **Malformed pair / missing-or-duplicate anchor (either pointer) — a hard STOP (do NOT continue).** A non-zero exit whose message names a marker/anchor problem; never soft-skip it.
13
+ (b) **Malformed pair / missing-or-duplicate anchor (any pointer) — a hard STOP (do NOT continue).** A non-zero exit whose message names a marker/anchor problem; never soft-skip it. (The one deliberate exception is (a)(iii): the autonomy pointer's ABSENT anchor is the chained soft skip, exit zero — a reported skip, not this STOP.)
14
14
 
15
- (c) **`methodology engine not found/invalid …` — a hard STOP (do NOT continue).** A fill was needed but the installed `agent-workflow-engine` is **fully absent/invalid** — it can supply **neither** fragment (distinct from (a)(ii), where the engine is valid but merely too old for the recipes one). Report it in plain language with the one-line install command `npx @sabaiway/agent-workflow-engine@latest init` (or note that `npx @sabaiway/agent-workflow-kit@latest init` installs the engine for you), then re-run upgrade once it is present. **Never** treat (c) as a soft-skip (a) — mis-handling it would silently drop the methodology pointer (a no-silent-failures violation). (b) and (c) STOP the upgrade; only (a) continues.
15
+ (c) **`methodology engine not found/invalid …` — a hard STOP (do NOT continue).** A fill was needed but the installed `agent-workflow-engine` is **fully absent/invalid** — it can supply **no** fragment (distinct from (a)(ii), where the engine is valid but merely too old for a chained one). Report it in plain language with the one-line install command `npx @sabaiway/agent-workflow-engine@latest init` (or note that `npx @sabaiway/agent-workflow-kit@latest init` installs the engine for you), then re-run upgrade once it is present. **Never** treat (c) as a soft-skip (a) — mis-handling it would silently drop a pointer (a no-silent-failures violation). (b) and (c) STOP the upgrade; only (a) continues.
16
16
 
17
- **No-Node project:** the fragments live only in the **installed `agent-workflow-engine`** (`references/methodology-slot.md` + `references/orchestration-slot.md`, under `~/.claude/skills/agent-workflow-engine` or `$AGENT_WORKFLOW_ENGINE_DIR`) — there is no bundled copy, and a No-Node host cannot run the `npx` engine install. Open `AGENTS.md` and classify **each** pointer by hand: a **filled / customized** pair → leave it verbatim (no engine needed); a **malformed** pair (not exactly one ordered `start → end`) → STOP, do not edit. A pair that needs filling — **absent markers OR a present-but-empty pair** — needs the engine's fragment, so: if the engine is **not installed**, that pointer **cannot be added** — report it plainly (the methodology is already in `docs/ai/agent_rules.md`; the recipes are available via `/agent-workflow-kit recipes`; install the engine to add the pointers). If the engine **is** present, **count the lines first** — if adding/filling would take the file over 100 lines, **skip that pointer and report the skip** (methodology first, then orchestration; the orchestration pair sits right under the methodology end marker). Fill each empty pair from its engine fragment (`methodology-slot.md` / `orchestration-slot.md`) — never inline a copy (that would re-create the retired mirror).
17
+ **No-Node project:** the fragments live only in the **installed `agent-workflow-engine`** (`references/methodology-slot.md` + `references/orchestration-slot.md` + `references/autonomy-slot.md`, under `~/.claude/skills/agent-workflow-engine` or `$AGENT_WORKFLOW_ENGINE_DIR`) — there is no bundled copy, and a No-Node host cannot run the `npx` engine install. Open `AGENTS.md` and classify **each** pointer by hand: a **filled / customized** pair → leave it verbatim (no engine needed); a **malformed** pair (not exactly one ordered `start → end`) → STOP, do not edit. A pair that needs filling — **absent markers OR a present-but-empty pair** — needs the engine's fragment, so: if the engine is **not installed**, that pointer **cannot be added** — report it plainly (the methodology is already in `docs/ai/agent_rules.md`; the recipes are available via `/agent-workflow-kit recipes`; the autonomy policy via `/agent-workflow-kit set-autonomy`; install the engine to add the pointers). If the engine **is** present, **count the lines first** — if adding/filling would take the file over 100 lines, **skip that pointer and report the skip** (methodology first, then orchestration, then autonomy; each chained pair sits right under the previous pair's end marker). Fill each empty pair from its engine fragment (`methodology-slot.md` / `orchestration-slot.md` / `autonomy-slot.md`) — never inline a copy (that would re-create the retired mirror).
18
18
 
19
19
  **Hidden-mode footprint reconcile — stamp-independent, same gate, BEFORE the equal-head short-circuit (D9 / AD-014).** A deployment does not record whether it chose `hidden`, so first **infer visibility**: `node ${CLAUDE_SKILL_DIR}/tools/hide-footprint.mjs --dir <project> --reconcile --dry-run` (writes **zero bytes**). It reports one of — **visible** (the entry point is tracked) → nothing to do; **ambiguous** (untracked but not ignored — could be a fresh uncommitted repo, or a hide that broke) → **ASK** the user which it is, never guess; **hidden** → re-run without `--dry-run` to migrate any older **machine-global** hide to the **project-local** `.git/info/exclude` (one managed block; folds in the legacy `.claude/skills/` line), idempotently (a clean re-run is zero-diff). Handle its surfaced paths exactly as bootstrap step 9 (`${CLAUDE_SKILL_DIR}/references/modes/bootstrap.md`) (already-committed → show `git rm --cached`, ask before `--include`; generic-name present file → ask; **leftover machine-wide ignore block → ASK before `--remove-global`**, default keep + report). No Node on the agent host / Windows → as bootstrap step 9 (`${CLAUDE_SKILL_DIR}/references/modes/bootstrap.md`). This runs on **every** hidden upgrade, like the methodology slot — no lineage-head bump, no migration file.
20
20
 
@@ -24,6 +24,8 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
24
24
 
25
25
  **Verification-profile ensure (seed-if-missing) — stamp-independent, same gate, BEFORE the equal-head short-circuit.** Ensure `docs/ai/verification-profile.json` exists: **create it from `${CLAUDE_SKILL_DIR}/references/templates/verification-profile.json` if missing** (the kit's OWN template twin, so the fallback/stale-memory path still gains the OPTIONAL fold-completeness profile); **an existing file is preserved byte-for-byte** (a project may have edited it for its language/runner). An ABSENT profile reproduces the default V8 + node:test behaviour, so this ensure only ADDS the opt-in default. Report it in the step 4 / step 8 report (*seeded* / *already present*). Like the config + gate ensures, no lineage-head bump or migration file (a `.json`, outside the docs cap-validator).
26
26
 
27
+ **Autonomy-declaration ensure (seed-if-missing) — stamp-independent, same gate, BEFORE the equal-head short-circuit.** Ensure `docs/ai/autonomy.json` exists: **create it from `${CLAUDE_SKILL_DIR}/references/templates/autonomy.json` if missing** (the kit's OWN template twin, mirrored from memory — so a stale memory never silently loses the seed); **an existing file is preserved byte-for-byte** (a declared policy is authored content — never clobbered, never refreshed in place). The seed is SPARSE (the onboarding note only) and **defaults-equivalent** — deploying it never changes behavior (the computed defaults stay the policy until the user declares levels with `/agent-workflow-kit set-autonomy` or by hand). Report it in the step 4 / step 8 success report (*seeded* / *already present, preserved*). Like the other config ensures, no lineage-head bump or migration file (a `.json`, outside the docs cap-validator).
28
+
27
29
  **Enforcement-script ensure (seed-if-missing) — stamp-independent, same gate, BEFORE the equal-head short-circuit.** A deployment older than the ADR-cascade feature has no `scripts/archive-decisions.mjs`, and an equal-head exit would otherwise never deliver it. Ensure the pair exists in the project's `scripts/`: **copy `archive-decisions.mjs` + `archive-decisions.test.mjs` from `${CLAUDE_SKILL_DIR}/references/scripts/` if missing** (the kit's own fallback copies — byte-identical to the memory canon by the mirror guard); **an existing file is preserved, never overwritten** (drift repair belongs to a lineage migration, not this ensure). **OLD ADR-store layout — DETECT FIRST, never auto-migrate (AD-051, Decision 13):** if the project still carries a `docs/ai/history/decisions-archive*.md` monolith (the `adrLayout: "old"` signal `status` surfaces), it is on the RETIRED 3-tier cascade — **do NOT seed or refresh the now one-file-per-ADR rotator here** (the new `archive-decisions.mjs` beside un-migrated monoliths would red their ADR gate). Instead surface a LOUD instruct: run the opt-in **`/agent-workflow-kit migrate-adr-store`** (it snapshots, refreshes the scripts, and migrates in one consent-gated step; previews first, never commits). The seed-if-missing above applies ONLY to a clean layout (no monolith). The deployed pre-commit hook gains the `archive-decisions.mjs --check` line only when the hook itself is next refreshed (re-run `node scripts/install-git-hooks.mjs` after the ensure and it will refuse a non-marker hook as always); an OLD hook without the line stays consistent-safe — the decisions gate is simply not enforced yet, never a broken hook. Skip this ensure on a No-Node project (the scripts are Node enforcement). Report it in the step 4 / step 8 success report (*added* / *already present* / *old ADR layout — migration instructed*).
28
30
 
29
31
  **Placed-bridge refresh — stamp-independent, same gate, BEFORE the equal-head short-circuit.** Run
@@ -54,11 +56,12 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
54
56
  **NEVER writes** it (the file lives outside every kit tree — D2), so an unknown/retired key is
55
57
  flagged + preserved, never edited. Runs on **every** upgrade; exit 0 covers every outcome.
56
58
  4. **Equal-head exit — a real successful-exit report, not a bare stop.** If the stamp **equals** the head, the lineage is up to date — but step 3 (the stamp-independent reconciles) ran first and may have changed things, so this is a proper exit report, not a no-op:
57
- - **Report step 3's outcome in plain language** — for **each** pointer (workflow-methodology and orchestration-recipes) whether it was *added*, was *already present* (nothing changed), or was *skipped because the entry point is over its line limit* (the cap-refusal soft-skip from step 3, with its reason); whether the `docs/ai/orchestration.json` config was *seeded* (created from the template), had its onboarding note *refreshed*, was *already current*, or carried a *customized note that was preserved* (a user edit is never clobbered); whether the `docs/ai/gates.json` gate declaration was *seeded* or was *already present* (preserved byte-for-byte); whether the `docs/ai/verification-profile.json` profile was *seeded* or was *already present* (preserved byte-for-byte); whether the enforcement-script ensure *added* the `archive-decisions` pair to `scripts/`, found it *already present*, or found an *old ADR layout — migration instructed*; the **placed-bridge refresh** outcome — paste the tool's per-bridge lines verbatim (they are already plain: *refreshed* / *already current* / *skipped — not placed* / *could not refresh* + recovery); the **agent-rules lens** outcome (*refreshed* / *already current* / *custom edit preserved + note* / *file absent* / *engine too old* / *over the line cap*); the **bridge-settings reconcile** outcome (paste the tool's line verbatim); and, for a hidden deployment, whether the hidden-mode footprint was *moved to project-local*, was *already project-local* (nothing changed), or needed a question (ambiguous visibility / a leftover machine-wide block). Plain wording only — never the reconcile/slot/anchor/marker terms (the never-leak-kit-internals Gotcha — `${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md`).
59
+ - **Report step 3's outcome in plain language** — for **each** pointer (workflow-methodology, orchestration-recipes and autonomy-policy) whether it was *added*, was *already present* (nothing changed), or was *skipped* (the soft-skip from step 3, with its reason — over the line limit / engine too old / the autonomy pointer's anchor absent); whether the `docs/ai/orchestration.json` config was *seeded* (created from the template), had its onboarding note *refreshed*, was *already current*, or carried a *customized note that was preserved* (a user edit is never clobbered); whether the `docs/ai/gates.json` gate declaration was *seeded* or was *already present* (preserved byte-for-byte); whether the `docs/ai/verification-profile.json` profile was *seeded* or was *already present* (preserved byte-for-byte); whether the `docs/ai/autonomy.json` declaration was *seeded* (the sparse defaults-equivalent note) or was *already present* (preserved byte-for-byte); whether the enforcement-script ensure *added* the `archive-decisions` pair to `scripts/`, found it *already present*, or found an *old ADR layout — migration instructed*; the **placed-bridge refresh** outcome — paste the tool's per-bridge lines verbatim (they are already plain: *refreshed* / *already current* / *skipped — not placed* / *could not refresh* + recovery); the **agent-rules lens** outcome (*refreshed* / *already current* / *custom edit preserved + note* / *file absent* / *engine too old* / *over the line cap*); the **bridge-settings reconcile** outcome (paste the tool's line verbatim); and, for a hidden deployment, whether the hidden-mode footprint was *moved to project-local*, was *already project-local* (nothing changed), or needed a question (ambiguous visibility / a leftover machine-wide block). Plain wording only — never the reconcile/slot/anchor/marker terms (the never-leak-kit-internals Gotcha — `${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md`).
58
60
  - **Never surface the structure number on this exit.** Whatever step 3 did, do **not** recite the `docs/ai` structure version, the internal versioning vocabulary, or the two-axes note here — the number is inert on an equal-head exit; it belongs to *Version disclosure* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md` (shown at the never-downgrade STOP, the explicit status view, or on an explicit ask). Frame the success itself per the final bullet: if step 3 changed anything, say **what changed** in plain human terms; only a pure zero-diff no-op is *settings already current — no update needed*.
61
+ - **Render the mandatory Recommendations section — on this exit too, BEFORE the footer.** Run `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd <project-root>` and paste its output VERBATIM from the `## Recommendations (agent-workflow)` header (present-even-when-empty — with everything optimal the body is exactly `no recommendations — flow optimal.`). Then OFFER the consent-gated applies: the user picks items in plain language and you run EXACTLY the rendered one-liners (a HAND-APPLY item is never run by you) — the full lane in `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`. Pinned order on this exit: Recommendations block → optional applies → report footer → the commit ask (the advisor/apply lane never lands after the commit ask).
59
62
  - **Print the report footer** in the canonical order (version block → one-line backend-status line → welcome mat — the shared contracts in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`; rendered from the helpers, same host-can't-run skip-with-reason). The welcome mat closes on **one** caveat-aware next step (a behind member first, else `setup` / `recipes` / `velocity` / `agents` / `hook`).
60
63
  - **Then ask before committing — never auto-commit.** If step 3 added the slot (or anything else changed), report it and ask. If step 3 was a pure zero-diff no-op and nothing else changed, give the plain **settings already current — no update needed** message (the *Success state* contract in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`) and still print the read-only version block (installed package versions) + backend line — but **no `docs/ai` structure version and no two-axes note** (nothing changed, so the number is inert here).
61
64
  5. Show the relevant `${CLAUDE_SKILL_DIR}/CHANGELOG.md` diff (entries newer than the project's stamp).
62
65
  6. **Collect the migration answers FIRST, then apply.** If `AGENTS.md` is missing BOTH the *Communication language* and *Attribution* blocks — i.e. both blocks are missing (a pre-1.1.0 deployment) — ask the two questions as ONE structured multi-question prompt; record each answer individually, write nothing until ALL are answered, and carry the answers into the migrations below: a migration whose answer was already collected never re-asks (its own "Ask the user" step is the standalone fallback); a single missing block keeps its single ask (step 7). Then apply `${CLAUDE_SKILL_DIR}/migrations/<version>-<slug>.md` in **semver order**, only those newer than the project's stamp. Migrations are **idempotent** — safe to re-run.
63
66
  7. Reconcile drift: add any kernel files/scripts the project is missing; never clobber project-authored content (their `decisions.md`, `known_issues.md`, page specs stay). Any user question a migration raises follows the same rule as bootstrap — **structured multiple-choice where supported** (`AskUserQuestion` in Claude Code), otherwise prose. If `AGENTS.md` has no *Communication language* block (pre-1.1.0 deployment), **ask the user their conversational language** and insert the block — see `migrations/1.1.0-communication-language.md`. If it has no *Attribution* block (pre-1.2.0 deployment), **ask whether the agent may attribute work to itself / AI** and insert the block (defaulting to `off`) — see `migrations/1.2.0-agent-attribution.md`. (An answer already collected by the step-6 batched prompt is carried in — never re-asked here.)
64
- 8. Re-stamp `docs/ai/.workflow-version` to the **deployment-lineage head** (`2.0.0`, not the package version — mechanics unchanged: the atomic write to the stamp file). In the report, **describe what the upgrade changed in plain human terms** — which parts of their `docs/ai` are now different (the migrations that ran), plus the step-3 **placed-bridge refresh** lines (pasted verbatim), the step-3 **agent-rules lens** outcome (same outcome set as step 4), and the step-3 **bridge-settings reconcile** outcome — rather than reciting a version number; **omit the raw structure number**, and do **not** print the two-axes note here (it belongs to *Version disclosure* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`, on demand only). Then **print the report footer** in the canonical order (version block → one-line backend-status line → welcome mat — the shared contracts in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`; rendered from the helpers, same host-can't-run skip-with-reason; the welcome mat closes on one caveat-aware next step). Then **ask before committing**.
67
+ 8. Re-stamp `docs/ai/.workflow-version` to the **deployment-lineage head** (`2.0.0`, not the package version — mechanics unchanged: the atomic write to the stamp file). In the report, **describe what the upgrade changed in plain human terms** — which parts of their `docs/ai` are now different (the migrations that ran), plus the step-3 **placed-bridge refresh** lines (pasted verbatim), the step-3 **agent-rules lens** outcome (same outcome set as step 4), the step-3 **bridge-settings reconcile** outcome, and the step-3 **autonomy-declaration ensure** outcome (*seeded* / *already present, preserved*) — rather than reciting a version number; **omit the raw structure number**, and do **not** print the two-axes note here (it belongs to *Version disclosure* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`, on demand only). Then **render the mandatory Recommendations section**: run `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd <project-root>`, paste its output VERBATIM from the `## Recommendations (agent-workflow)` header (present-even-when-empty: `no recommendations — flow optimal.`), and OFFER the consent-gated applies (run EXACTLY the rendered one-liners; a HAND-APPLY item is never run by you — `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`). Then **print the report footer** in the canonical order (version block → one-line backend-status line → welcome mat — the shared contracts in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`; rendered from the helpers, same host-can't-run skip-with-reason; the welcome mat closes on one caveat-aware next step). Then **ask before committing** — the pinned order on this exit is: Recommendations block → optional applies → report footer → the commit ask.
@@ -4,7 +4,7 @@ The opt-in onboarding **velocity profile** — it seeds a fixed, audited **read-
4
4
 
5
5
  **Version-status routing (like the other writer modes):** read `docs/ai/.workflow-version` first — not-deployed → bootstrap; stamp < `2.0.0` → `upgrade`; stamp > head / unparseable → STOP. The tool enforces this in code too (`--apply` STOPs unless the stamp is the lineage head).
6
6
 
7
- Run `node ${CLAUDE_SKILL_DIR}/tools/velocity-profile.mjs [--dry-run | --apply] [--kit-tools] [--accept-edits] [--cwd <dir>]`:
7
+ Run `node ${CLAUDE_SKILL_DIR}/tools/velocity-profile.mjs [--dry-run | --apply] [--kit-tools] [--bridge-tier] [--accept-edits] [--cwd <dir>]`:
8
8
 
9
9
  1. **`--dry-run` first, always** (the default — changes nothing). It prints: the fixed read-only core it would add; a **read-only advisory** that lists your `package.json` `scripts` as **unaudited candidates you may add BY HAND** (inspect each first) to `.claude/settings.json` / `settings.local.json` — the tool **never** writes them and flags obviously-mutating names as "do not add"; any **pre-existing non-read-only `Bash(...)` entries** to consider removing by hand; and the honest residual notice (below). It STOPs (zero writes) on a symlinked `.claude` / non-regular `settings.json`, malformed settings JSON, or an unsafe `permissions.defaultMode` — `bypassPermissions` or anything outside `default`/`acceptEdits`/`plan`, present in **either** `settings.json` or `settings.local.json`.
10
10
  2. **Ask the opt-ins** via **`AskUserQuestion` where supported** — two separate choices, the safe option FIRST in each. First the **`--kit-tools` tier** (separate from `acceptEdits`; **"core only" remains the default answer** — seed the tier only on an explicit yes, then add `--kit-tools` to the `--apply` re-run). Then the `acceptEdits` opt-in:
@@ -21,6 +21,7 @@ Run `node ${CLAUDE_SKILL_DIR}/tools/velocity-profile.mjs [--dry-run | --apply] [
21
21
  - `node ${CLAUDE_SKILL_DIR}/tools/detect-backends.mjs` (wildcard)
22
22
  - `node ${CLAUDE_SKILL_DIR}/tools/commands.mjs` (wildcard)
23
23
  - `node ${CLAUDE_SKILL_DIR}/tools/review-state.mjs --check` (wildcard)
24
+ - `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd ${PROJECT_ROOT}` (wildcard — the read-only deployment advisor; its rendered apply one-liners are writers and still prompt)
24
25
  - `node ${CLAUDE_SKILL_DIR}/tools/manifest/validate.mjs --strict <skill-dir>` (wildcard)
25
26
  - `node ${CLAUDE_SKILL_DIR}/tools/release-scan.mjs <path>` (wildcard)
26
27
  - `node ${CLAUDE_SKILL_DIR}/tools/run-gates.mjs --cwd ${PROJECT_ROOT}` — **EXACT byte-string only**, and honestly **project-exec, not read-only**: it runs YOUR declared `docs/ai/gates.json` commands — the same trust boundary the opt-in hook grants byte-exact per-cmd. A wildcard would be BROADER than that boundary (`--cwd <dir>` executes another project's declared gates), so the bare cwd-defaulting form, any other `--cwd`, `--only`, and **`--record`** forms all still prompt (`--record` WRITES a gate-run record into the review ledger — a recording run is never auto-approved, AD-048).
@@ -30,6 +31,16 @@ Honesty notes: tier entries get **NO PreToolUse-hook residual coverage** — the
30
31
 
31
32
  **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
33
 
34
+ **The `--bridge-tier` (own opt-in, AD-044).** Seeds what a promptless council review run needs — BOTH surfaces: `permissions.allow` prefix rules AND the wrapper names in `sandbox.excludedCommands` (the harness runs an excluded command OUTSIDE the sandbox — the wrappers need network — so a plain allowlisted invocation triggers no sandbox-bypass approval). Both land in the **project** `.claude/settings.json` — the file this writer owns; an exclusion placed only in `settings.local.json` was live-observed NOT to route the command outside the sandbox (2026-07-11: the wrapper then starts sandboxed and dies on a read-only HOME + a network prompt), so hand-wiring the local file is not a working substitute for this tier. **Honesty note:** a session whose sandbox is imposed by the harness runtime itself (e.g. an IDE-managed session sandbox) may ignore settings-level exclusions entirely — there the wrappers need the session-level sandbox config (or a per-run consented bypass); the tier's seeded posture is correct for the settings-native sandbox and simply prompts again elsewhere (fail-safe, never a silent widening). Each bridge's observed egress hosts are declared in its `capability.json` `networkHosts` — the single documentation source (observed-minimal — a blocked host names itself at run time; read the manifests, this doc deliberately retypes no host list). The kit **never seeds** `sandbox.network.allowedDomains` or `sandbox.filesystem.allowWrite` (bridge council 2026-07-11, both backends concur): a network pre-allow widens egress for EVERY sandboxed command, and a write allowance on CLI state dirs (`~/.codex`, `~/.gemini/…`) would make credential dirs writable to every sandboxed command. Per-bridge picture under a harness-managed sandbox (live-observed 2026-07-11/12): an IDE-managed session sandbox ignores hand-applied `sandbox.network.allowedDomains` / `sandbox.filesystem.allowWrite` in BOTH settings scopes — its own per-host network consents govern egress; the durable zero-prompt lanes there are the session/host sandbox config (hosts from `networkHosts` + the CLI state-dir writes) or the per-run consented bypass. codex additionally needs a writable HOME (EROFS `~/.codex`); note the apex-vs-wildcard nuance — an apex domain is NOT covered by its `*.`-wildcard form, so the manifests carry both forms where observed (the blocked host names itself at run time). The upgrade Recommendations advisor renders exactly this as a HAND-APPLY item with the risk stated (`${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`). Membership is the FROZEN review-wrapper constant, **never** the execution/probe wrappers (`codex-exec`, `agy-run` keep their human prompt — delegated execution is not covered by this consent), and only the **`code` review mode** — a `plan`/`diff` invocation takes a file argument that can point OUTSIDE the repo, so those modes keep their prompt; each wrapper entry derives ONLY when its bridge is **placed on PATH** (an absent bridge is a stated skip). The seeded byte-forms (this list IS the documented-invocation source for the bridge tier):
35
+
36
+ - `Bash(codex-review code:*)` — the code-mode prefix, args wildcard; plus `codex-review` in `sandbox.excludedCommands`
37
+ - `Bash(agy-review code:*)` — the code-mode prefix, args wildcard; plus `agy-review` in `sandbox.excludedCommands`
38
+ - `Bash(node "${CLAUDE_SKILL_DIR}/tools/grounding.mjs":*)` — the grounding pre-step, **double-quoted absolute path**: exactly the byte-form the `procedures` advisor renders, so the pasted pre-step matches the rule (seeded↔rendered byte-parity). It derives ONLY when `agy-review` is placed (the pre-step exists for agy's grounded reviews; codex grounds natively) — a codex-only install never auto-allows this writer. The quoted form is accepted for THIS one tool only — never a general quote allowance; an unseedable kit path (spaces/metacharacters) is a stated skip. Its writer surface is closed by the tool's own guard: `--out` accepts only system-temp scratch (rewritable) or a FRESH gitignored in-repo path (create-only, exclusive write) — tracked, in-repo-not-ignored, EXISTING in-repo (even gitignored), outside-repo non-temp, and symlink/non-regular destinations are all refused.
39
+
40
+ **Consented posture (printed on every `--bridge-tier` run, stated not pretended away):** an auto-allowed review wrapper runs **UNATTENDED** — it reads any repo file it is pointed at and sends the assembled payload to its **subscription backend**; prefix rules cannot inspect arguments, so a code-mode argument that names a readable file (agy's `--facts`/`--decided`) rides the same consent. That is the tier's purpose (unattended council review runs) and its residual. Tier entries get no PreToolUse-hook coverage — the same documented residual class as the autonomy red-line rules. The grounding entry's writer surface is bounded by `grounding.mjs`'s own scratch-destination guard (a tracked or in-repo-not-ignored `--out` is refused by the tool itself).
41
+
42
+ **Invocation shape (why a run still prompts):** a prefix allow rule matches only a **PLAIN invocation starting with the wrapper name** — `codex-review code`, `agy-review code --facts @f`. An env-var prefix (`AGY_PROBE=1 agy-review …`) or a compound chain (`agy-review … && …`; `;`-joined statements) can NEVER match a prefix rule (observed live); output redirects are fine. Drive the wrappers as plain single commands.
43
+
33
44
  **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
45
 
35
46
  ---
@@ -41,6 +52,6 @@ Honesty notes: tier entries get **NO PreToolUse-hook residual coverage** — the
41
52
  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
53
  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
54
  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.
55
+ 4. **`--autonomy` cannot combine** with `--accept-edits`, `--kit-tools`, or `--bridge-tier` (allowlist-mode flags) — a loud usage error.
45
56
 
46
57
  **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.