@sabaiway/agent-workflow-kit 11.2.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +2 -1
- package/SKILL.md +5 -1
- package/bridges/codex-cli-bridge/SKILL.md +14 -12
- package/bridges/codex-cli-bridge/bin/codex-exec.sh +16 -15
- package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +9 -9
- package/bridges/codex-cli-bridge/bin/codex-review.sh +14 -13
- package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +8 -8
- package/bridges/codex-cli-bridge/capability.json +4 -4
- package/bridges/codex-cli-bridge/references/driving-codex.md +2 -2
- package/bridges/codex-cli-bridge/references/sandbox-and-flags.md +6 -6
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/agents/review-lens.md +1 -0
- package/references/modes/bridge-settings.md +2 -2
- package/references/modes/now.md +30 -0
- package/references/scripts/spec-schema.mjs +54 -30
- package/references/scripts/spec-schema.test.mjs +65 -0
- package/tools/bridge-settings.mjs +1 -1
- package/tools/commands.mjs +7 -0
- package/tools/feedback-record.mjs +6 -2
- package/tools/now-cli.mjs +104 -0
- package/tools/now-facts.mjs +67 -0
- package/tools/now-plan-facts.mjs +129 -0
- package/tools/now-render.mjs +162 -0
- package/tools/now-status.mjs +145 -0
- package/tools/plan-shape-facts.mjs +1 -1
- package/tools/procedures.mjs +2 -1
- package/tools/queue-audit-cli.mjs +17 -10
- package/tools/queue-audit-rows.mjs +98 -18
- package/tools/queue-audit.mjs +58 -12
- package/tools/queue-row-name.mjs +149 -0
- package/tools/script-priors.mjs +2 -0
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
|
+
## 12.1.0 — a queue row carries a plain name a person can read, and `now` renders where the work stands from the evidence, never from the plan's own text (AD-134)
|
|
8
|
+
|
|
9
|
+
**MINOR: two additive surfaces, one series, one new refusal.** The name judge is advisory until a gate line opts in, and `now` is
|
|
10
|
+
a new read-only command beside `status`. The one behaviour a deployed `queue-audit --check` line can see change: a heading a row
|
|
11
|
+
swallows (an ATX line indented one to three spaces inside a row's body) now refuses with exit 2 and both one-keystroke corrections,
|
|
12
|
+
where the audit used to scope around it silently and misjudge the rows after it — a document the corpus never writes.
|
|
13
|
+
|
|
14
|
+
**The name judge (plan 1 of the series, landed repo-only in `da196b9`).** `tools/queue-row-name.mjs` cuts a row's display
|
|
15
|
+
title at the id the row PRESENTS as one and judges the rest as a sentence: three or more words, one of the first three carrying
|
|
16
|
+
a lower-case letter, a letter somewhere, never the id restated, never a run of the row's own status segments. `titleOf` returns
|
|
17
|
+
`{ text, name, id, judged, endLine }` from ONE parse and every `auditQueue` row now carries `name`, `id`, `nameFindings` and
|
|
18
|
+
`buckets` — the full line-numbered heading LINEAGE above the row, computed once inside the one parser.
|
|
19
|
+
`queue-audit-cli --check --require-names` is the opt-in that turns a name finding into exit 1; without it every finding is a
|
|
20
|
+
note and a gate line written before this release keeps its verdict byte for byte. A heading a row swallows — an ATX line
|
|
21
|
+
indented one to three spaces inside a row's body — is REFUSED with its line and both one-keystroke corrections, because the
|
|
22
|
+
document and the row scan read that line two ways and the corpus writes none. Two classifier defects fixed red-first: a live
|
|
23
|
+
marker counts at a segment head or wherever dated, and a record prefix owes an adjacent date at every segment head but the title's; `feedback-record`'s
|
|
24
|
+
row writer puts the claim sentence ahead of the id so the kit passes the gate it offers. Measured over this repo's queue: the
|
|
25
|
+
shipped judge reports findings on 165 of the 247 work-carrying rows of `## Pending / backlog` before the migration, and the migration moved no class cell.
|
|
26
|
+
|
|
27
|
+
**`now` (plan 2).** `/agent-workflow-kit now` — `node tools/now-cli.mjs --dir <project> [--format plain|ansi|json | --json]` —
|
|
28
|
+
renders four blocks: **NOW** (every plan `plansInFlight` returns, its derived phase, the current and the next step, the tree
|
|
29
|
+
fingerprint, the per-backend review verdict, the final receipt and the red-proof currency from `buildSummaryState`), **STEPS**
|
|
30
|
+
(the ledger rows of each plan, one status each), **QUEUE** (every work-carrying row of `docs/plans/queue.md` folded under the heading PATH it
|
|
31
|
+
carries, per-bucket per-class counts over all five classes, names never ids — an unnamed row prints `unnamed (line N)`; position is called priority
|
|
32
|
+
ONLY in a bucket whose path passes through `## Pending / backlog`, every other bucket is archive), **CAMPAIGN** (the source-size
|
|
33
|
+
practice's figures and config state; an absent opt-in config is a rendered state). The contract is `docs/ai/specs/kit/now.md`
|
|
34
|
+
(live, S1–S10 bound). Its red line: a status is a function of the row's (path, verb) pair and the evidence at that path — the
|
|
35
|
+
path fact, the changed set (ONE cached `diff --cached --name-only -z --no-renames`, both sides of a rename listed, then
|
|
36
|
+
`computeWorkingState`'s unstaged and untracked
|
|
37
|
+
sets, then the path fact; a path in both staged and unstaged is the named disagreement), and the exclusion fact (ONE cached
|
|
38
|
+
`check-ignore -z --stdin`) — and the row's prose moves none: a checked box or a terminal marker outside quotation is a CLAIM
|
|
39
|
+
printed beside the evidence-derived status wherever the two disagree. Four statuses, a closed set (`landed`, `in progress`, `pending`, `unjudged`); three
|
|
40
|
+
annotations (claim, over-budget anomaly, a red-proof bound to the row's path at the current base). A present, clean `modify`
|
|
41
|
+
row is `unjudged` and the render names WHICH fact is missing — `excluded from git here, no changed-set evidence` or `no
|
|
42
|
+
base-motion reader` — never `landed`. A sweep row (`dir/**`, `modify` only) is judged as a SET: present when its expansion on disk is non-empty, changed when
|
|
43
|
+
its pattern matches any path of a changed set (a deleted member included), excluded only when every member is. A git-dir
|
|
44
|
+
store the summary cannot trust (a malformed receipts or evidence line) withholds the tree line with the store's own cause
|
|
45
|
+
while every plan still renders; the final-run line names the receipt's verdict and gate count before its coverage token.
|
|
46
|
+
Every status line carries its evidence source. The command writes nothing in any state:
|
|
47
|
+
every git query it adds runs under `GIT_OPTIONAL_LOCKS=0`, and the suite proves a recursive content hash of `.git` identical
|
|
48
|
+
before and after a run. Exit 0 whenever anything rendered (a WITHHELD block with its cause included), 1 when nothing did (a
|
|
49
|
+
`--dir` that is not a git work tree), 2 for usage. Five modules — `now-status.mjs` (pure rules), `now-plan-facts.mjs`,
|
|
50
|
+
`now-facts.mjs` (the IO shell), `now-render.mjs`, `now-cli.mjs` — registered in the catalog (Inspect, read-only), `SKILL.md`,
|
|
51
|
+
`references/modes/now.md` and the README; the tarball pin counts 294. Stated residual: no reader in this family tells a
|
|
52
|
+
tracked, unmodified file a plan already rewrote from one it never touched, so STEPS is complete when the base-motion reader
|
|
53
|
+
lands; the write-nothing claim is proved dynamically, the structural read-graph proof waits on the core-evidence decomposition.
|
|
54
|
+
|
|
55
|
+
**Bundled codex bridge 3.8.0 — the pin moves to `gpt-6-astra` at effort `high` (AD-135).** Both wrappers pin the model
|
|
56
|
+
and the effort the maintainer chose; the quality-first guard stays a pin-integrity guard and now refuses `xhigh` exactly as it
|
|
57
|
+
refuses `low` — every shipped sentence that called the pin "the maximum effort" says "the pinned effort", in the wrappers,
|
|
58
|
+
the manifest `posture`, the bridge docs and the kit surfaces composed from the manifest (`recipes --status-line`,
|
|
59
|
+
`bridge-settings`, `procedures`). The Fast tier stays a consented per-host knob (AD-043); its copy carries the codex
|
|
60
|
+
catalog's own words for gpt-6-astra ("2x speed, increased usage", cache fetched 2026-09-05, no credit-rate figure stated)
|
|
61
|
+
and the sol-era figures (~1.5x speed, 2.5x credit rate, probed 2026-07-05) are retired from every reader. The tier caveat
|
|
62
|
+
still rides every render (`SPEND KNOB`). Version anchors: `capability.json`, `SKILL.md`, both `AW_BRIDGE_VERSION`
|
|
63
|
+
lines; the kit mirror is byte-equal to the canon. A host that arms `CODEX_SERVICE_TIER=priority` runs gpt-6-astra /
|
|
64
|
+
high / priority.
|
|
65
|
+
|
|
66
|
+
## 12.0.0 — the reader mirror refuses an open-list clause, the outgoing reader becomes a prior, the consult line names the second case and the lens walks around every check (AD-133)
|
|
67
|
+
|
|
68
|
+
**MAJOR by the AD-117 class.** `references/scripts/spec-schema.mjs` and its test are the memory 8.0.0 bodies
|
|
69
|
+
byte-identically — `spec-check` relays the new `open-list` rule unchanged, so a consumer store valid under the old canon
|
|
70
|
+
can refuse under this kit; the remedy is the closing clause, never a fourth case. `tools/script-priors.mjs` and
|
|
71
|
+
`FROZEN_PRIORS` gain the outgoing reader pair as `5.0.0`..`7.2.1` with its fixture bodies under
|
|
72
|
+
`test/fixtures/script-priors/5.0.0/`, so a deployed 5.0.0–7.2.1 reader classifies `prior`, never `custom`.
|
|
73
|
+
|
|
74
|
+
**The consult clause and the lens bullet.** `tools/procedures.mjs` `CONSULT_LINE` — two source literals joined into
|
|
75
|
+
ONE rendered line, each under the 1000-byte cap — renders inside the agy `--focus` payload "If this finding is the
|
|
76
|
+
second case against the same check, reply with the replacement invariant, not an added case."; the codex consult-brief
|
|
77
|
+
and the lens re-dispatch forms say "with the same payload"; `tools/procedures.test.mjs` pins the payload order for both
|
|
78
|
+
activities. `references/agents/review-lens.md` gains the "How to review" bullet **When the artifact is a plan, walk
|
|
79
|
+
around every check** (the S12 arm in `cheap-agents-derived.test.mjs`; the placed copy takes the same line on refresh).
|
|
80
|
+
`tools/spec-coverage.test/cli.test.mjs` characterizes the S6 exit partition (`--help` / `-h` as the sole argument, an
|
|
81
|
+
unreadable store, a stray `--reason` beside `--check`, the debt-write failure as an exception).
|
|
82
|
+
|
|
7
83
|
## 11.2.0 — a field report is triaged through a rendered procedure over a checked record (AD-132)
|
|
8
84
|
|
|
9
85
|
Three consumer field reports were triaged ad hoc — verify each claim on HEAD, record the verdict,
|
package/README.md
CHANGED
|
@@ -232,6 +232,7 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
|
|
|
232
232
|
| `/agent-workflow-kit gates` | any time | **project gate runner** — runs the verification commands **your project itself declares** in `docs/ai/gates.json` (seeded at deploy; hand-editable `{ id, title, cmd }` entries plus the optional boolean `lcovProducer`, each `cmd` one bash line) as one batch: a per-gate **PASS/FAIL table** + one machine-readable summary line, exit 0 iff all green; a failing gate's own output is shown verbatim; `--only <id>` re-runs one. Honest distinct outcomes for a missing / empty / malformed declaration — never a silent green. The runner writes nothing **by default** and never commits — opt-in `--final` runs the FULL declared matrix and mints ONE final-run receipt into the git-dir core-evidence store (status green/red, pre/post tree fingerprints, the declaration, the consumed lcov's sha; the receipt the commit-guard binds); it executes only your own declared commands (a batching convenience, not a sandbox). The velocity tier auto-approves only the exact no-`--final` form — the recording run stays explicit. |
|
|
233
233
|
| `/agent-workflow-kit setup [backend]` | opt-in, any time | **link-only** auto-setup of a bridge: places the bundled bridge skill (only into an absent / empty / managed dir — never overwrites an unmanaged one) + links its wrappers onto `PATH` via managed symlinks (idempotent; refuses to clobber a non-symlink; try `--dry-run` to preview). The binary install + the one-time subscription login stay **manual**: it prints the exact **login** command and points the binary install at each bridge's `setup/README.md`. POSIX wrappers — on Windows use WSL. Never commits, never runs a subscription CLI. |
|
|
234
234
|
| `/agent-workflow-kit status` | any time | **read-only** single view of **versions + deployment + settings + bridges**: which members (kit / memory / engine / the two bridges) are installed and at what version (with an honest "installed on this machine" note when one is behind) and — in a project — what's deployed (`docs/ai`, the version stamps, and the **visibility**: visible / hidden / unclear), and the **feature-spec adoption state** (`not adopted` / `adopting (N draft)` / `adopted (N live, M draft)` / `could not be read`, plus `declined` when recorded), plus your settings (orchestration recipes, attribution, velocity) and the bridges' readiness. The two version axes (package number vs deployment-structure head) stay decoupled. Never writes, never commits, never runs a subscription CLI. |
|
|
235
|
+
| `/agent-workflow-kit now` | any time | **read-only** answer to where work stands in four blocks: **NOW** names every plan in flight, its phase, current and next step, and the tree evidence; **STEPS** gives every ledger row its evidence-derived status; **QUEUE** folds named rows under their full heading paths and calls position priority only in the judged backlog; **CAMPAIGN** shows the source-size practice figures and config state. The plan's own text never sets a status; a contradicted claim prints beside it. A block that cannot be derived is WITHHELD with its cause; NOW has two halves, plans and tree, each independently a value or WITHHELD, and NOW itself is WITHHELD only when both are. Never writes, never commits, never runs a subscription CLI. |
|
|
235
236
|
| `/agent-workflow-kit recipes` | any time | **read-only** orchestration advisor: presents five named recipes for composing the carriers of a step — the bridges and the full-tool executor subagent — into plan → execute → review — **Solo / Reviewed / Council / Delegated / Subagent** — plans + recommends one for your environment (degrading with a stated reason when a backend isn't ready, or when the executor vehicle is missing/unusable), and offers the choice. The activity/slot registry (four activities) is rendered by `procedures` and by `set-recipe --help`. The orchestrator runs it via the bridge skills or the executor vehicle and **always commits**; the kit never executes a recipe, never runs a subscription CLI, never commits. |
|
|
236
237
|
| `/agent-workflow-kit procedures <activity>` | any time | **read-only** activity-procedures advisor: prints a named activity's ordered steps (`plan-authoring` / `plan-execution` / `routine` / `feedback-triage`) read **live** from the engine, plus the **resolved recipe per slot** from your `docs/ai/orchestration.json` (agent-writable via `set-recipe`, or hand-edited) + carrier readiness (`plan-authoring`: author, fold, review; default Reviewed when a backend is ready, Council on request; slot-aware incl. Delegated and Subagent) — and, for every dispatched backend, the **full driving contract at the point of use** (exact copy-pasteable invocation, grounding levers like agy's `--facts`/`--decided`, the round-2 `--continue` delta, guarded passthrough), verbatim from the bridge manifests (drift-guarded; each wrapper's `--help` prints the same) — except `feedback-triage`, whose record-bound block carries the check with `--excerpts`, the resolved member lines (ready bridge commands, the ready lens brief, or explicit skipped members), and either the record round-table command for a bridge obligation or the no-receipt fact otherwise: the record is the artifact. `--override <slot>=<value>` adjusts one slot per run. Composes with `recipes`; never writes, never commits, never runs a subscription CLI. |
|
|
237
238
|
| `/agent-workflow-kit set-recipe` | any time | **config writer** for `docs/ai/orchestration.json`: tell the agent your preference in plain language and it maps it to explicit `--set <activity>.<slot>=<value>` / `--unset` ops; the kit validates, **previews by default**, and writes only on `--write` (deployment-gated, atomic, symlink/TOCTOU-safe), resolving the effective recipe vs live readiness. Writes **only** that file — **never runs a backend or a subagent, never commits**; hand-editing stays fully supported. |
|
|
@@ -251,7 +252,7 @@ file), or run the guarded `/agent-workflow-kit uninstall`.
|
|
|
251
252
|
| `/agent-workflow-kit agents` | Claude Code · opt-in | **subagent vehicles** — places the five bundled subagent definitions into `.claude/agents/`: **four read-only vehicles + one full-tool `executor`**. **No read-only vehicle gets `Bash`**, and that is the load-bearing property: a read-only fan-out on a full-tool subagent shells out for facts it could have read, and every shelled command is an approval prompt you never needed to see. Three of the four ride a **cheap model** (haiku, low effort) for mechanical work — extraction sweeps, changelog fact-skeletons, gate-failure triage; the fourth, **`review-lens`**, is an ADDITIONAL independent read-only review opinion on code your configured backends have already seen (never a replacement for your review recipe, advisory like every review). The fifth, **`executor`** (`model: opus`, all tools), is the ONE vehicle with a shell and the instrument behind the **Subagent** recipe: dispatched only for a bounded, file-disjoint execution / authoring / routine slice you verify afterwards — never for read-only work, never as a review backend, and it never commits. Its state (`placed` / `customized` / `unusable` / `missing`) is what a `subagent` slot's readiness resolves from. Writing code and running gates stay off the four read-only vehicles; the executor carries a bounded slice you re-verify on your main lane, and every vehicle's output is verified. Preview by default (`--apply` writes); an existing customized file is **preserved, never overwritten**; never touches `settings*.json`, never commits. |
|
|
252
253
|
| `/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). Detection is a conservative string scan, so it over-asks on a byte that is ordinary text — searching for `=>`, or a read wearing `2>/dev/null`, prompts. That is a documented open limit: 4.1.0 built three mechanisms to narrow it and removed all three in review, each counterexample kept as a test (see Mode: hook). 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. |
|
|
253
254
|
| `/agent-workflow-kit state-block-guard` | Claude Code · opt-in | **closing-block detector** — a `Stop` hook that reads the turn's final assistant message and warns when the closing state block is defective: the «what I need from you» slot answering *nothing* (a turn that ENDS always needs a resume, so the answer is false, not merely unhelpful), or a first-person promise of imminent work in a turn that is over. Judged on the slot's first clause, so a real ask followed by a clause break and "nothing else" passes, and a promise gated on something named passes; matching is word-bounded and Unicode-aware, quoted and fenced examples are stripped, and the last STARTED block decides — an incomplete tail counts as no block rather than falling back to an earlier one. A message carrying no block at all is silent unless you pass `--require-block` — this kit does not mandate the block, and a hook that runs every turn must not warn every turn. The judgement is lexical and the mode doc names every residual it leaves. **Detection, never prevention** — a `Stop` hook cannot un-send the message it judges; what it buys is that a silent recurrence becomes a visible one. Warns via `systemMessage` and **exits 0 on every path**: never `deny`, never blocks the stop, never re-enters the model. Reads nothing but the message, makes no network call, approves nothing. This mode is **read-only and has no writer** — it ships the self-contained hook and a paste-ready wiring block you merge into `.claude/settings.json` yourself. |
|
|
254
|
-
| `/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` —
|
|
255
|
+
| `/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` — "2x speed, **increased usage**" in the catalog's own words, quality-neutral, default off — a consented spend), the codex/agy hard timeouts, the codex review byte cap, and `AGY_REVIEW_MAX_TOTAL_BYTES` (the ceiling on what an oversized agy code review may feed before it refuses pre-spend). `AGY_REVIEW_ALLOW_ADDDIR` is a **retired** compatibility key: still recognized so an existing line never warns as unknown, but it arms nothing — the writer refuses to set it and `--unset` clears it. 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. |
|
|
255
256
|
| `/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. |
|
|
256
257
|
|
|
257
258
|
It **never auto-commits** and **never overwrites** an existing `AGENTS.md` without asking.
|
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: '
|
|
6
|
+
version: '12.1.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-kit
|
|
@@ -111,6 +111,10 @@ writer — read `${CLAUDE_SKILL_DIR}/references/modes/setup.md` before acting.
|
|
|
111
111
|
|
|
112
112
|
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/status.md` before acting.
|
|
113
113
|
|
|
114
|
+
### Mode: now
|
|
115
|
+
|
|
116
|
+
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/now.md` before acting.
|
|
117
|
+
|
|
114
118
|
### Mode: recommendations
|
|
115
119
|
|
|
116
120
|
read-only — read `${CLAUDE_SKILL_DIR}/references/modes/recommendations.md` before acting.
|
|
@@ -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: '3.
|
|
5
|
+
version: '3.8.0'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# codex-cli-bridge
|
|
@@ -48,9 +48,9 @@ this skill. Both wrappers enforce the subscription path before invoking codex:
|
|
|
48
48
|
|
|
49
49
|
## Models quality-first pinned
|
|
50
50
|
|
|
51
|
-
Delegated codex work ALWAYS runs on the **PINNED model at
|
|
52
|
-
**pin** `gpt-
|
|
53
|
-
— knowingly-worse output is never traded for quota. The pin is deliberate: an explicit `-m gpt-
|
|
51
|
+
Delegated codex work ALWAYS runs on the **PINNED model at the PINNED reasoning effort**: the wrappers
|
|
52
|
+
**pin** `gpt-6-astra` / `high` and **refuse** (exit 2, loud) a non-default `CODEX_MODEL` / `CODEX_EFFORT`
|
|
53
|
+
— knowingly-worse output is never traded for quota. The pin is deliberate: an explicit `-m gpt-6-astra`
|
|
54
54
|
names one model rather than following the CLI's current default. That the pinned id is also the
|
|
55
55
|
*strongest* selectable Codex model is a **separate, time-bounded claim**, checked BY HAND against
|
|
56
56
|
<https://developers.openai.com/codex/models>. There is **no automated gate and this file records no
|
|
@@ -63,8 +63,10 @@ either way between releases:
|
|
|
63
63
|
available until someone re-checks the page.
|
|
64
64
|
|
|
65
65
|
The guard is therefore a **pin-integrity** guard, not a quality guarantee: it enforces that runs use
|
|
66
|
-
the id named here, and it refuses a *stronger* model exactly as it refuses a weaker one.
|
|
67
|
-
|
|
66
|
+
the id named here, and it refuses a *stronger* model exactly as it refuses a weaker one. The effort
|
|
67
|
+
pin is the same kind of decision: `high` is a deliberate posture, not the catalog maximum (`xhigh`,
|
|
68
|
+
`max` and `ultra` exist above it), and the guard refuses a higher effort exactly as it refuses a lower
|
|
69
|
+
one. Read a refusal as "not the pinned id", never as "a downgrade was prevented".
|
|
68
70
|
|
|
69
71
|
Economy comes only from **quality-neutral waste removal** (clean capture, a hard timeout,
|
|
70
72
|
a precomputed review diff, `resume` instead of re-sending context), never from a downgrade.
|
|
@@ -75,8 +77,8 @@ output as real delegated work.
|
|
|
75
77
|
|
|
76
78
|
| Variable | Default | Effect |
|
|
77
79
|
|---|---|---|
|
|
78
|
-
| `CODEX_MODEL` | `gpt-
|
|
79
|
-
| `CODEX_EFFORT` | `
|
|
80
|
+
| `CODEX_MODEL` | `gpt-6-astra` (pinned) | model passed to `-m`; a non-default is REFUSED unless `CODEX_PROBE=1` |
|
|
81
|
+
| `CODEX_EFFORT` | `high` (pinned) | reasoning effort (`-c model_reasoning_effort=…`); non-default REFUSED unless `CODEX_PROBE=1` |
|
|
80
82
|
|
|
81
83
|
`codex --version` reports the CLI version, **not** the model list. Quota is metered in **messages**
|
|
82
84
|
(a rolling 5h window + a weekly cap), not raw tokens — which is why the levers above are about removing
|
|
@@ -156,10 +158,10 @@ defeat a policy is guarded — see [§ Models](#models-quality-first-pinned).
|
|
|
156
158
|
|
|
157
159
|
| Variable | Default | Effect |
|
|
158
160
|
|---|---|---|
|
|
159
|
-
| `CODEX_MODEL` | `gpt-
|
|
160
|
-
| `CODEX_EFFORT` | `
|
|
161
|
+
| `CODEX_MODEL` | `gpt-6-astra` (pinned) | model; non-default REFUSED unless `CODEX_PROBE=1` |
|
|
162
|
+
| `CODEX_EFFORT` | `high` (pinned) | reasoning effort; non-default REFUSED unless `CODEX_PROBE=1` |
|
|
161
163
|
| `CODEX_HARD_TIMEOUT` | `3600` (exec) / `1800` (review) | hard wall-clock cap (seconds) via `timeout`/`gtimeout`; exit 124/137 ⇒ "exceeded hard cap". No `timeout` binary ⇒ a nonce-less exec warns loudly + runs uncapped, a **nonced** exec REFUSES pre-spend (an accounted dispatch that cannot be capped can never honour the terminal-exit rule), and `codex-review` REFUSES pre-spend (fail-closed preflight). |
|
|
162
|
-
| `CODEX_SERVICE_TIER` | unset (standard tier) | **SPEND knob**: `priority` (catalog name "Fast") =
|
|
164
|
+
| `CODEX_SERVICE_TIER` | unset (standard tier) | **SPEND knob**: `priority` (catalog name "Fast") = "2x speed, **increased usage**" in the codex catalog's own words for gpt-6-astra (cache fetched 2026-09-05); it states no credit-rate figure — quality-neutral (same model). codex accepts any `-c service_tier` string silently (probe-verified), so the wrapper validates: an unsupported value warns and runs standard. Env or settings file. |
|
|
163
165
|
| `CODEX_SESSION_FILE` | `./.codex-last-session` | where `codex-exec` records the session id and where `--resume-last` reads it |
|
|
164
166
|
| `CODEX_REVIEW_MAX_TOTAL_BYTES` | `1500000` | `codex-review code`: above this the assembled diff goes via a git-dir temp file instead of inline — never truncated |
|
|
165
167
|
| `AW_REVIEW_NONCE` | unset | the flow dispatch nonce (safe grammar `[A-Za-z0-9._-]{1,64}` — anything else refuses pre-spend). `codex-review … --nonce <n>` is the plain-argument equivalent (one seam; flag and a non-empty env must agree, a disagreeing pair refuses pre-spend) — the lane for hosts whose dispatch policy has no env-prefix form. When supplied, a successful review first mints the finding MANIFEST `agent-workflow-finding-manifest-codex-<nonce>.json` beside the receipts file (atomic, no-clobber, ORDERED before the receipt append) — a failed mint EXCLUDES the receipt, so a nonce-supplied dispatch never lands a receipt without its readable manifest; nonce-less runs add no nonce field and mint nothing (the `wrapperVersion` field every receipt carries moves with each release) |
|
|
@@ -210,7 +212,7 @@ skipped entirely without a nonce: the wrapper is byte-unchanged, writes no artif
|
|
|
210
212
|
`${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf` holds `KEY=VALUE` lines,
|
|
211
213
|
**parsed, never sourced** — a file line can never execute code. Precedence: explicit env (even
|
|
212
214
|
empty — `KEY=` disables a knob for one run) > file > built-in default. File-settable keys for this
|
|
213
|
-
bridge: `CODEX_SERVICE_TIER` (the Fast tier — **
|
|
215
|
+
bridge: `CODEX_SERVICE_TIER` (the Fast tier — **increased usage**; enabling it is a consented
|
|
214
216
|
per-host spend decision, never a default), `CODEX_HARD_TIMEOUT`, `CODEX_REVIEW_MAX_TOTAL_BYTES` —
|
|
215
217
|
exactly the manifest `settings` block (the single source; the wrapper constants and `--help` are
|
|
216
218
|
drift-guarded against it). Model/effort keys are **not** file-settable — the quality guard above
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
# - network access OFF: new dependencies / network installs are done by a human
|
|
14
14
|
# - approval_policy=never: there is no TTY in exec; anything needing escalation
|
|
15
15
|
# is refused and reported, then handled by hand
|
|
16
|
-
# - the PINNED model at
|
|
16
|
+
# - the PINNED model at the PINNED reasoning effort (quality-first — see below)
|
|
17
17
|
# - git WRITES are blocked by a physical shim (codex spawns git via execve, which
|
|
18
18
|
# bypasses shell functions) — the orchestrator owns the commit boundary.
|
|
19
19
|
#
|
|
20
20
|
# Quality-first (hard rule): delegated codex work ALWAYS runs on the PINNED
|
|
21
|
-
# model at
|
|
21
|
+
# model at the PINNED reasoning effort. The defaults below are pinned and the wrapper
|
|
22
22
|
# REFUSES a non-default CODEX_MODEL/CODEX_EFFORT — knowingly-worse output is never
|
|
23
23
|
# traded for quota. The ONLY exception is a throwaway probe whose result does not
|
|
24
24
|
# depend on effort: set CODEX_PROBE=1 (echoed loudly) to relax the guard. Economy
|
|
@@ -149,7 +149,7 @@ Notes:
|
|
|
149
149
|
|
|
150
150
|
Settings file (KEY=VALUE, parsed never sourced; env wins over file, file wins over built-in default):
|
|
151
151
|
${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf
|
|
152
|
-
CODEX_SERVICE_TIER — service tier: 'priority' (Fast —
|
|
152
|
+
CODEX_SERVICE_TIER — service tier: 'priority' (Fast — "2x speed, increased usage", the codex catalog's own words for gpt-6-astra, cache fetched 2026-09-05; it states no credit-rate figure); a consented SPEND knob, default off (standard tier)
|
|
153
153
|
CODEX_HARD_TIMEOUT — hard wall-clock cap, integer seconds 1..86400 (built-in default 3600)
|
|
154
154
|
|
|
155
155
|
Environment: CODEX_HARD_TIMEOUT (seconds, default 3600), CODEX_PROBE=1 (throwaway probe only), AW_DISPATCH_NONCE (delegation dispatch nonce — mints the exec receipt; the --nonce <n> flag is its plain-argument equivalent), AW_DELEGATION_STORE (absolute delegation-store path; its dirname is where the receipt lands).
|
|
@@ -319,19 +319,20 @@ aw_resolve_timeout_bin() {
|
|
|
319
319
|
printf '%s' "$bin"
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
DEFAULT_CODEX_MODEL="gpt-
|
|
323
|
-
DEFAULT_CODEX_EFFORT="
|
|
322
|
+
DEFAULT_CODEX_MODEL="gpt-6-astra" # pinned model id (see SKILL.md: strongest-model status is hand-checked, ungated)
|
|
323
|
+
DEFAULT_CODEX_EFFORT="high" # pinned reasoning effort — a deliberate posture, not the catalog maximum
|
|
324
324
|
CODEX_MODEL="${CODEX_MODEL:-$DEFAULT_CODEX_MODEL}"
|
|
325
325
|
CODEX_EFFORT="${CODEX_EFFORT:-$DEFAULT_CODEX_EFFORT}"
|
|
326
|
-
# Generous hard wall-clock cap, sized for a slow
|
|
326
|
+
# Generous hard wall-clock cap, sized for a slow run at the pinned effort (subscription latency
|
|
327
327
|
# varies — a trivial reply was observed taking minutes). Raise for a known-healthy
|
|
328
328
|
# long run; lowering it only risks killing real work.
|
|
329
329
|
CODEX_HARD_TIMEOUT="${CODEX_HARD_TIMEOUT:-3600}"
|
|
330
|
-
# Codex service tier (quality-neutral speed knob
|
|
330
|
+
# Codex service tier (quality-neutral speed knob): default EMPTY ⇒ no
|
|
331
331
|
# service_tier flag (standard tier) — enabling Fast is a consented per-host SPEND act, never a
|
|
332
332
|
# silent default. The only server-catalog tier id on this subscription is 'priority' (catalog
|
|
333
|
-
# display name "Fast":
|
|
334
|
-
#
|
|
333
|
+
# display name "Fast": "2x speed, increased usage" in the catalog's own words for gpt-6-astra, cache
|
|
334
|
+
# fetched 2026-09-05; it states no credit-rate figure; quality-neutral — same model). codex itself
|
|
335
|
+
# accepts ANY -c service_tier string silently (probe-verified), so
|
|
335
336
|
# the wrapper validates the effective value: an unsupported one warns and runs on the standard
|
|
336
337
|
# tier — a typo can never silently masquerade as Fast.
|
|
337
338
|
CODEX_SERVICE_TIER="${CODEX_SERVICE_TIER:-}"
|
|
@@ -372,14 +373,14 @@ CHATGPT_LOGIN_GUARD="Logged in using ChatGPT"
|
|
|
372
373
|
# receipt this wrapper mints; scripts/release/version-sync.mjs bumps it under the one-anchor-per-file
|
|
373
374
|
# rule, so a release can never leave it behind (the AD-053 drift class).
|
|
374
375
|
AW_RECEIPT_BACKEND="codex"
|
|
375
|
-
AW_BRIDGE_VERSION="3.
|
|
376
|
+
AW_BRIDGE_VERSION="3.8.0" # aw-version-anchor
|
|
376
377
|
# The kill grace handed to timeout(1) as --kill-after, and recorded in the receipt as killGraceS:
|
|
377
378
|
# ONE constant, so the number the ledger checks against the dispatch deadline is the number the run
|
|
378
379
|
# actually applied.
|
|
379
380
|
CODEX_KILL_GRACE_S=15
|
|
380
381
|
|
|
381
382
|
# --- Quality-first guard: refuse any non-pinned model/effort ---------------
|
|
382
|
-
# Real delegated runs must use the pinned model at
|
|
383
|
+
# Real delegated runs must use the pinned model at the pinned effort. A throwaway probe
|
|
383
384
|
# (effort-independent result) may opt out with CODEX_PROBE=1, announced loudly.
|
|
384
385
|
if [[ "${CODEX_PROBE:-}" == "1" ]]; then
|
|
385
386
|
echo "warning: CODEX_PROBE=1 — THROWAWAY PROBE MODE. Quality guards relaxed; do NOT use this run's" >&2
|
|
@@ -387,13 +388,13 @@ if [[ "${CODEX_PROBE:-}" == "1" ]]; then
|
|
|
387
388
|
else
|
|
388
389
|
if [[ "$CODEX_MODEL" != "$DEFAULT_CODEX_MODEL" ]]; then
|
|
389
390
|
echo "error: CODEX_MODEL='$CODEX_MODEL' is not the pinned model '$DEFAULT_CODEX_MODEL'." >&2
|
|
390
|
-
echo " Delegated codex work must run on the pinned model at
|
|
391
|
+
echo " Delegated codex work must run on the pinned model at the pinned effort (quality-first)." >&2
|
|
391
392
|
echo " For a throwaway probe whose result is effort-independent, set CODEX_PROBE=1." >&2
|
|
392
393
|
exit 2
|
|
393
394
|
fi
|
|
394
395
|
if [[ "$CODEX_EFFORT" != "$DEFAULT_CODEX_EFFORT" ]]; then
|
|
395
|
-
echo "error: CODEX_EFFORT='$CODEX_EFFORT' is not the pinned
|
|
396
|
-
echo " Delegated codex work must run at
|
|
396
|
+
echo "error: CODEX_EFFORT='$CODEX_EFFORT' is not the pinned effort '$DEFAULT_CODEX_EFFORT'." >&2
|
|
397
|
+
echo " Delegated codex work must run at the pinned reasoning effort (quality-first)." >&2
|
|
397
398
|
echo " For a throwaway probe whose result is effort-independent, set CODEX_PROBE=1." >&2
|
|
398
399
|
exit 2
|
|
399
400
|
fi
|
|
@@ -932,7 +933,7 @@ if [[ -n "$resume_mode" ]]; then
|
|
|
932
933
|
else
|
|
933
934
|
# `-o` writes ONLY codex's final message; `--json` streams structured events
|
|
934
935
|
# (thread.started carries the session id). CoT is dropped and colour disabled, so
|
|
935
|
-
# the captured surfaces stay clean. Reasoning still runs at
|
|
936
|
+
# the captured surfaces stay clean. Reasoning still runs at the pinned effort — quality is
|
|
936
937
|
# unchanged; we only stop printing the noise.
|
|
937
938
|
codex_cmd=(codex exec
|
|
938
939
|
--ignore-user-config
|
|
@@ -194,10 +194,10 @@ describe('codex-exec.sh — quality-first model/effort guard (1.1)', { concurren
|
|
|
194
194
|
|
|
195
195
|
it('refuses a non-default CODEX_EFFORT', async () => {
|
|
196
196
|
const sb = makeSandbox();
|
|
197
|
-
const r = await run(sb, { env: { CODEX_EFFORT: '
|
|
197
|
+
const r = await run(sb, { env: { CODEX_EFFORT: 'xhigh' } });
|
|
198
198
|
rmSync(sb.root, { recursive: true, force: true });
|
|
199
199
|
assert.notEqual(r.status, 0);
|
|
200
|
-
assert.match(r.stderr, /not the pinned
|
|
200
|
+
assert.match(r.stderr, /not the pinned effort/);
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
it('CODEX_PROBE=1 allows a non-default model and warns loudly', async () => {
|
|
@@ -650,8 +650,8 @@ describe('codex-exec.sh — preflight (unchanged invariants)', { concurrency: 2
|
|
|
650
650
|
|
|
651
651
|
describe('codex-exec.sh — resume entrypoint restates every invariant (3.1)', { concurrency: 2 }, () => {
|
|
652
652
|
const RESUME_INVARIANTS = [
|
|
653
|
-
/(^|\n)resume(\n|$)/, /(^|\n)--ignore-user-config(\n|$)/, /(^|\n)gpt-
|
|
654
|
-
/model_reasoning_effort=
|
|
653
|
+
/(^|\n)resume(\n|$)/, /(^|\n)--ignore-user-config(\n|$)/, /(^|\n)gpt-6-astra(\n|$)/,
|
|
654
|
+
/model_reasoning_effort=high/, /sandbox_mode=workspace-write/,
|
|
655
655
|
/approval_policy=never/, /sandbox_workspace_write\.network_access=false/,
|
|
656
656
|
];
|
|
657
657
|
|
|
@@ -1546,7 +1546,7 @@ describe('codex-exec.sh — dispatch-posture labeling (D5, AD-061)', { concurren
|
|
|
1546
1546
|
const lines = banners(r.stderr);
|
|
1547
1547
|
assert.equal(lines.length, 1, 'EXACTLY ONE banner line per run');
|
|
1548
1548
|
assert.equal(lines[0],
|
|
1549
|
-
'exec posture: model=gpt-
|
|
1549
|
+
'exec posture: model=gpt-6-astra effort=high tier=standard sandbox=workspace-write session=fresh timeout=3600s');
|
|
1550
1550
|
});
|
|
1551
1551
|
|
|
1552
1552
|
it('an ARMED Fast tier rides the banner (tier=priority)', async () => {
|
|
@@ -1642,11 +1642,11 @@ describe('codex-exec.sh — dispatch-posture labeling (D5, AD-061)', { concurren
|
|
|
1642
1642
|
|
|
1643
1643
|
it('a banner field carrying CONTROL BYTES refuses pre-spend (model / effort / tier / timeout / DEL)', async () => {
|
|
1644
1644
|
const cases = [
|
|
1645
|
-
{ CODEX_MODEL: `gpt-
|
|
1646
|
-
{ CODEX_EFFORT: `
|
|
1645
|
+
{ CODEX_MODEL: `gpt-6-astra${String.fromCharCode(1)}` },
|
|
1646
|
+
{ CODEX_EFFORT: `high${String.fromCharCode(2)}` },
|
|
1647
1647
|
{ CODEX_SERVICE_TIER: `priority${String.fromCharCode(3)}` },
|
|
1648
1648
|
{ CODEX_HARD_TIMEOUT: `3600${String.fromCharCode(4)}` },
|
|
1649
|
-
{ CODEX_MODEL: `gpt-
|
|
1649
|
+
{ CODEX_MODEL: `gpt-6-astra${String.fromCharCode(127)}` },
|
|
1650
1650
|
];
|
|
1651
1651
|
for (const env of cases) {
|
|
1652
1652
|
const sb = makeSandbox();
|
|
@@ -2047,7 +2047,7 @@ describe('codex-exec.sh — the pre-spend reservation (D1/D8)', { concurrency: 2
|
|
|
2047
2047
|
assert.equal(r.status, 71, r.stderr);
|
|
2048
2048
|
assert.equal(held.state, 'reserved');
|
|
2049
2049
|
assert.equal(held.wrapperVersion, MANIFEST.version, 'the receipt stamps the bridge version version-sync bumps');
|
|
2050
|
-
assert.deepEqual(held.posture, { model: 'gpt-
|
|
2050
|
+
assert.deepEqual(held.posture, { model: 'gpt-6-astra', effort: 'high', tier: null });
|
|
2051
2051
|
assert.equal(held.capS, 3600);
|
|
2052
2052
|
assert.equal(held.killGraceS, 15);
|
|
2053
2053
|
assert.match(held.contractDigest, /^[0-9a-f]{64}$/);
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
# back as a validated JSON object, with a raw-text fallback.
|
|
22
22
|
#
|
|
23
23
|
# Auth/policy: subscription-only, identical to codex-exec.sh. Quality-first: the
|
|
24
|
-
# review runs on the PINNED model at
|
|
24
|
+
# review runs on the PINNED model at the pinned effort (advisory findings still bear on
|
|
25
25
|
# what ships, so the same pin-integrity guard applies; CODEX_PROBE=1 relaxes it for
|
|
26
26
|
# a throwaway probe only).
|
|
27
27
|
#
|
|
@@ -39,7 +39,7 @@ set -euo pipefail
|
|
|
39
39
|
case "${1:-}" in
|
|
40
40
|
--help|-h)
|
|
41
41
|
cat <<'HELP'
|
|
42
|
-
codex-review — read-only ADVISORY review by the OpenAI Codex CLI (subscription-only; the PINNED model at
|
|
42
|
+
codex-review — read-only ADVISORY review by the OpenAI Codex CLI (subscription-only; the PINNED model at the pinned effort).
|
|
43
43
|
|
|
44
44
|
Usage:
|
|
45
45
|
codex-review plan <plan-file> [--nonce <n>]
|
|
@@ -91,7 +91,7 @@ Receipt:
|
|
|
91
91
|
|
|
92
92
|
Settings file (KEY=VALUE, parsed never sourced; env wins over file, file wins over built-in default):
|
|
93
93
|
${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf
|
|
94
|
-
CODEX_SERVICE_TIER — service tier: 'priority' (Fast —
|
|
94
|
+
CODEX_SERVICE_TIER — service tier: 'priority' (Fast — "2x speed, increased usage", the codex catalog's own words for gpt-6-astra, cache fetched 2026-09-05; it states no credit-rate figure); a consented SPEND knob, default off (standard tier)
|
|
95
95
|
CODEX_HARD_TIMEOUT — hard wall-clock cap, integer seconds 1..86400 (built-in default 1800)
|
|
96
96
|
CODEX_REVIEW_MAX_TOTAL_BYTES — inline-payload cap, integer bytes 1..100000000 (default 1500000); above it the diff rides via a git-dir temp file
|
|
97
97
|
|
|
@@ -279,15 +279,15 @@ aw_resolve_timeout_bin() {
|
|
|
279
279
|
printf '%s' "$bin"
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
DEFAULT_CODEX_MODEL="gpt-
|
|
283
|
-
DEFAULT_CODEX_EFFORT="
|
|
282
|
+
DEFAULT_CODEX_MODEL="gpt-6-astra"
|
|
283
|
+
DEFAULT_CODEX_EFFORT="high"
|
|
284
284
|
# Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
|
|
285
285
|
# version (drift-guarded by codex-review.test.mjs against capability.json).
|
|
286
286
|
AW_RECEIPT_BACKEND="codex"
|
|
287
|
-
AW_BRIDGE_VERSION="3.
|
|
287
|
+
AW_BRIDGE_VERSION="3.8.0" # aw-version-anchor
|
|
288
288
|
CODEX_MODEL="${CODEX_MODEL:-$DEFAULT_CODEX_MODEL}"
|
|
289
289
|
CODEX_EFFORT="${CODEX_EFFORT:-$DEFAULT_CODEX_EFFORT}"
|
|
290
|
-
# Generous hard cap for a slow
|
|
290
|
+
# Generous hard cap for a slow review at the pinned effort (subscription latency varies).
|
|
291
291
|
CODEX_HARD_TIMEOUT="${CODEX_HARD_TIMEOUT:-1800}"
|
|
292
292
|
# Above this assembled-payload size (bytes), the diff goes via a git-dir-local temp
|
|
293
293
|
# file instead of inline — never truncated.
|
|
@@ -298,11 +298,12 @@ CODEX_REVIEW_MAX_TOTAL_BYTES="${CODEX_REVIEW_MAX_TOTAL_BYTES:-1500000}"
|
|
|
298
298
|
# file), so the budget is pinned at the DEFAULT inline-payload cap — the map can never outgrow the
|
|
299
299
|
# whole payload, and every realistic repo's map assembles byte-unchanged.
|
|
300
300
|
AW_REVIEW_MAP_BUDGET_BYTES=1500000
|
|
301
|
-
# Codex service tier (quality-neutral speed knob
|
|
301
|
+
# Codex service tier (quality-neutral speed knob): default EMPTY ⇒ no
|
|
302
302
|
# service_tier flag (standard tier) — enabling Fast is a consented per-host SPEND act, never a
|
|
303
303
|
# silent default. The only server-catalog tier id on this subscription is 'priority' (catalog
|
|
304
|
-
# display name "Fast":
|
|
305
|
-
#
|
|
304
|
+
# display name "Fast": "2x speed, increased usage" in the catalog's own words for gpt-6-astra, cache
|
|
305
|
+
# fetched 2026-09-05; it states no credit-rate figure; quality-neutral — same model). codex itself
|
|
306
|
+
# accepts ANY -c service_tier string silently (probe-verified), so
|
|
306
307
|
# the wrapper validates the effective value: an unsupported one warns and runs on the standard
|
|
307
308
|
# tier — a typo can never silently masquerade as Fast.
|
|
308
309
|
CODEX_SERVICE_TIER="${CODEX_SERVICE_TIER:-}"
|
|
@@ -365,13 +366,13 @@ if [[ "${CODEX_PROBE:-}" == "1" ]]; then
|
|
|
365
366
|
else
|
|
366
367
|
if [[ "$CODEX_MODEL" != "$DEFAULT_CODEX_MODEL" ]]; then
|
|
367
368
|
echo "error: CODEX_MODEL='$CODEX_MODEL' is not the pinned model '$DEFAULT_CODEX_MODEL'." >&2
|
|
368
|
-
echo " A delegated review must run on the pinned model at
|
|
369
|
+
echo " A delegated review must run on the pinned model at the pinned effort (quality-first)." >&2
|
|
369
370
|
echo " For a throwaway probe whose result is effort-independent, set CODEX_PROBE=1." >&2
|
|
370
371
|
exit 2
|
|
371
372
|
fi
|
|
372
373
|
if [[ "$CODEX_EFFORT" != "$DEFAULT_CODEX_EFFORT" ]]; then
|
|
373
|
-
echo "error: CODEX_EFFORT='$CODEX_EFFORT' is not the pinned
|
|
374
|
-
echo " A delegated review must run at
|
|
374
|
+
echo "error: CODEX_EFFORT='$CODEX_EFFORT' is not the pinned effort '$DEFAULT_CODEX_EFFORT'." >&2
|
|
375
|
+
echo " A delegated review must run at the pinned reasoning effort (quality-first)." >&2
|
|
375
376
|
echo " For a throwaway probe whose result is effort-independent, set CODEX_PROBE=1." >&2
|
|
376
377
|
exit 2
|
|
377
378
|
fi
|
|
@@ -172,10 +172,10 @@ describe('codex-review.sh — quality-first model/effort guard (1.1)', { concurr
|
|
|
172
172
|
|
|
173
173
|
it('refuses a non-default CODEX_EFFORT', async () => {
|
|
174
174
|
const sb = makeSandbox();
|
|
175
|
-
const r = await run(sb, { env: { CODEX_EFFORT: '
|
|
175
|
+
const r = await run(sb, { env: { CODEX_EFFORT: 'xhigh' } });
|
|
176
176
|
rmSync(sb.root, { recursive: true, force: true });
|
|
177
177
|
assert.notEqual(r.status, 0);
|
|
178
|
-
assert.match(r.stderr, /not the pinned
|
|
178
|
+
assert.match(r.stderr, /not the pinned effort/);
|
|
179
179
|
});
|
|
180
180
|
|
|
181
181
|
it('CODEX_PROBE=1 relaxes the guard and warns', async () => {
|
|
@@ -1646,8 +1646,8 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2
|
|
|
1646
1646
|
const receipts = readReceipts(sb.repo);
|
|
1647
1647
|
rmSync(sb.root, { recursive: true, force: true });
|
|
1648
1648
|
assert.equal(r.status, 0, r.stderr);
|
|
1649
|
-
assert.match(r.stderr, /review posture: model=gpt-
|
|
1650
|
-
assert.deepEqual(receipts[0].posture, { model: 'gpt-
|
|
1649
|
+
assert.match(r.stderr, /review posture: model=gpt-6-astra effort=high tier=standard/, 'the banner states the actual run posture');
|
|
1650
|
+
assert.deepEqual(receipts[0].posture, { model: 'gpt-6-astra', effort: 'high', tier: null }, 'banner ↔ receipt parity (standard tier = null)');
|
|
1651
1651
|
assert.deepEqual(Object.keys(receipts[0]), Object.keys(RECEIPT_FIXTURE), 'fixture key set + order');
|
|
1652
1652
|
});
|
|
1653
1653
|
|
|
@@ -1657,7 +1657,7 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2
|
|
|
1657
1657
|
const receipts = readReceipts(sb.repo);
|
|
1658
1658
|
rmSync(sb.root, { recursive: true, force: true });
|
|
1659
1659
|
assert.equal(r.status, 0, r.stderr);
|
|
1660
|
-
assert.match(r.stderr, /review posture: model=gpt-
|
|
1660
|
+
assert.match(r.stderr, /review posture: model=gpt-6-astra effort=high tier=priority/);
|
|
1661
1661
|
assert.equal(receipts[0].posture.tier, 'priority');
|
|
1662
1662
|
});
|
|
1663
1663
|
|
|
@@ -1674,7 +1674,7 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2
|
|
|
1674
1674
|
|
|
1675
1675
|
it('a posture value carrying CONTROL BYTES refuses pre-spend, BEFORE the pinned-model guard', async () => {
|
|
1676
1676
|
const sb = makeSandbox();
|
|
1677
|
-
const r = await run(sb, { env: { CODEX_MODEL: `gpt-
|
|
1677
|
+
const r = await run(sb, { env: { CODEX_MODEL: `gpt-6-astra${String.fromCharCode(1)}` } });
|
|
1678
1678
|
const receipts = readReceipts(sb.repo);
|
|
1679
1679
|
rmSync(sb.root, { recursive: true, force: true });
|
|
1680
1680
|
assert.notEqual(r.status, 0);
|
|
@@ -1689,7 +1689,7 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2
|
|
|
1689
1689
|
const receipts = readReceipts(sb.repo);
|
|
1690
1690
|
rmSync(sb.root, { recursive: true, force: true });
|
|
1691
1691
|
assert.equal(r.status, 0, r.stderr);
|
|
1692
|
-
assert.match(r.stderr, /^review posture: model=gpt-
|
|
1692
|
+
assert.match(r.stderr, /^review posture: model=gpt-6-astra effort=high tier=standard timeout=1800s$/m);
|
|
1693
1693
|
assert.deepEqual(Object.keys(receipts[0].posture), ['model', 'effort', 'tier'], 'timeout never enters the receipt posture');
|
|
1694
1694
|
});
|
|
1695
1695
|
|
|
@@ -1715,7 +1715,7 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2
|
|
|
1715
1715
|
|
|
1716
1716
|
it('a DEL (0x7f) byte in a banner field refuses pre-spend like the C0 range', async () => {
|
|
1717
1717
|
const sb = makeSandbox();
|
|
1718
|
-
const r = await run(sb, { env: { CODEX_MODEL: `gpt-
|
|
1718
|
+
const r = await run(sb, { env: { CODEX_MODEL: `gpt-6-astra${String.fromCharCode(127)}` } });
|
|
1719
1719
|
const receipts = readReceipts(sb.repo);
|
|
1720
1720
|
rmSync(sb.root, { recursive: true, force: true });
|
|
1721
1721
|
assert.notEqual(r.status, 0);
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"schema": 1,
|
|
4
4
|
"name": "codex-cli-bridge",
|
|
5
5
|
"kind": "execution-backend",
|
|
6
|
-
"version": "3.
|
|
7
|
-
"posture": { "model": "gpt-
|
|
6
|
+
"version": "3.8.0",
|
|
7
|
+
"posture": { "model": "gpt-6-astra", "effort": "high", "tier": null },
|
|
8
8
|
"provides": ["execute", "review"],
|
|
9
9
|
"roles": {
|
|
10
10
|
"execute": {
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
],
|
|
142
142
|
"guardrails": [
|
|
143
143
|
{ "value": "read-only sandbox — codex cannot edit, create or delete a file", "enforcement": "enforced", "source": "bin/codex-review.sh" },
|
|
144
|
-
{ "value": "runs on the pinned model at
|
|
144
|
+
{ "value": "runs on the pinned model at the pinned effort", "enforcement": "enforced", "condition": "unless CODEX_PROBE=1 relaxes the guard for a throwaway probe", "source": "bin/codex-review.sh" },
|
|
145
145
|
{ "value": "a successful review appends one receipt line the review-state gate reads", "enforcement": "enforced", "condition": "a receipt write failure warns and the review still succeeds — the tree then reads un-receipted", "source": "capability.json roles.review.contract.receipt" }
|
|
146
146
|
],
|
|
147
147
|
"customHooks": ["CODEX_PROBE"]
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
"values": ["priority"],
|
|
194
194
|
"default": null,
|
|
195
195
|
"appliesTo": ["codex-exec", "codex-review"],
|
|
196
|
-
"effect": "codex service tier; 'priority' (catalog display name Fast) =
|
|
196
|
+
"effect": "codex service tier; 'priority' (catalog display name Fast) = \"2x speed, increased usage\" in the codex catalog's own words for gpt-6-astra (cache fetched 2026-09-05); it states no credit-rate figure — quality-neutral (same model). Unset/empty ⇒ no service_tier flag (standard tier). SPEND KNOB: enabling it is a consented per-host act, never a default. codex itself accepts any -c service_tier string silently, so the wrapper validates the value."
|
|
197
197
|
},
|
|
198
198
|
{
|
|
199
199
|
"key": "CODEX_HARD_TIMEOUT",
|
|
@@ -20,7 +20,7 @@ judgment.
|
|
|
20
20
|
|
|
21
21
|
## Quality-first: model & effort are pinned
|
|
22
22
|
|
|
23
|
-
Delegated codex work ALWAYS runs on the PINNED model at
|
|
23
|
+
Delegated codex work ALWAYS runs on the PINNED model at the pinned effort: `gpt-6-astra` / `high` are **pinned**
|
|
24
24
|
and a non-default `CODEX_MODEL`/`CODEX_EFFORT` is **refused** (exit 2). That the pinned id is still the
|
|
25
25
|
strongest selectable model is a hand-checked claim with no automated gate and no recorded date — see
|
|
26
26
|
SKILL.md. Do not try to "tune down" the
|
|
@@ -92,7 +92,7 @@ codex-exec --resume <session-id> <file|-> # explicit session id
|
|
|
92
92
|
|
|
93
93
|
Resume continues the SAME codex session, so you avoid re-sending the original context. It runs through
|
|
94
94
|
the wrapper, which **re-establishes every invariant** (subscription-only `*_API_KEY` scrub,
|
|
95
|
-
`--ignore-user-config`, the pinned `gpt-
|
|
95
|
+
`--ignore-user-config`, the pinned `gpt-6-astra`/`high`) and **restates the full posture via `-c`** —
|
|
96
96
|
because `codex exec resume` resets the sandbox/approval/network posture and rejects `-s`/`--add-dir`/`-C`,
|
|
97
97
|
the wrapper passes `-c sandbox_mode=workspace-write -c approval_policy=never -c
|
|
98
98
|
sandbox_workspace_write.network_access=false` explicitly. A resume takes no passthrough flags and an
|
|
@@ -47,7 +47,7 @@ carries the session id) into the run trace, with stderr merged into it; `--color
|
|
|
47
47
|
`--color`, which stays on the fresh lane), so the resume lane is no longer the odd one out: it used
|
|
48
48
|
to print its final message straight to stdout with the event stream nowhere, which left the very
|
|
49
49
|
mode a nested-sandbox incident fired on without a structured evidence surface. Net effect: the wrapper prints just the final answer. **Reasoning still runs at
|
|
50
|
-
|
|
50
|
+
the pinned effort** — quality is unchanged; only the *noise* is dropped. On success `codex-exec` extracts the
|
|
51
51
|
session id from the trace and records it to `${CODEX_SESSION_FILE:-./.codex-last-session}` (so
|
|
52
52
|
`--resume-last` can find it) and echoes `session: <id>` to stderr. On a missing/empty final-message
|
|
53
53
|
file it falls back to the trace tail (loud, never silent).
|
|
@@ -63,8 +63,8 @@ failure is proven.
|
|
|
63
63
|
|
|
64
64
|
## Quality-first guard (pinned model & effort)
|
|
65
65
|
|
|
66
|
-
The wrappers default `CODEX_MODEL=gpt-
|
|
67
|
-
non-default — delegated work always uses the PINNED model at
|
|
66
|
+
The wrappers default `CODEX_MODEL=gpt-6-astra` and `CODEX_EFFORT=high` and **refuse** (exit 2, loud) any
|
|
67
|
+
non-default — delegated work always uses the PINNED model at the pinned effort; quality is never traded for
|
|
68
68
|
quota. (Whether the pinned id is still the strongest selectable model is a hand-checked claim with no
|
|
69
69
|
automated gate — see SKILL.md.) `CODEX_PROBE=1` relaxes this for a throwaway, effort-independent probe only (echoed loudly), and
|
|
70
70
|
a probe still runs on the subscription, in the sandbox, with clean capture.
|
|
@@ -164,7 +164,7 @@ EVIDENCE posture as a fresh run — `-o` for the final message, `--json` into th
|
|
|
164
164
|
|
|
165
165
|
A backgrounded/hung run survives otherwise, so both wrappers wrap codex in `timeout`/`gtimeout`
|
|
166
166
|
(`--kill-after=15s`): `CODEX_HARD_TIMEOUT` defaults to **3600s (exec)** / **1800s (review)**, sized for a
|
|
167
|
-
slow
|
|
167
|
+
slow run at the pinned effort. Exit 124/137 ⇒ "exceeded the hard cap" (raise the cap or narrow the task). If neither
|
|
168
168
|
`timeout` nor `gtimeout` is on `PATH`, `codex-exec` **warns loudly and runs uncapped** — never a silent
|
|
169
169
|
no-op — while `codex-review` **refuses pre-spend** (the fail-closed hard-timeout preflight).
|
|
170
170
|
|
|
@@ -205,8 +205,8 @@ exec` over the precomputed diff instead, keeping every invariant intact.
|
|
|
205
205
|
| `-o, --output-last-message <f>` | write ONLY the final message (clean capture) |
|
|
206
206
|
| `--json` | structured event stream (`thread.started` ⇒ session id) |
|
|
207
207
|
| `--output-schema <f>` | constrain output to a JSON schema (`CODEX_REVIEW_SCHEMA=1`) |
|
|
208
|
-
| `-m <model>` | model (wrapper default `gpt-
|
|
209
|
-
| `-c model_reasoning_effort=<effort>` | reasoning effort (wrapper default `
|
|
208
|
+
| `-m <model>` | model (wrapper default `gpt-6-astra`, pinned via `CODEX_MODEL`) |
|
|
209
|
+
| `-c model_reasoning_effort=<effort>` | reasoning effort (wrapper default `high`, pinned via `CODEX_EFFORT`) |
|
|
210
210
|
| `--ignore-user-config` | do NOT load `$CODEX_HOME/config.toml`; auth still uses `CODEX_HOME` |
|
|
211
211
|
| `--color never` | disable ANSI colour in output |
|
|
212
212
|
|