@sabaiway/agent-workflow-kit 1.46.0 → 1.48.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 (34) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +3 -3
  3. package/SKILL.md +1 -1
  4. package/bridges/antigravity-cli-bridge/SKILL.md +1 -1
  5. package/bridges/antigravity-cli-bridge/bin/agy-review.sh +6 -1
  6. package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +6 -0
  7. package/bridges/antigravity-cli-bridge/capability.json +5 -2
  8. package/bridges/codex-cli-bridge/SKILL.md +1 -1
  9. package/bridges/codex-cli-bridge/bin/codex-exec.sh +20 -0
  10. package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +50 -0
  11. package/bridges/codex-cli-bridge/bin/codex-review.sh +1 -1
  12. package/bridges/codex-cli-bridge/capability.json +5 -2
  13. package/capability.json +1 -1
  14. package/package.json +1 -1
  15. package/references/agents/changelog-skeleton.md +1 -0
  16. package/references/agents/gate-triage.md +1 -0
  17. package/references/agents/mechanical-sweep.md +1 -0
  18. package/references/hooks/gate-approve.mjs +120 -18
  19. package/references/modes/hook.md +6 -1
  20. package/references/modes/recommendations.md +17 -6
  21. package/references/modes/review-ledger.md +2 -1
  22. package/references/modes/upgrade.md +2 -1
  23. package/references/modes/velocity.md +4 -2
  24. package/references/shared/report-footer.md +14 -0
  25. package/references/templates/agent_rules.md +1 -1
  26. package/tools/ack-write.mjs +186 -0
  27. package/tools/detect-backends.mjs +6 -0
  28. package/tools/doc-parity.mjs +7 -0
  29. package/tools/gate-hook.mjs +193 -4
  30. package/tools/procedures.mjs +6 -1
  31. package/tools/recommendations.mjs +171 -17
  32. package/tools/review-ledger-write.mjs +112 -6
  33. package/tools/review-ledger.mjs +1 -1
  34. package/tools/velocity-profile.mjs +25 -12
package/CHANGELOG.md CHANGED
@@ -4,6 +4,82 @@ 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.48.0 — Family-owned neutral ack store + read-prompt-economy hook lane (AD-055, the CLAUDE-CODE-HARNESS-FRICTION cluster)
8
+
9
+ A **feature** release (kit-only — engine 1.17.0, memory 2.3.0, bridges 2.7.0/2.6.0 unchanged) that
10
+ closes two sibling defects where the kit fought the Claude Code host surface. Both land under one ADR
11
+ (AD-055), two commit-anchored segments.
12
+
13
+ - **Part I — the neutral ack store relocates off the host settings schema.** The `sandbox-lane`
14
+ upgrade recommendation converged by writing `agentWorkflow.sandboxLaneAck` into
15
+ `.claude/settings.local.json` — an advertised apply path a Claude Code host blocks twice (the
16
+ Edit-tool settings validator rejects the unknown key; the command sandbox EROFS-denies
17
+ `.claude/settings*.json`). The neutral fingerprint acknowledgement now lives in a **family-owned
18
+ `docs/ai/acks.json`** no host validator guards, written by a new consent-gated **ack writer**
19
+ (`tools/ack-write.mjs`); the legacy settings-scope key is still read for one deprecation window
20
+ (until the next MAJOR). The recommendation's apply line is an executable writer one-liner again.
21
+ - **Part II — the read-prompt-economy hook lane kills read-side Bash prompts at the source.** A
22
+ Claude Code prefix allow rule can never match a `;`/`&&`/`|` COMPOUND even when every segment is
23
+ seeded, so routine read compounds still prompt. The placed gate hook gains an **opt-in read-lane**
24
+ (rung c): with `docs/ai/lanes.json` set to `{ "readLane": true }` (read live per call, fail-closed),
25
+ a command whose every separator-split segment is a plain frozen read-only core command with **zero
26
+ shell metaprogramming** is auto-approved — a conservative closed-world allow bounded by the audited
27
+ core (a standalone opt-in grant). `lanes.json` is a **separate** kit-owned file — `gates.json`, its
28
+ validators and the byte-mirrored template stay untouched. The residual guard (settings-allowed
29
+ singles) additionally trips the bash-5.3 funsub openers, a backslash-newline line-continuation
30
+ splice, and a de-spliced re-scan of quote/backslash/bracket/brace `--output` reconstruction.
31
+ - **`gate-hook --read-lane`** is the consent-gated writer for `lanes.json`: it verifies the placed
32
+ hook is byte-current **and** wired **and** at the deployment stamp head before enabling (a pre-1.48
33
+ hook never reads `lanes.json`), refusing a stale/unwired hook with the delete-to-reseed recovery
34
+ (absolute paths). The upgrade Recommendations advisor surfaces the **read-lane offer** once the hook
35
+ is placed+wired (RISK_NOTED, with a consent-moment posture note; ATTENTION variants when the placed
36
+ hook is stale or missing — no silent dark lane).
37
+ - **Canon honesty.** `velocity.md` (read-side invocation shape), `hook.md` (rung c + `lanes.json` +
38
+ the currency check + delete-to-reseed), the three cheap-agent templates (they grant no Bash — a
39
+ missing `Grep`/`Glob` falls back to the Read tool; a harness-forced Bash read stays plain-single),
40
+ and the README hook row.
41
+
42
+ Reviewed by the codex + agy council across three rounds (agy SHIP ×3; every fixable fold red-first);
43
+ the surviving word-construction-on-a-single major is a documented inherent-layer-residual — a
44
+ string-based residual guard cannot close every shell reconstruction of a write flag without a full
45
+ shell parser or an over-ASK that would defeat the read-prompt-economy goal (rung b is a trust-posture
46
+ convenience, not a sandbox). Dogfooded live on this host: the read-lane currency guard passed on the
47
+ re-placed 1.48 hook and wrote `lanes.json`.
48
+
49
+ ## 1.47.0 — REPORT-FACTS train: live-fact report contract · batched ledger writer · version-sync wrapper lane · sandbox-lanes canon & bridge contract twins (AD-054)
50
+
51
+ A **feature** release (ships with engine 1.17.0, memory 2.3.0, bridges 2.7.0/2.6.0 bundled) that
52
+ bundles three top-of-queue items plus this session's own live prompt-defects into one train, all
53
+ fixed kit-level:
54
+
55
+ - **Report-facts contract (D1/D2).** A binding clause at the point of use: any claim a report makes
56
+ about the CURRENT host or session state — prompts fired, sandbox scope, whether a bypass was
57
+ needed, network reachability, approval counts — must trace to **live tool output** run **this
58
+ session**; with no live signal the claim is **omitted or explicitly marked unverified**; a
59
+ memory/handover snapshot is **context, never report facts**. The full clause lives in
60
+ `references/shared/report-footer.md` (single home); upgrade steps 4/8 and the recommendations
61
+ advisor carry one binding line each, pinned by the new `report-facts-contract.test.mjs`.
62
+ - **Batched ledger writer (D3).** `review-ledger-write.mjs` gains a `batch` verb — one invocation
63
+ applies an ordered record/classify/override list through the SAME single-verb code paths (no forked
64
+ validator). Two passes: the whole envelope is validated structurally first with ZERO writes, then
65
+ ops apply sequentially and fail-fast on the first typed STOP with an honest partial-success report
66
+ (prior ops stay recorded, append-only). One writer call for a records stage instead of ~13.
67
+ - **version-sync wrapper lane (D4).** `version-sync --bump` for a bridge now also rewrites the
68
+ line-anchored `AW_BRIDGE_VERSION` in `bin/*.sh` (closed one-anchor rule — every assignment counted,
69
+ so a shadowing malformed line is caught; a non-canonical anchor or a downgrade is refused with zero
70
+ writes), and the no-flag verify checks it across all four constants (each wrapper + its kit mirror).
71
+ The bridge version constant is now first-class — dogfooded on this very release.
72
+ - **Bridge contract twins + codex-exec detection (D7).** Both bridge manifests gain a typed `notes[]`
73
+ (codex execute = the nested-sandbox limit; agy review = the pre-dispatch host-diff), rendered in the
74
+ `procedures` advisor and each wrapper `--help`, bidirectionally drift-guarded. `codex-exec.sh` now
75
+ detects the nested-sandbox failure class (a sandbox-mechanism token AND a permission/read-only
76
+ failure token together) and emits a stated recovery hint — route codex-exec OUTSIDE the harness
77
+ sandbox ON the observed failure, never a preemptive blanket. The velocity bridge-tier stays
78
+ REVIEW-wrappers-only; delegated execution keeps its human prompt.
79
+ - **Canon twins (D5/D6).** The prompt-economy canon gains a writer-batch clause and two sandbox-lane
80
+ sentences (pre-dispatch host-diff + nested-sandbox honesty), rendered across `orchestration.md` §5,
81
+ the agent-rules lens (re-rendered into both templates), and the kit cost-lanes advisor.
82
+
7
83
  ## 1.46.0 — Recommendations UX rework: verdict-first, shape-capped, user-language; sandbox-lane discoverability (REC-UX-REWORK, AD-053)
8
84
 
9
85
  A **feature** release (ships with engine 1.16.0, memory 2.2.0, bridges 2.6.0/2.5.0 bundled)
package/README.md CHANGED
@@ -238,14 +238,14 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
238
238
  | `/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). `--await [--timeout <s>]` (AD-049) BLOCKS until every recipe-named backend has receipted the current tree — the durable completion signal is the receipt, never a process event — so you wait for the bridges instead of hand-polling. Never writes, never commits, never runs a subscription CLI; it spawns read-only `git` queries to fingerprint the tree — and `git commit --no-verify` stays possible (discipline, not a sandbox). |
239
239
  | `/agent-workflow-kit sandbox-masks` | any time | **cosmetic exclude lane for sandbox device masks** — an OS sandbox (Claude Code) injects character-device masks into the work tree as untracked `git status` noise; the review domain already ignores them **by construction** (never-committable untracked classes — char/block devices, FIFOs, sockets — are excluded from the fingerprint, the assembled review payload, and the clean checks). This mode hides them from `git status` too: flagless = read-only probe (derives the CURRENT mask set from the unfiltered walk + lstat — never a frozen list — and revalidates fenced entries, loudly flagging one that became a real path); `--apply` = consent-gated FULL-BLOCK replace of its own fenced block in `git rev-parse --git-path info/exclude` (stale masks drop by construction; `--clear` always means REMOVE the block — it takes precedence over the derivation). Writes ONLY its fence — never `.gitignore`, never global config; symlinked/non-regular exclude paths and malformed fences fail closed. Watch note: a real file at an excluded path is silently skipped by bulk staging (`git add -A`/`git add .`) — delete the stale line first; the probe flags exactly this case. |
240
240
  | `/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. `--autonomy` (AD-044) appends the COMPUTED effective autonomy policy from the git-top `docs/ai/autonomy.json` (every red-line + per-activity level, stated source line; absent file → the computed defaults ARE the policy, exit 0; a malformed policy fails CLOSED, exit 1). `--ledger-summary` (AD-049) appends a COMPUTED review-ledger digest for the single in-flight segment (rounds · origins · classifications · verdicts · overrides — unrelated loops excluded), so the reviewer sees the loop's own history without hand-copying. Prints to stdout; `--out` writes **one scratch file only** — system-temp outside the repo ($TMPDIR / /tmp, rewritable) or a **fresh** gitignored in-repo path (create-only, exclusive write; an existing in-repo file, even gitignored, is refused — the `.env` clobber class); tracked, not-ignored-in-repo, other outside-repo, and symlink/non-regular destinations are all refused. Never commits, never runs a subscription CLI. |
241
- | `/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, and any recorded **overrides** (`oracle-change` lifts named tampered test files; `red-proof` waives the observed-red proof for exactly one `testId`; v4 adds **`size-cap`** — the exact sanctioned magnitude for a surface over the diff cap, segment-scoped — all loud, durable, auditable waivers, never silent) 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. **Since v4 every record carries `base` = the HEAD commit and the whole loop is SEGMENT-scoped (AD-048):** round numbering, the caps, and every tooth reset ONLY at a gated commit — a multiphase plan records fully while round 4 within one segment stays refused; `gate-run` records (minted by `gates --record`) make gates-before-review a computed precondition; the triage class **`refuted`** is the honest phantom-finding lane (grounds mandatory); `--telemetry` renders counts-only gate-efficacy data across all loops and both ledgers. `--status` replaces the hand-composed per-round tally; `record --from-receipts` (AD-049) DRAFTS the `backends[]` from the current-fingerprint receipts (verdict per backend, counts from the supplied findings) instead of hand-composing them — a recipe-named backend with no receipt is a loud stop; `--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`** (v1..v3 records stay valid on read — old records never enter a segment). The writer refuses a round (past the hard-max, while a triage is pending, or lacking a grounded review receipt) and refuses an override outside its single in-flight loop. Honest residual: records are forgeable — self-discipline, not a security boundary. Never commits, never runs a subscription CLI. |
241
+ | `/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, and any recorded **overrides** (`oracle-change` lifts named tampered test files; `red-proof` waives the observed-red proof for exactly one `testId`; v4 adds **`size-cap`** — the exact sanctioned magnitude for a surface over the diff cap, segment-scoped — all loud, durable, auditable waivers, never silent) 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. **Since v4 every record carries `base` = the HEAD commit and the whole loop is SEGMENT-scoped (AD-048):** round numbering, the caps, and every tooth reset ONLY at a gated commit — a multiphase plan records fully while round 4 within one segment stays refused; `gate-run` records (minted by `gates --record`) make gates-before-review a computed precondition; the triage class **`refuted`** is the honest phantom-finding lane (grounds mandatory); `--telemetry` renders counts-only gate-efficacy data across all loops and both ledgers. `--status` replaces the hand-composed per-round tally; `record --from-receipts` (AD-049) DRAFTS the `backends[]` from the current-fingerprint receipts (verdict per backend, counts from the supplied findings) instead of hand-composing them — a recipe-named backend with no receipt is a loud stop; a **`batch`** verb applies an ordered list of record/classify/override ops in ONE writer call (the prompt-economy lane — the whole envelope is validated structurally first with zero writes, then ops apply sequentially and fail-fast; prior ops stay recorded, append-only); `--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`** (v1..v3 records stay valid on read — old records never enter a segment). The writer refuses a round (past the hard-max, while a triage is pending, or lacking a grounded review receipt) and refuses an override outside its single in-flight loop. Honest residual: records are forgeable — self-discipline, not a security boundary. Never commits, never runs a subscription CLI. |
242
242
  | `/agent-workflow-kit fold-completeness` | any time | **fold-completeness gate** — attests the review loop's folded fixes were proven the HONEST way (no fix theater): the runner executes your suite ONCE under `NODE_V8_COVERAGE`, checks every changed executable line is **executed**, probes every bound `testId` N times (`AW_FOLD_RERUNS`), records content hashes, and scans the test surface for tamper; the `--red` verb observes a test FAILING on the pre-fold tree — **BEFORE the fix** — and mints an **observed-red receipt**. The read-only checker (`--status` / `--check`) then requires, per bound test: the receipt, receipt-precedes-run order, N/N-green probes, and content **custody** (the green test is byte-identical to the one seen failing) — the receipt+custody half waivable for exactly one `testId` by a recorded `red-proof` override; mixed/timed-out probes are QUARANTINE (never converted, no override); **v3 records carry `base` and the proof is segment-scoped (AD-048)** — a committed phase's custody obligations close with its commit, and a receipt never crosses a commit boundary; tampered pre-existing test files fail closed unless covered by a recorded `oracle-change` override. Honest residuals: coverage proves **execution, not assertion**, and records are forgeable — self-discipline, not a security boundary. v1 scope is JS/V8 (pluggable via `AW_FOLD_BOUND_CMD`): 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. |
243
- | `/agent-workflow-kit recommendations` | any time (every `upgrade` ends with it) | **read-only deployment advisor** (AD-044) — computes what in THIS deployment is configured sub-optimally (allowlist not seeded, autonomy render drifted, OS sandbox unavailable, gates undeclared, bridge friction, sandbox-mask clutter, an unacknowledged sandbox recipe) and renders **verdict-first**: one composed verdict line (does anything need attention?), then each item as **{severity · what · one-line benefit · the exact consent-gated apply one-liner}**. The agent PRESENTS the section in the user's conversational language — every fact and count, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; raw tool block on request — and runs EXACTLY the rendered one-liners only on your yes, surfacing each item's posture note first. Renders **present-even-when-empty** (`no recommendations — flow optimal.`); a failed probe degrades to a stated skip line. Registry strings are fact-true frozen one-line data (posture/risk notes live in the mode doc at the consent moment); the sandbox-lane item is **HAND-APPLY** — the kit never seeds `sandbox.network.allowedDomains` / `filesystem.allowWrite` (the recipe is documented per bridge in `capability.json` `networkHosts` + `writableDirs`; convergence is a neutral fingerprint acknowledgement, never a security key). `--cwd` is required (the target project is explicit); never writes, never commits, never runs a subscription CLI. |
243
+ | `/agent-workflow-kit recommendations` | any time (every `upgrade` ends with it) | **read-only deployment advisor** (AD-044) — computes what in THIS deployment is configured sub-optimally (allowlist not seeded, autonomy render drifted, OS sandbox unavailable, gates undeclared, bridge friction, sandbox-mask clutter, an unacknowledged sandbox recipe) and renders **verdict-first**: one composed verdict line (does anything need attention?), then each item as **{severity · what · one-line benefit · an optional `recipe:` line (sandbox-lane only) · the exact consent-gated apply one-liner}**. The agent PRESENTS the section in the user's conversational language — every fact and count, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; raw tool block on request — and runs EXACTLY the rendered one-liners only on your yes, surfacing each item's posture note first. Renders **present-even-when-empty** (`no recommendations — flow optimal.`); a failed probe degrades to a stated skip line. Registry strings are fact-true frozen one-line data (posture/risk notes live in the mode doc at the consent moment); the kit never seeds `sandbox.network.allowedDomains` / `filesystem.allowWrite` (**HAND-APPLY** territory), and the sandbox-lane item's convergence is a neutral fingerprint acknowledgement recorded by a consent-gated ack writer into `docs/ai/acks.json` — never a security key (the recipe is documented per bridge in `capability.json` `networkHosts` + `writableDirs`). `--cwd` is required (the target project is explicit); never writes, never commits, never runs a subscription CLI. |
244
244
  | `/agent-workflow-kit doc-parity` | any time | **read-only doc-parity lint** (AD-049) — kills the doc-drift class where a mode-contract doc silently lags a code constant (a `--check` doc still reading `300` after the diff cap moved to `400`): a **closed, exported registry** binds each live constant (review caps, schema versions, the ledger's own class/scope vocabulary, and the autonomy-doctor EXIT/status/trusted-dir contract) to the exact token its `references/modes/*.md` contract must carry, and asserts the CURRENT value renders into every bound file — a drifted doc, an unreadable file, or an absent token **fails closed**. The values are sourced from the live imports (never re-typed), so the lint can't itself go stale; adding a binding is adding a checked entry (closed-world, edit-safe). `--check` is a gate exit code for `docs/ai/gates.json`. Never writes, never commits, never runs a subscription CLI. |
245
245
  | `/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. |
246
246
  | `/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. |
247
247
  | `/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. |
248
- | `/agent-workflow-kit hook` | Claude Code · opt-in | **gate-approval hook** — places a self-contained PreToolUse hook (`.claude/hooks/`) and wires it into `.claude/settings.json`: a Bash command **byte-identical** to a gate you declared in `docs/ai/gates.json` (run from the project root) is auto-approved — no prompt, no idle; a seeded read-only command carrying a runtime residual (output redirection, command substitution, `--output` writes) now **asks** even where an allow rule would have silently passed it (proven live — hook `ask` overrides an allow rule). Exact matches only, never patterns; never `deny`; a broken `gates.json` only disables auto-approval, never the guard. Preview by default; never writes `settings.local.json`; never commits. |
248
+ | `/agent-workflow-kit hook` | Claude Code · opt-in | **gate-approval hook** — places a self-contained PreToolUse hook (`.claude/hooks/`) and wires it into `.claude/settings.json`: a Bash command **byte-identical** to a gate you declared in `docs/ai/gates.json` (run from the project root) is auto-approved — no prompt, no idle; a seeded read-only command carrying a runtime residual (output redirection, command substitution, `--output` writes) now **asks** even where an allow rule would have silently passed it (proven live — hook `ask` overrides an allow rule). Exact matches only, never patterns; never `deny`; a broken `gates.json` only disables auto-approval, never the guard. An opt-in **read-lane** (`--read-lane` → `docs/ai/lanes.json`, a **separate** file from `gates.json`) additionally auto-approves *compounds* of seeded read-only commands carrying no shell metaprogramming; `--apply --read-lane` verifies the placed hook is current first (delete-to-reseed otherwise). Preview by default; never writes `settings.local.json`; never commits. |
249
249
  | `/agent-workflow-kit bridge-settings` | opt-in, any time | **host-level bridge settings** — read or change the bridges' `KEY=VALUE` config file (`${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf`), the **one place a knob survives kit upgrades** (it lives outside every kit tree; a refresh never touches it, and now states loudly if it ever overwrote a local edit). First knobs: the **codex Fast tier** (`CODEX_SERVICE_TIER=priority` — ~1.5× speed at a **2.5× credit rate**, quality-neutral, default off — a consented spend), the codex/agy hard timeouts, the review byte cap, the oversized-review add-dir toggle. Allowed keys + value rules come from the bundled bridge manifests; **model/effort are never settable** (the quality guard is untouched). **Previews by default**; refuses an unknown key, an out-of-range value, or a duplicate-carrying file; writes atomically (symlink/TOCTOU-safe). Never commits, never runs a subscription CLI. |
250
250
  | `/agent-workflow-kit autonomy-doctor` | opt-in, any time | **guarded sandbox provisioner "doctor"** — can this machine run the Claude sandbox, and (only with your consent) fix it: macOS Seatbelt built-in / Linux+WSL2 needs `bwrap`+`socat` / native Windows → WSL2. Flagless = **FS-only preview** (the diagnosis, the exact absolute-path command it WOULD run, the exact `--apply <pm>:<pkgs>` consent tuple — runs nothing, never claims ready); `--verify` runs the unprivileged proof (a `bwrap` user-namespace smoke + `socat -V`) — the **only** source of a Linux "ready (verified)" claim; `--apply <pm>:<pkgs>` is the consent-gated privileged install (the tuple must equal the previewed plan; everything executed resolves to absolute paths inside `/usr/bin:/bin:/usr/sbin:/sbin`; the exact command is re-printed immediately before execution), then verifies. Honest loud degrades (unknown PM, untrusted location, nested-sandbox INDETERMINATE, root-unproven) and a stated restart step. Sits **outside every velocity auto-approve tier**; never auto-runs, never writes repo files, never commits. |
251
251
 
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.46.0'
6
+ version: '1.48.0'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
@@ -2,7 +2,7 @@
2
2
  name: antigravity-cli-bridge
3
3
  description: Delegate work to Google's Antigravity CLI (`agy`) — the successor to Gemini CLI — to reach Gemini, Claude, and GPT-OSS models under a Google AI Pro/Ultra subscription from the terminal. Use when the user wants to run a headless `agy` prompt, hand a focused task or second-opinion review to `agy`, install or authenticate Antigravity CLI, check or economise its quota/models, bridge project context into `agy`, set up a second delegated-execution backend beside Codex, or troubleshoot `agy` flags, models, auth, conversations, or its no-JSON headless behaviour.
4
4
  metadata:
5
- version: '2.5.0'
5
+ version: '2.6.0'
6
6
  ---
7
7
 
8
8
  # antigravity-cli-bridge
@@ -69,6 +69,11 @@ Grounding:
69
69
  --facts @f = the verified facts to review AGAINST; --decided @f = decisions
70
70
  already made, do NOT re-raise (anti-circling)
71
71
 
72
+ Notes:
73
+ pre-dispatch host-diff: before the FIRST dispatch of this bridge, diff its declared networkHosts
74
+ against the live sandbox allow-list — a missing host is surfaced to the maintainer BEFORE
75
+ dispatching, never fired into a known prompt
76
+
72
77
  Round-2 / resume:
73
78
  agy-review --continue [--decided @f] [--focus "…"]
74
79
  agy-review --conversation <id> [--decided @f] [--focus "…"]
@@ -194,7 +199,7 @@ DEFAULT_AGY_REVIEW_MODEL="Gemini 3.1 Pro (High)"
194
199
  # Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
195
200
  # version (drift-guarded by agy-review.test.mjs against capability.json).
196
201
  AW_RECEIPT_BACKEND="agy"
197
- AW_BRIDGE_VERSION="2.5.0"
202
+ AW_BRIDGE_VERSION="2.6.0"
198
203
  # `-` not `:-` so an EXPLICIT empty AGY_MODEL= survives (drop --model, use settings.json — agy.sh:52).
199
204
  AGY_MODEL="${AGY_MODEL-$DEFAULT_AGY_REVIEW_MODEL}"
200
205
  # Frontier review models. ANY model is allowed; a sub-frontier one only earns a soft, silenceable warning.
@@ -550,6 +550,12 @@ describe('agy-review.sh — --help contract (manifest-pinned)', () => {
550
550
  assert.equal(norm(helpSection(help, 'Grounding:').join(' ')), norm(REVIEW_CONTRACT.grounding));
551
551
  });
552
552
 
553
+ it('Notes renders the manifest contract.notes verbatim (a typed contract key that MUST surface)', () => {
554
+ const help = runHelp('--help').stdout;
555
+ assert.ok(REVIEW_CONTRACT.notes.length > 0, 'manifest notes must be non-empty');
556
+ assert.equal(norm(helpSection(help, 'Notes:').join(' ')), norm(REVIEW_CONTRACT.notes.join(' ')));
557
+ });
558
+
553
559
  it('Round-2 / resume set-EQUALS the manifest continue descriptors', () => {
554
560
  const help = runHelp('--help').stdout;
555
561
  const got = helpSection(help, 'Round-2 / resume:').filter((l) => l.startsWith('agy-review')).map(norm);
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "antigravity-cli-bridge",
5
5
  "kind": "execution-backend",
6
- "version": "2.5.0",
6
+ "version": "2.6.0",
7
7
  "provides": ["review", "probe"],
8
8
  "roles": {
9
9
  "review": {
@@ -28,7 +28,10 @@
28
28
  "agy-review --continue [--decided @f] [--focus \"…\"]",
29
29
  "agy-review --conversation <id> [--decided @f] [--focus \"…\"]"
30
30
  ],
31
- "receipt": "side effect — a successful review appends one JSON receipt line to <git dir>/agent-workflow-review-receipts.jsonl (AW_REVIEW_RECEIPTS overrides; plan/diff outside a git tree: warn + skip unless overridden): 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/diff mode; verdict recorded verbatim from the mandated '### Verdict' section (SHIP / SHIP WITH NITS / REWORK); grounded = whether a NON-EMPTY --facts payload was supplied (an empty payload records grounded:false — fail-closed, the state gate rejects it), factsHash = sha256 of the facts payload; a continuation receipt is fresh:false (informational-only — it cannot attest the folded tree); a write failure warns, never fails the review"
31
+ "receipt": "side effect — a successful review appends one JSON receipt line to <git dir>/agent-workflow-review-receipts.jsonl (AW_REVIEW_RECEIPTS overrides; plan/diff outside a git tree: warn + skip unless overridden): 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/diff mode; verdict recorded verbatim from the mandated '### Verdict' section (SHIP / SHIP WITH NITS / REWORK); grounded = whether a NON-EMPTY --facts payload was supplied (an empty payload records grounded:false — fail-closed, the state gate rejects it), factsHash = sha256 of the facts payload; a continuation receipt is fresh:false (informational-only — it cannot attest the folded tree); a write failure warns, never fails the review",
32
+ "notes": [
33
+ "pre-dispatch host-diff: before the FIRST dispatch of this bridge, diff its declared networkHosts against the live sandbox allow-list — a missing host is surfaced to the maintainer BEFORE dispatching, never fired into a known prompt"
34
+ ]
32
35
  }
33
36
  },
34
37
  "probe": { "cmd": "agy-run", "source": "bin/agy.sh", "output": "advisory" }
@@ -2,7 +2,7 @@
2
2
  name: codex-cli-bridge
3
3
  description: Delegate work to the OpenAI Codex CLI (`codex`) under a ChatGPT subscription — run plan/instruction EXECUTION in a sandboxed workspace, or get a read-only ADVISORY review of a plan or working-tree diff — as a second delegated-execution backend beside Antigravity. Use when the user wants to hand a bounded coding task or plan to `codex exec`, get a second-opinion review from codex, install or authenticate Codex CLI, understand its sandbox/network/approval policy, drive codex efficiently from the main agent (exec vs review, resume, the commit boundary), bridge project context (`AGENTS.md`) into codex, or troubleshoot codex flags, models, auth, or its no-TTY headless behaviour.
4
4
  metadata:
5
- version: '2.6.0'
5
+ version: '2.7.0'
6
6
  ---
7
7
 
8
8
  # codex-cli-bridge
@@ -67,6 +67,12 @@ Guarded passthrough after '--':
67
67
  blocked always: -c* --config* -s* --sandbox* --dangerously-bypass-approvals-and-sandbox --dangerously-bypass-hook-trust --full-auto --oss --local-provider* -p* --profile* -m* --model* -o* --output-last-message* --json* --color* --output-schema* --ephemeral*
68
68
  relaxed only under CODEX_PROBE=1: --add-dir* -C* --cd* --skip-git-repo-check --ignore-rules --enable* --disable*
69
69
 
70
+ Notes:
71
+ nested-sandbox limit: codex-exec ships its OWN OS sandbox (bwrap workspace-write) and cannot run
72
+ nested inside a harness sandbox (the FS turns read-only) — route it OUTSIDE the harness sandbox
73
+ (excludedCommands / a per-run consented bypass) on the OBSERVED bwrap/EPERM failure, never a
74
+ preemptive blanket
75
+
70
76
  Settings file (KEY=VALUE, parsed never sourced; env wins over file, file wins over built-in default):
71
77
  ${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf
72
78
  CODEX_SERVICE_TIER — service tier: 'priority' (Fast — ~1.5x speed at a 2.5x credit rate on gpt-5.6-sol); a consented SPEND knob, default off (standard tier)
@@ -557,6 +563,20 @@ fi
557
563
  if [[ $rc -ne 0 ]]; then
558
564
  echo "error: codex exec failed (exit $rc). Last lines of the run trace:" >&2
559
565
  tail -n 40 "$trace" >&2
566
+ # Nested-sandbox detection: codex ships its OWN OS sandbox (bwrap); run nested inside a harness
567
+ # sandbox the FS is read-only and codex's own sandbox setup fails. Fire the STATED recovery hint
568
+ # only on a COMBINATION — a sandbox MECHANISM token AND a permission/read-only FAILURE token in the
569
+ # trace — so a lone 'bwrap' banner, or a lone 'permission denied' from unrelated code, is NOT enough
570
+ # (never a preemptive blanket). grep is line-oriented, so a plain alternation stays within a line —
571
+ # the old `[^\n]*` between the two halves was wrong twice over (it excluded the letter 'n', and grep
572
+ # never spans lines anyway), so the split into two `-q` passes both fixes it and states the intent.
573
+ if grep -qiE 'bwrap|landlock|user namespace|pivot_root|unshare|seccomp' "$trace" 2>/dev/null \
574
+ && grep -qiE 'read-only file system|erofs|operation not permitted|permission denied|eperm' "$trace" 2>/dev/null; then
575
+ echo "hint: this looks like a NESTED-SANDBOX failure — codex-exec ships its own OS sandbox (bwrap)," >&2
576
+ echo " which cannot run nested inside a harness sandbox (the FS is read-only). Route codex-exec" >&2
577
+ echo " OUTSIDE the harness sandbox: add it to the harness sandbox excludedCommands, or dispatch" >&2
578
+ echo " this one run via a per-run consented bypass. Do NOT blanket-disable the sandbox." >&2
579
+ fi
560
580
  exit $rc
561
581
  fi
562
582
 
@@ -21,6 +21,7 @@ const FAKE_CODEX = [
21
21
  '#!/usr/bin/env bash',
22
22
  'set -u',
23
23
  'if [[ "${1:-}" == "login" ]]; then echo "${CODEX_FAKE_LOGIN:-Logged in using ChatGPT}"; exit 0; fi',
24
+ 'if [[ -n "${CODEX_FAKE_STDERR:-}" ]]; then echo "$CODEX_FAKE_STDERR" >&2; fi',
24
25
  ': "${CODEX_FAKE_ARGV:=/dev/null}"',
25
26
  ': "${CODEX_FAKE_ENV:=/dev/null}"',
26
27
  ': "${CODEX_FAKE_STDIN:=/dev/null}"',
@@ -274,6 +275,49 @@ describe('codex-exec.sh — clean output + session capture (1.2)', () => {
274
275
  assert.equal(r.status, 7);
275
276
  assert.match(r.stderr, /codex exec failed \(exit 7\)/);
276
277
  assert.match(r.stderr, /thread\.started/, 'failure should surface the trace tail');
278
+ assert.doesNotMatch(r.stderr, /NESTED-SANDBOX/, 'a plain failure (no bwrap signature) never triggers the hint');
279
+ });
280
+
281
+ it('on a NESTED-SANDBOX failure (bwrap/read-only trace) surfaces the stated recovery hint', () => {
282
+ const sb = makeSandbox();
283
+ const r = run(sb, { env: { CODEX_FAKE_EXIT: '1', CODEX_FAKE_STDERR: 'bwrap: setting up sandbox: mkdir /newroot: Read-only file system' } });
284
+ rmSync(sb.root, { recursive: true, force: true });
285
+ assert.equal(r.status, 1);
286
+ assert.match(r.stderr, /NESTED-SANDBOX/, 'names the failure class');
287
+ assert.match(r.stderr, /excludedCommands|per-run consented bypass/, 'states the recovery route');
288
+ assert.match(r.stderr, /Do NOT blanket-disable/, 'warns against a preemptive blanket');
289
+ });
290
+
291
+ it('a NON-nested codex failure does NOT emit the nested-sandbox hint (no false positive)', () => {
292
+ const sb = makeSandbox();
293
+ const r = run(sb, { env: { CODEX_FAKE_EXIT: '3', CODEX_FAKE_STDERR: 'model error: rate limited, try again later' } });
294
+ rmSync(sb.root, { recursive: true, force: true });
295
+ assert.equal(r.status, 3);
296
+ assert.doesNotMatch(r.stderr, /NESTED-SANDBOX/, 'a generic failure never triggers the hint');
297
+ });
298
+
299
+ it('#6 fold: a mechanism+failure trace whose message contains the letter n (mkdir /newroot) still fires — the old [^\\n]* wrongly excluded n', () => {
300
+ const sb = makeSandbox();
301
+ const r = run(sb, { env: { CODEX_FAKE_EXIT: '1', CODEX_FAKE_STDERR: 'bwrap: mkdir /newroot: operation not permitted' } });
302
+ rmSync(sb.root, { recursive: true, force: true });
303
+ assert.equal(r.status, 1);
304
+ assert.match(r.stderr, /NESTED-SANDBOX/, 'bwrap (mechanism) + operation not permitted (failure) fire even through n-bearing words');
305
+ });
306
+
307
+ it('#6 fold: a LONE mechanism token (a bwrap banner, no failure) does NOT fire — a combination is required', () => {
308
+ const sb = makeSandbox();
309
+ const r = run(sb, { env: { CODEX_FAKE_EXIT: '2', CODEX_FAKE_STDERR: 'bwrap version 0.11.0' } });
310
+ rmSync(sb.root, { recursive: true, force: true });
311
+ assert.equal(r.status, 2);
312
+ assert.doesNotMatch(r.stderr, /NESTED-SANDBOX/, 'a mechanism token without a permission/read-only failure is not nested-sandbox proof');
313
+ });
314
+
315
+ it('#6 fold: a LONE failure token (permission denied, no sandbox mechanism) does NOT fire', () => {
316
+ const sb = makeSandbox();
317
+ const r = run(sb, { env: { CODEX_FAKE_EXIT: '2', CODEX_FAKE_STDERR: 'curl: (7) permission denied' } });
318
+ rmSync(sb.root, { recursive: true, force: true });
319
+ assert.equal(r.status, 2);
320
+ assert.doesNotMatch(r.stderr, /NESTED-SANDBOX/, 'a permission failure from unrelated code is not nested-sandbox proof');
277
321
  });
278
322
 
279
323
  it('warns (never silently) when the session sidecar cannot be written', () => {
@@ -734,6 +778,12 @@ describe('codex-exec.sh — --help contract (manifest-pinned)', () => {
734
778
  setEq(tier('relaxed only under CODEX_PROBE=1:'), EXEC_CONTRACT.passthrough.probeRelaxed, 'help tier-2 ⟷ manifest probeRelaxed');
735
779
  });
736
780
 
781
+ it('Notes renders the manifest contract.notes verbatim (a typed contract key that MUST surface)', () => {
782
+ const help = runHelp('--help').stdout;
783
+ assert.ok(EXEC_CONTRACT.notes.length > 0, 'manifest notes must be non-empty');
784
+ assert.equal(norm(helpSection(help, 'Notes:').join(' ')), norm(EXEC_CONTRACT.notes.join(' ')));
785
+ });
786
+
737
787
  it('--help after the -- separator is passthrough payload, never intercepted', () => {
738
788
  const sb = makeSandbox();
739
789
  const r = run(sb, { args: ['-', '--', '--help'], input: 'go' });
@@ -172,7 +172,7 @@ DEFAULT_CODEX_EFFORT="xhigh"
172
172
  # Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
173
173
  # version (drift-guarded by codex-review.test.mjs against capability.json).
174
174
  AW_RECEIPT_BACKEND="codex"
175
- AW_BRIDGE_VERSION="2.6.0"
175
+ AW_BRIDGE_VERSION="2.7.0"
176
176
  CODEX_MODEL="${CODEX_MODEL:-$DEFAULT_CODEX_MODEL}"
177
177
  CODEX_EFFORT="${CODEX_EFFORT:-$DEFAULT_CODEX_EFFORT}"
178
178
  # Generous hard cap for a slow xhigh review (subscription latency varies).
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "codex-cli-bridge",
5
5
  "kind": "execution-backend",
6
- "version": "2.6.0",
6
+ "version": "2.7.0",
7
7
  "provides": ["execute", "review"],
8
8
  "roles": {
9
9
  "execute": {
@@ -24,7 +24,10 @@
24
24
  "policy": "guarded",
25
25
  "blocked": ["-c*", "--config*", "-s*", "--sandbox*", "--dangerously-bypass-approvals-and-sandbox", "--dangerously-bypass-hook-trust", "--full-auto", "--oss", "--local-provider*", "-p*", "--profile*", "-m*", "--model*", "-o*", "--output-last-message*", "--json*", "--color*", "--output-schema*", "--ephemeral*"],
26
26
  "probeRelaxed": ["--add-dir*", "-C*", "--cd*", "--skip-git-repo-check", "--ignore-rules", "--enable*", "--disable*"]
27
- }
27
+ },
28
+ "notes": [
29
+ "nested-sandbox limit: codex-exec ships its OWN OS sandbox (bwrap workspace-write) and cannot run nested inside a harness sandbox (the FS turns read-only) — route it OUTSIDE the harness sandbox (excludedCommands / a per-run consented bypass) on the OBSERVED bwrap/EPERM failure, never a preemptive blanket"
30
+ ]
28
31
  }
29
32
  },
30
33
  "review": {
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.46.0",
6
+ "version": "1.48.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.46.0",
3
+ "version": "1.48.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",
@@ -21,3 +21,4 @@ Rules:
21
21
  - Mark anything uncertain as `VERIFY:` rather than asserting it.
22
22
  - No superlatives, no persuasion, no summary paragraph — that is the frontier's red-line work.
23
23
  - Read-only: you never modify files.
24
+ - Tooling note: this vehicle grants `Read`/`Grep`/`Glob` only — **no `Bash`**. If a harness omits `Grep`/`Glob`, fall back to the `Read` tool (whole-file reads), never a shelled-out command. Should a harness nonetheless route your reads through `Bash`, keep each one a **plain single read-only command** (`grep …`, `ls …`, `cat …`) — never a `;`/`&&`/`|` chain, never `node -e`; where the maintainer enabled the opt-in **read-lane** (`docs/ai/lanes.json`), the gate hook keeps those seeded-read-only Bash reads promptless (it fires on subagent Bash too).
@@ -21,3 +21,4 @@ Rules:
21
21
  - Output: one section per failing gate, ordered as the run reported them. No fix suggestions,
22
22
  no root-cause speculation beyond the failure class, no code.
23
23
  - Read-only: you never modify files, never re-run commands.
24
+ - Tooling note: this vehicle grants `Read`/`Grep`/`Glob` only — **no `Bash`**. If a harness omits `Grep`/`Glob`, fall back to the `Read` tool (whole-file reads), never a shelled-out command. Should a harness nonetheless route your reads through `Bash`, keep each one a **plain single read-only command** (`grep …`, `ls …`, `cat …`) — never a `;`/`&&`/`|` chain, never `node -e`; where the maintainer enabled the opt-in **read-lane** (`docs/ai/lanes.json`), the gate hook keeps those seeded-read-only Bash reads promptless (it fires on subagent Bash too).
@@ -18,3 +18,4 @@ Rules:
18
18
  - Output format: the structure the prompt asks for (list / table / JSON). No preamble, no
19
19
  commentary, no recommendations — the orchestrator applies judgment, you supply facts.
20
20
  - Read-only: you never modify files, never run commands, never propose edits.
21
+ - Tooling note: this vehicle grants `Read`/`Grep`/`Glob` only — **no `Bash`**. If a harness omits `Grep`/`Glob`, fall back to the `Read` tool (whole-file reads), never a shelled-out command. Should a harness nonetheless route your reads through `Bash`, keep each one a **plain single read-only command** (`grep …`, `ls …`, `cat …`) — never a `;`/`&&`/`|` chain, never `node -e`; where the maintainer enabled the opt-in **read-lane** (`docs/ai/lanes.json`), the gate hook keeps those seeded-read-only Bash reads promptless (it fires on subagent Bash too).