@sabaiway/agent-workflow-kit 3.1.0 → 3.2.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.
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "codex-cli-bridge",
5
5
  "kind": "execution-backend",
6
- "version": "3.0.0",
6
+ "version": "3.1.0",
7
7
  "posture": { "model": "gpt-5.6-sol", "effort": "xhigh", "tier": null },
8
8
  "provides": ["execute", "review"],
9
9
  "roles": {
@@ -27,7 +27,11 @@
27
27
  "probeRelaxed": ["--add-dir*", "-C*", "--cd*", "--skip-git-repo-check", "--ignore-rules", "--enable*", "--disable*"]
28
28
  },
29
29
  "notes": [
30
- "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
+ "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",
31
+ "exec posture banner: ONE stderr line before dispatch states the ACTUAL run posture — exec posture: model=… effort=… tier=… sandbox=workspace-write session=fresh|resume:<id> timeout=… — from RESOLVED post-validation values; the resume id is validated pre-spend, and control bytes in any banner field refuse pre-spend",
32
+ "threat model: the sidecar byte and grammar screens detect corrupted input under a trusted parent environment. A hostile parent environment — including exported shell functions or PATH substitution of core/backend commands — is outside the threat model and can substitute the backend itself. Targeted shadow-proof resolution protects banner/dispatch honesty from accidental shadowing; it is not an environment security boundary",
33
+ "the exec posture banner appends a banner-only timeout=<duration|uncapped> field — exactly the duration handed to timeout(1), uncapped when no timeout/gtimeout binary caps the run; INFORMATIONAL only: it is never persisted in a receipt or session sidecar",
34
+ "quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts"
31
35
  ]
32
36
  }
33
37
  },
@@ -43,7 +47,11 @@
43
47
  ],
44
48
  "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",
45
49
  "continue": [],
46
- "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); probe = whether the run relaxed the quality guards (CODEX_PROBE=1), written on EVERY receipt so it self-declares — the kit's review-state gate rejects a probe-marked receipt (a probe review never attests) and equally rejects an unmarked one (silence is not a declaration); posture = the ACTUAL run posture {model, effort, tier} (tier null on the standard tier), written on EVERY receipt (D5) — the gate rejects a receipt with an absent/invalid posture (a pre-D5 wrapper minted it; re-run the review), one stderr banner line states the same posture, and a posture value carrying control bytes refuses pre-spend in every mode; a run whose final message carries NO recognized 'Verdict: <ship|revise|rethink>' line — empty or missing output included — exits 4 with NO receipt (D4: a FAILED review to RE-RUN, never a fatal session error); a write failure warns, never fails the review"
50
+ "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); probe = whether the run relaxed the quality guards (CODEX_PROBE=1), written on EVERY receipt so it self-declares — the kit's review-state gate rejects a probe-marked receipt (a probe review never attests) and equally rejects an unmarked one (silence is not a declaration); posture = the ACTUAL run posture {model, effort, tier} (tier null on the standard tier), written on EVERY receipt (D5) — the gate rejects a receipt with an absent/invalid posture (a pre-D5 wrapper minted it; re-run the review), one stderr banner line states the same posture, and a posture value carrying control bytes refuses pre-spend in every mode; a run whose final message carries NO recognized 'Verdict: <ship|revise|rethink>' line — empty or missing output included — exits 4 with NO receipt (D4: a FAILED review to RE-RUN, never a fatal session error); a write failure warns, never fails the review",
51
+ "notes": [
52
+ "the review posture banner appends a banner-only timeout=<duration|uncapped> field — exactly the duration handed to timeout(1), uncapped when no timeout/gtimeout binary caps the run; INFORMATIONAL only: it never enters the receipt posture or the D5 banner↔receipt parity",
53
+ "quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts"
54
+ ]
47
55
  }
48
56
  }
49
57
  },
@@ -72,7 +80,8 @@
72
80
  "guardrails": [
73
81
  { "value": "runs under codex's OWN OS sandbox (workspace-write)", "enforcement": "enforced", "condition": "it cannot nest inside another sandbox — the FS turns read-only; route it outside on the OBSERVED failure", "source": "capability.json roles.execute.contract.notes" },
74
82
  { "value": "the guarded passthrough blocks model / sandbox / approval overrides", "enforcement": "enforced", "source": "bin/codex-exec.sh" },
75
- { "value": "hard wall-clock cap CODEX_HARD_TIMEOUT (built-in default 3600s)", "enforcement": "enforced", "condition": "only while timeout(1)/gtimeout is on PATH — otherwise the wrapper warns and runs uncapped", "source": "capability.json settings.CODEX_HARD_TIMEOUT" }
83
+ { "value": "hard wall-clock cap CODEX_HARD_TIMEOUT (built-in default 3600s)", "enforcement": "enforced", "condition": "only while timeout(1)/gtimeout is on PATH — otherwise the wrapper warns and runs uncapped", "source": "capability.json settings.CODEX_HARD_TIMEOUT" },
84
+ { "value": "ONE exec posture stderr banner line states the ACTUAL run posture before dispatch (session=fresh|resume:<id>; timeout is banner-only)", "enforcement": "enforced", "source": "bin/codex-exec.sh" }
76
85
  ],
77
86
  "customHooks": ["CODEX_PROBE"]
78
87
  },
@@ -87,6 +96,9 @@
87
96
  "operands": [
88
97
  { "slot": "<plan-file|->", "required": true, "description": "the follow-up instruction file, or - to read it from stdin" }
89
98
  ],
99
+ "guardrails": [
100
+ { "value": "ONE exec posture stderr banner line states the ACTUAL run posture before dispatch (session=resume:<id> only AFTER the sidecar id is resolved and validated; timeout is banner-only)", "enforcement": "enforced", "source": "bin/codex-exec.sh" }
101
+ ],
90
102
  "customHooks": ["CODEX_PROBE"]
91
103
  },
92
104
  {
@@ -100,6 +112,9 @@
100
112
  { "slot": "<session-id>", "required": true, "description": "the session id the original run printed on stderr" },
101
113
  { "slot": "<plan-file|->", "required": true, "description": "the follow-up instruction file, or - to read it from stdin" }
102
114
  ],
115
+ "guardrails": [
116
+ { "value": "ONE exec posture stderr banner line states the ACTUAL run posture before dispatch (session=resume:<id> only AFTER the explicit id is validated against the session-id grammar; timeout is banner-only)", "enforcement": "enforced", "source": "bin/codex-exec.sh" }
117
+ ],
103
118
  "customHooks": ["CODEX_PROBE"]
104
119
  },
105
120
  {
@@ -27,6 +27,17 @@ model or effort for a real run — the wrapper will stop you. Quota is metered i
27
27
  never from a downgrade. The only opt-out is a throwaway, effort-independent probe: `CODEX_PROBE=1`
28
28
  (loud) — never use its output as real work.
29
29
 
30
+ ## Posture banners — quote them verbatim
31
+
32
+ Every dispatch states its ACTUAL posture on ONE stderr line: `codex-exec` emits
33
+ `exec posture: model=… effort=… tier=… sandbox=workspace-write session=fresh|resume:<id> timeout=…`
34
+ (fresh and resume alike, only after the resume id is resolved and validated), `codex-review` emits
35
+ `review posture: model=… effort=… tier=… timeout=…`. When you label a dispatch for a user or a
36
+ record, **quote the posture banner verbatim** — the banner is the machine-stated posture; a prose
37
+ re-type drifts. The `timeout=` field is **banner-only** (exactly the duration handed to
38
+ `timeout(1)`, or `uncapped` when no capping binary is on PATH) — informational, never part of a
39
+ receipt or the banner↔receipt parity.
40
+
30
41
  ## Exec vs review
31
42
 
32
43
  Use **`codex-exec`** when there is a concrete plan or focused instruction to implement, the project
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": "3.1.0",
6
+ "version": "3.2.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": "3.1.0",
3
+ "version": "3.2.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",
@@ -1,6 +1,6 @@
1
1
  ### Mode: bootstrap
2
2
 
3
- Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md · ${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md
3
+ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md · ${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md · ${CLAUDE_SKILL_DIR}/references/shared/command-shapes.md
4
4
 
5
5
  > Bundled sources below (templates, scripts) live in **this skill's own directory** — `${CLAUDE_SKILL_DIR}/` in Claude Code, or the folder containing this `SKILL.md` in Codex / other agents. Use that as the copy/read source; the working directory is the **target project**, not the skill.
6
6
 
@@ -9,7 +9,8 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
9
9
  1. **Recon (read-only).** Before writing anything:
10
10
  - `package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml` → stack, package manager, scripts.
11
11
  - `ls -la` root → `README`, existing `AGENTS.md`/`CLAUDE.md`, CI configs, linter/formatter configs.
12
- - `git log --oneline -30` + `git status` → recent activity, branch, uncommitted changes.
12
+ - `git log --oneline -30` → recent activity.
13
+ - `git status` → branch, uncommitted changes.
13
14
  - `src/` (or equivalent) 2–3 levels deep → modules, routes/pages, components, services, types.
14
15
  - Tests (framework, location, E2E?) and linter rules.
15
16
  - Record: stack, package manager, daily commands (`dev`/`test`/`lint`/`type-check`), routes/pages, architecture layers.
@@ -1,6 +1,6 @@
1
1
  ### Mode: upgrade
2
2
 
3
- Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md · ${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md
3
+ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKILL_DIR}/references/shared/composition-handoff.md · ${CLAUDE_SKILL_DIR}/references/shared/deploy-tail.md · ${CLAUDE_SKILL_DIR}/references/shared/command-shapes.md
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** (`3.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".
@@ -48,7 +48,12 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
48
48
  (refresh it with `npx @sabaiway/agent-workflow-engine@latest init`, then re-run) · **over the
49
49
  file's line cap — refused** (trim the file, re-run). The section is found by its heading — no
50
50
  markers; a renamed heading is preserved + noted. A fully absent/invalid engine is the same hard
51
- STOP as (c). Exit 0 covers every soft outcome; only the STOP is non-zero.
51
+ STOP as (c). Exit 0 covers every soft outcome; only the STOP is non-zero. The same invocation
52
+ also reconciles the **Communication (user-facing messages)** section from the kit's own bundled
53
+ template canon (no engine involved) — relay its line too: *refreshed* / *already current* /
54
+ *custom edit preserved + note* / *section absent — noted (never an insert)* / *over the line
55
+ cap — refused*; an unreadable bundled template canon is its own loud STOP naming the kit
56
+ reinstall command.
52
57
 
53
58
  **Bridge settings reconcile — stamp-independent, same gate, BEFORE the equal-head short-circuit.**
54
59
  Run `node ${CLAUDE_SKILL_DIR}/tools/bridge-settings.mjs --reconcile` and **paste its outcome line
@@ -56,7 +61,7 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
56
61
  **NEVER writes** it (the file lives outside every kit tree — D2), so an unknown/retired key is
57
62
  flagged + preserved, never edited. Runs on **every** upgrade; exit 0 covers every outcome.
58
63
  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:
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/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* / `skipped-readonly` / *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`).
64
+ - **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/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* / `skipped-readonly` / *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*) and the **Communication-section** outcome (its own set: refreshed / already current / custom preserved + note / section absent — noted / over the cap — refused); 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`).
60
65
  - **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
66
  - **Render the mandatory Recommendations section — on this exit too, BEFORE the footer.** Run `node ${CLAUDE_SKILL_DIR}/tools/recommendations.mjs --cwd <project-root>` and PRESENT its output — from the `## Recommendations (agent-workflow)` header — in the user's conversational language: every fact, count and item from the tool, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; show the raw tool block on request. The section is present-even-when-empty (with everything optimal the body is exactly `no recommendations — flow optimal.`) and VERDICT-FIRST — the composed verdict line renders from the frozen templates `{K} item(s) need attention` / `nothing is broken` / `{N} optional recommendation(s), apply any you want` / `optimality NOT attested — {M} probe check(s) skipped`. Then OFFER the consent-gated applies: the user picks items in plain language; surface each picked item's posture note, get the explicit confirm, then 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).
62
67
  - **Live host/session facts are tool-composed only.** Any claim this report makes about the current host or session state — prompts fired, sandbox scope, whether a bypass was needed, network reachability, approval counts — must trace to **live tool output** from **this session** (the lines you just composed, or a probe you ran this run); a memory/handover snapshot is **context, never report facts**, and a claim with no live signal is **omitted or explicitly marked unverified** — never asserted from recollection. Full clause: *Live host/session facts* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.md`.
@@ -65,4 +70,4 @@ Requires: ${CLAUDE_SKILL_DIR}/references/shared/report-footer.md · ${CLAUDE_SKI
65
70
  5. Show the relevant `${CLAUDE_SKILL_DIR}/CHANGELOG.md` diff (entries newer than the project's stamp).
66
71
  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.
67
72
  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.)
68
- 8. Re-stamp `docs/ai/.workflow-version` to the **deployment-lineage head** (`3.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>` and PRESENT its output — from the `## Recommendations (agent-workflow)` header — in the user's conversational language (every fact, count and item, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; raw tool block on request; present-even-when-empty: `no recommendations — flow optimal.`), then OFFER the consent-gated applies (per picked item: posture note → explicit confirm → run EXACTLY the rendered one-liner; a HAND-APPLY item is never run by you — `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`). **Every current host/session claim in this report is tool-composed only** — prompts fired, sandbox scope, whether a bypass was needed, network reachability and approval counts must trace to **live tool output** from **this session**, a memory/handover snapshot is **context, never report facts**, and an unbacked claim is **omitted or explicitly marked unverified** (full clause: *Live host/session facts* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.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.
73
+ 8. Re-stamp `docs/ai/.workflow-version` to the **deployment-lineage head** (`3.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** + **Communication-section** outcomes (same outcome sets 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>` and PRESENT its output — from the `## Recommendations (agent-workflow)` header — in the user's conversational language (every fact, count and item, nothing added or dropped; commands, paths, hosts and rule strings byte-exact; raw tool block on request; present-even-when-empty: `no recommendations — flow optimal.`), then OFFER the consent-gated applies (per picked item: posture note → explicit confirm → run EXACTLY the rendered one-liner; a HAND-APPLY item is never run by you — `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md`). **Every current host/session claim in this report is tool-composed only** — prompts fired, sandbox scope, whether a bypass was needed, network reachability and approval counts must trace to **live tool output** from **this session**, a memory/handover snapshot is **context, never report facts**, and an unbacked claim is **omitted or explicitly marked unverified** (full clause: *Live host/session facts* in `${CLAUDE_SKILL_DIR}/references/shared/report-footer.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.
@@ -1,5 +1,7 @@
1
1
  ### Mode: velocity
2
2
 
3
+ Requires: ${CLAUDE_SKILL_DIR}/references/shared/command-shapes.md
4
+
3
5
  The opt-in onboarding **velocity profile** — it seeds a fixed, audited **read-only** Claude Code allowlist into `.claude/settings.json` so an agent stops idling on approval prompts for routine read-only commands while the maintainer is away. It is the family's **first programmatic `.claude/settings.json` writer** (attribution stayed an agent-driven prose merge). **In-agent, opt-in, writes only `.claude/settings.json`**, on one hard rule: **it never allowlists `commit`/`push`/`publish`** — so a direct commit/push/publish still ASKs; the only caveat is the trust-posture residual (below) — its closure is **shipped, opt-in: `${CLAUDE_SKILL_DIR}/references/modes/hook.md`**.
4
6
 
5
7
  **Version-status routing (like the other writer modes):** read `docs/ai/.workflow-version` first — not-deployed → bootstrap; stamp < `3.0.0` → `upgrade`; stamp > head / unparseable → STOP. The tool enforces this in code too (`--apply` STOPs unless the stamp is the lineage head).
@@ -0,0 +1,22 @@
1
+ ### Command shapes — the promptless bar for instructed reads & probes
2
+
3
+ When a mode doc tells you to read a file or probe project state WITHOUT prescribing the exact
4
+ command (a recon read, the version-stamp read, any "check X" instruction), the shape is yours —
5
+ and improvised shapes are where approval prompts come from. The bar:
6
+
7
+ - **Reads ride the host's file-read tool** (Read/Grep/Glob in Claude Code, or your agent's
8
+ equivalent) whenever one exists — a file-read tool never fires a shell approval prompt.
9
+ - **No file-read tool → ONE plain undecorated command per probe:** no `;`/`&&` compounds, no
10
+ redirects, no pipes, no command substitution — one probe per invocation. This applies the
11
+ deployed agent-rules lens’s «plain pipeline per call» discipline here as a stricter
12
+ single-command shape. Any decorated or chained form falls outside this contract’s baseline
13
+ guarantee; behavior is then host/config-dependent — it may prompt, an opt-in read-lane may
14
+ auto-approve a vetted compound, and command substitution may even slip past a prefix allow
15
+ rule. The plain single-command shape is the only shell fallback this contract treats as
16
+ promptless by construction.
17
+ - **Improvised file writes ride the host's file-edit tools** (Write/Edit or the equivalent) —
18
+ never an ad-hoc heredoc or shell-redirect write.
19
+
20
+ **Scope — improvised shapes only.** The executable commands a mode doc itself prescribes (the
21
+ `node …/tools/…` dispatch lines, `--apply` lanes, install/symlink steps) are OUTSIDE this
22
+ contract: run them exactly as prescribed, as plain single invocations.
@@ -43,7 +43,7 @@ duplicate anchor → **STOP with an error**, never edit (the file is left byte-f
43
43
  exceed the 100-line cap, the engine is too old to ship its fragment, or (autonomy only) its anchor
44
44
  (the orchestration pair) is absent: every prior pointer still lands and the upgrade continues.
45
45
 
46
- **Agent-rules lens refresh (runs in BOTH paths).** Its precondition is its own target file — run it
46
+ **Agent-rules lens + Communication refresh (runs in BOTH paths).** Its precondition is its own target file — run it
47
47
  only after `<project>/docs/ai/agent_rules.md` exists: after the substrate deploy in the
48
48
  **delegated** path, after the fallback-template copy in the **kit** path (never anchored to the
49
49
  `AGENTS.md` step above). ONE command:
@@ -53,4 +53,9 @@ prior canonical body is refreshed from the installed engine; a current seed repo
53
53
  current* (zero-diff). Relay its outcome in plain language (*refreshed* / *already current* /
54
54
  *custom edit preserved + note* / *file absent — skipped* / *engine too old — skipped* / *over the
55
55
  line cap — refused*); a fully absent/invalid engine is the same loud STOP + one-line install
56
- command as the pointer reconcile.
56
+ command as the pointer reconcile. The same invocation also reconciles the **Communication
57
+ (user-facing messages)** section from the kit's own bundled template canon (no engine involved):
58
+ a body matching the current canon is reported *already current*; a body matching a known prior
59
+ is refreshed; a custom body is preserved + noted; an absent section is a stated note (never an
60
+ insert); an over-cap refresh is refused; and an unreadable bundled template canon is its own
61
+ loud STOP naming the kit reinstall command.
@@ -63,7 +63,16 @@ Before proposing changes or committing, review against:
63
63
  ### 2.4. Quality Gates
64
64
  - Always run type-checker, linter, and all tests before committing.
65
65
 
66
- ### 2.5. Planning, review & process-fidelity invariants
66
+ ### 2.5. Communication (user-facing messages)
67
+ Apply this as part of §2 before any user-facing summary:
68
+ - **Plain language.** User-facing narration is short, clear, plain words of the dialogue language; when the dialogue language is not English, transliterated English jargon is banned — an English term survives only as the NAME of a thing (a flag / command / file / test), glossed in plain words when helpful; plain English stays plain for English-dialogue users.
69
+ - **Deliver the artifact IN the message** — paste the prompt / diff / version / command inline; never "see §X / open the file / run it and you'll see" as a *substitute* for showing what was asked.
70
+ - **Lead with the result**, then the details; show exactly what was asked — no deflection, no "almost done" when the ask was the finished thing.
71
+ - **No condescension, no filler.** Own a miss plainly and fix it in the same message.
72
+ - **Large artifact (≈>100 lines):** deliver a real summary or the key excerpt inline **and** link the file — never flood the reader with a 2000-line paste, never hide the answer behind a bare pointer.
73
+ - **Live host/session facts are tool-composed only.** Any claim about the current host or session state (prompts fired, sandbox scope, whether a bypass was needed, network reachability, approval counts) must trace to **live tool output** from **this session**; a memory/handover snapshot is **context, never report facts**, and a claim with no live signal is **omitted or explicitly marked unverified** — never asserted from recollection.
74
+
75
+ ### 2.6. Planning, review & process-fidelity invariants
67
76
  Apply these when authoring a plan, reviewing, folding a finding, or editing code — the layer read **before any code change**. (Full canon: the project's planning / workflow-methodology + orchestration canon. This section is rendered from that canon and refreshed on upgrade; a custom edit is preserved verbatim, but flagged.)
68
77
  - **Fold by code, not prose.** Before folding a code-touching finding into a plan or change, read the cited `file:line` and cite it — a prose fold drifts from the code and seeds the next bug.
69
78
  - **Right altitude.** Pin intent + invariants + acceptance criteria (named tests); leave fine code-mechanics to Execute, where prose cannot diverge from reality.
@@ -148,6 +148,17 @@ export const duplicateKeys = (parsed) => [...parsed.byKey.entries()].filter(([,
148
148
 
149
149
  // ── effective-value resolution (env > file > built-in default) ────────────────────────
150
150
 
151
+ // The env keys the wrappers resolver-validate AFTER precedence (AD-061 aw_effective_timeout) —
152
+ // exactly these mirror the wrapper's invalid-env → warn + built-in-default lane.
153
+ const RESOLVER_VALIDATED_ENV = new Set(['CODEX_HARD_TIMEOUT', 'AGY_HARD_TIMEOUT']);
154
+ // A control byte (C0 range + DEL) in a screened knob makes the wrapper EXIT 2 pre-spend — the
155
+ // advisor must report that refusal, never a benign fallback, and never echo the raw byte into
156
+ // the report (a newline could otherwise forge a `review posture:`/status line). safeShow escapes
157
+ // every note value: JSON.stringify handles C0, an explicit pass handles DEL (JSON leaves it raw).
158
+ const hasControlByte = (s) => /[\x01-\x1f\x7f]/.test(s);
159
+ const safeShow = (s) => JSON.stringify(s).slice(1, -1).replace(/\x7f/g, '\\u007f');
160
+ const REFUSED = (key, v) => ({ value: null, source: 'default', note: `env value "${safeShow(v)}" carries control bytes for ${key} — the wrapper REFUSES the run pre-spend` });
161
+
151
162
  // The effective value of one knob + where it comes from. Fact-only; never a model claim.
152
163
  export const effectiveOf = (entry, parsed, getenv) => {
153
164
  const key = entry.key;
@@ -159,13 +170,22 @@ export const effectiveOf = (entry, parsed, getenv) => {
159
170
  // add-dir knobs fall to their real built-in default). Report the manifest default (null ⇒ "wrapper
160
171
  // built-in applies"), not a misleading null-for-everything.
161
172
  if (v === '') return { value: entry.default, source: 'default', note: 'the env KEY= suppresses the file override — the wrapper built-in applies' };
173
+ // A control byte in a SCREENED knob (the tier + the resolver-validated timeouts) is a pre-spend
174
+ // refusal in the wrapper — report it as such (the default value is inert; the run never happens).
175
+ if (hasControlByte(v) && (entry.kind === 'enum' || RESOLVER_VALIDATED_ENV.has(key))) {
176
+ return REFUSED(key, v);
177
+ }
162
178
  // Mirror the wrapper: an ENUM knob (the service tier) validates its ENV value too — codex accepts
163
179
  // any `-c service_tier` string silently, so the wrapper drops an unsupported one to the built-in
164
- // default (codex-exec.sh:188). A non-enum env value is the operator's documented RAW override (e.g.
165
- // a timeout(1) duration like `2h` the wrapper passes straight through) shown as-is (D3 scopes
166
- // typed validation to FILE lines; the Phase-1 council refuted validating non-enum env usage).
180
+ // default (codex-exec.sh:188). The TIMEOUT knobs are resolver-validated env INCLUDED since AD-061
181
+ // (aw_effective_timeout closed the old env bypass, with a 7-digit integer-part overflow bound) —
182
+ // the advisor must never display a dead override as active. Every OTHER non-enum env value stays
183
+ // the operator's RAW override (the wrappers run no resolver on it), shown as-is.
167
184
  if (entry.kind === 'enum' && !settingValueValid(entry, v)) {
168
- return { value: entry.default, source: 'default', note: `env value "${v}" is not a supported ${key} — the wrapper runs the built-in default` };
185
+ return { value: entry.default, source: 'default', note: `env value "${safeShow(v)}" is not a supported ${key} — the wrapper runs the built-in default` };
186
+ }
187
+ if (RESOLVER_VALIDATED_ENV.has(key) && (!settingValueValid(entry, v) || v.match(/^\d*/)[0].length > 7)) {
188
+ return { value: entry.default, source: 'default', note: `env value "${safeShow(v)}" is invalid for ${key} — the wrapper falls back to the built-in default` };
169
189
  }
170
190
  return { value: v, source: 'env' };
171
191
  }
@@ -173,7 +193,7 @@ export const effectiveOf = (entry, parsed, getenv) => {
173
193
  if (fileEntries && fileEntries.length) {
174
194
  const v = fileEntries[fileEntries.length - 1].value; // last occurrence wins
175
195
  if (settingValueValid(entry, v)) return { value: v, source: 'file' };
176
- return { value: entry.default, source: 'default', note: `file value "${v}" is invalid — falls back to the built-in default` };
196
+ return { value: entry.default, source: 'default', note: `file value "${safeShow(v)}" is invalid — falls back to the built-in default` };
177
197
  }
178
198
  return { value: entry.default, source: 'default' };
179
199
  };
@@ -89,7 +89,7 @@ export const handoffPlan = (delegate) =>
89
89
  memoryWrites: ['docs/ai/', 'AGENTS.md', 'docs/ai/.memory-version'],
90
90
  // The lens region runs AFTER the substrate deploy (its own precondition: the file exists)
91
91
  // — it converges a stale-memory seed to the installed engine's canon (AD-041).
92
- kitWrites: ['AGENTS.md pointer slots (methodology / orchestration / autonomy)', 'docs/ai/agent_rules.md lens region', 'docs/ai/.workflow-version'],
92
+ kitWrites: ['AGENTS.md pointer slots (methodology / orchestration / autonomy)', 'docs/ai/agent_rules.md lens + Communication regions', 'docs/ai/.workflow-version'],
93
93
  stampsPresent: ['.memory-version', '.workflow-version'],
94
94
  memoryRaisesCommitGate: false,
95
95
  commitGate: 'kit-only-after-injection',
@@ -101,7 +101,7 @@ export const handoffPlan = (delegate) =>
101
101
  // the kit reconciles them (ensure-slot + inject-because-empty) exactly like the delegate
102
102
  // path — so both paths end with FILLED slots, not inline methodology. The lens region
103
103
  // runs after the fallback-template copy of docs/ai (same reconcile, both paths — AD-041).
104
- kitWrites: ['docs/ai/', 'AGENTS.md', 'AGENTS.md pointer slots (methodology / orchestration / autonomy)', 'docs/ai/agent_rules.md lens region', 'docs/ai/.workflow-version'],
104
+ kitWrites: ['docs/ai/', 'AGENTS.md', 'AGENTS.md pointer slots (methodology / orchestration / autonomy)', 'docs/ai/agent_rules.md lens + Communication regions', 'docs/ai/.workflow-version'],
105
105
  stampsPresent: ['.workflow-version'],
106
106
  memoryRaisesCommitGate: false,
107
107
  commitGate: 'kit-only-after-injection',
@@ -82,6 +82,10 @@ const RAW_BACKENDS = [
82
82
  },
83
83
  notes: [
84
84
  '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',
85
+ 'exec posture banner: ONE stderr line before dispatch states the ACTUAL run posture — exec posture: model=… effort=… tier=… sandbox=workspace-write session=fresh|resume:<id> timeout=… — from RESOLVED post-validation values; the resume id is validated pre-spend, and control bytes in any banner field refuse pre-spend',
86
+ 'threat model: the sidecar byte and grammar screens detect corrupted input under a trusted parent environment. A hostile parent environment — including exported shell functions or PATH substitution of core/backend commands — is outside the threat model and can substitute the backend itself. Targeted shadow-proof resolution protects banner/dispatch honesty from accidental shadowing; it is not an environment security boundary',
87
+ 'the exec posture banner appends a banner-only timeout=<duration|uncapped> field — exactly the duration handed to timeout(1), uncapped when no timeout/gtimeout binary caps the run; INFORMATIONAL only: it is never persisted in a receipt or session sidecar',
88
+ 'quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts',
85
89
  ],
86
90
  },
87
91
  review: {
@@ -92,6 +96,10 @@ const RAW_BACKENDS = [
92
96
  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',
93
97
  continue: [],
94
98
  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); probe = whether the run relaxed the quality guards (CODEX_PROBE=1), written on EVERY receipt so it self-declares — the kit\'s review-state gate rejects a probe-marked receipt (a probe review never attests) and equally rejects an unmarked one (silence is not a declaration); posture = the ACTUAL run posture {model, effort, tier} (tier null on the standard tier), written on EVERY receipt (D5) — the gate rejects a receipt with an absent/invalid posture (a pre-D5 wrapper minted it; re-run the review), one stderr banner line states the same posture, and a posture value carrying control bytes refuses pre-spend in every mode; a run whose final message carries NO recognized \'Verdict: <ship|revise|rethink>\' line — empty or missing output included — exits 4 with NO receipt (D4: a FAILED review to RE-RUN, never a fatal session error); a write failure warns, never fails the review',
99
+ notes: [
100
+ 'the review posture banner appends a banner-only timeout=<duration|uncapped> field — exactly the duration handed to timeout(1), uncapped when no timeout/gtimeout binary caps the run; INFORMATIONAL only: it never enters the receipt posture or the D5 banner↔receipt parity',
101
+ 'quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts',
102
+ ],
95
103
  },
96
104
  },
97
105
  bin: 'codex',
@@ -128,6 +136,8 @@ const RAW_BACKENDS = [
128
136
  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 (code mode refuses pre-spend without one — no run, no receipt — unless --ungrounded/AGY_PROBE=1; in plan/diff 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); probe = whether the run relaxed the quality guards (AGY_PROBE=1), written on EVERY receipt so it self-declares — the kit's review-state gate rejects a probe-marked receipt (a probe review never attests) and equally rejects an unmarked one (silence is not a declaration); posture = the ACTUAL run posture {model} (agy has no tier), written on EVERY receipt (D5) — the gate rejects a receipt with an absent/invalid posture (a pre-D5 wrapper minted it; re-run the review), one stderr banner line states the same posture, an ATTESTING review with AGY_MODEL explicitly emptied refuses pre-spend, and a model string carrying control bytes refuses pre-spend in every mode; a run whose output carries NO recognized '### Verdict' section — empty output included — exits 4 with NO receipt (D4: a FAILED review to RE-RUN, never a fatal session error); a write failure warns, never fails the review",
129
137
  notes: [
130
138
  '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',
139
+ 'the review posture banner appends a banner-only timeout=<duration|uncapped> field — exactly the duration agy-run hands to timeout(1), uncapped when no timeout/gtimeout binary caps the run; INFORMATIONAL only: it never enters the receipt posture or the D5 banner↔receipt parity',
140
+ 'quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts',
131
141
  ],
132
142
  },
133
143
  },