@sabaiway/agent-workflow-kit 14.19.1 → 14.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -1
  3. package/SKILL.md +1 -1
  4. package/bridges/antigravity-cli-bridge/SKILL.md +45 -50
  5. package/bridges/antigravity-cli-bridge/bin/agy-model-posture.test.mjs +257 -0
  6. package/bridges/antigravity-cli-bridge/bin/agy-review-harness.test.mjs +10 -3
  7. package/bridges/antigravity-cli-bridge/bin/agy-review-honesty.test.mjs +20 -21
  8. package/bridges/antigravity-cli-bridge/bin/agy-review-model-screen.test.mjs +4 -4
  9. package/bridges/antigravity-cli-bridge/bin/agy-review.sh +120 -48
  10. package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +22 -62
  11. package/bridges/antigravity-cli-bridge/bin/agy.sh +109 -16
  12. package/bridges/antigravity-cli-bridge/bin/agy.test.mjs +5 -5
  13. package/bridges/antigravity-cli-bridge/capability.json +14 -7
  14. package/bridges/antigravity-cli-bridge/references/driving-agy.md +16 -20
  15. package/bridges/antigravity-cli-bridge/references/models-and-flags.md +10 -27
  16. package/bridges/codex-cli-bridge/SKILL.md +57 -49
  17. package/bridges/codex-cli-bridge/bin/codex-exec.sh +145 -46
  18. package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +28 -55
  19. package/bridges/codex-cli-bridge/bin/codex-model-posture.test.mjs +371 -0
  20. package/bridges/codex-cli-bridge/bin/codex-review.sh +134 -36
  21. package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +33 -45
  22. package/bridges/codex-cli-bridge/capability.json +22 -8
  23. package/bridges/codex-cli-bridge/references/driving-codex.md +18 -15
  24. package/bridges/codex-cli-bridge/references/sandbox-and-flags.md +16 -12
  25. package/bridges/codex-cli-bridge/setup/README.md +3 -3
  26. package/capability.json +1 -1
  27. package/package.json +1 -1
  28. package/references/modes/bridge-settings.md +10 -7
  29. package/references/modes/jev.md +3 -2
  30. package/references/modes/recipes.md +1 -1
  31. package/references/modes/recommendations.md +2 -1
  32. package/references/modes/review-state.md +1 -1
  33. package/references/vendor/typesafe-ai/LICENSE +21 -0
  34. package/references/vendor/typesafe-ai/SKILL.md.pinned +149 -0
  35. package/tools/ack-store.mjs +2 -0
  36. package/tools/bridge-catalog.mjs +114 -0
  37. package/tools/bridge-posture.mjs +11 -2
  38. package/tools/bridge-settings-read.mjs +41 -5
  39. package/tools/bridge-settings.mjs +111 -23
  40. package/tools/detect-backends.mjs +6 -6
  41. package/tools/family-registry.mjs +3 -3
  42. package/tools/jev-facts.mjs +101 -4
  43. package/tools/jev-guide.mjs +31 -12
  44. package/tools/jev-skill.mjs +231 -0
  45. package/tools/manifest/schema.md +1 -1
  46. package/tools/manifest/validate.mjs +3 -2
  47. package/tools/procedures.mjs +3 -3
  48. package/tools/recipes.mjs +2 -2
  49. package/tools/recommendations.mjs +49 -4
  50. package/tools/review-state.mjs +1 -1
@@ -17,23 +17,22 @@
17
17
  # policy (no plan contract, no auto-approve, no workspace edits) — that is left
18
18
  # to whatever flow we design later, which can opt in via passthrough flags.
19
19
  #
20
- # Model families (compact inventory only; run `agy models` for exact display strings, then pass
21
- # one via AGY_MODEL):
22
- # Gemini 3.8 Flash (Low|Medium|High), Gemini 3.7 Flash (Low|Medium|High),
23
- # Gemini 3.6 Flash (Low|Medium|High), Gemini 3.5 Flash (Low|Medium|High), Gemini 3.1 Pro (Low|High),
24
- # Claude Sonnet 4.6 (Thinking), Claude Opus 4.6 (Thinking), GPT-OSS 120B (Medium)
20
+ # Model: the host posture — AGY_MODEL in the bridge settings file, else the built-in default
21
+ # "Gemini 3.8 Flash (High)". `/agent-workflow-kit bridge-settings` shows the models the installed
22
+ # agy offers and sets one.
25
23
  #
26
24
  # Usage (installed on PATH as `agy-run`):
27
25
  # agy-run "your prompt" # prompt as an argument
28
26
  # echo "your prompt" | agy-run - # prompt from stdin
29
27
  # agy-run @path/to/prompt.md # prompt from a file
30
- # AGY_MODEL="Claude Opus 4.6 (Thinking)" agy-run "..." # pick a model
28
+ # AGY_MODEL="<display string>" agy-run "..." # a one-run model (default: the host posture)
31
29
  # AGY_TIMEOUT=10m agy-run "..." # override print timeout (agy's soft bound)
32
30
  # AGY_HARD_TIMEOUT=8m agy-run "..." # override the hard wall-clock cap (timeout(1))
33
31
  # AGY_MAX_PROMPT_BYTES=60000 agy-run @big.md # LOWER the single-argv byte ceiling (default 120000;
34
32
  # # the override only tightens it — it can never exceed the OS ~131072 limit)
35
33
  # agy-run "..." -- --add-dir . # passthrough agy flags (this wrapper stays
36
- # # flow-agnostic; it never widens agy's own permissions)
34
+ # # flow-agnostic; it never widens agy's own permissions;
35
+ # # --model* and --effort* refuse — the model is AGY_MODEL)
37
36
  set -euo pipefail
38
37
 
39
38
  # --- --help / -h (pre-preflight: no agy, no login needed) ----------------------
@@ -56,7 +55,7 @@ Settings file (KEY=VALUE, parsed never sourced; env wins over file, file wins ov
56
55
  ${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf
57
56
  AGY_HARD_TIMEOUT — hard wall-clock cap, duration string like 5m/30m/90s (built-in default = AGY_TIMEOUT, 5m)
58
57
 
59
- Environment: AGY_MODEL (exact display string from `agy models`; empty ⇒ agy's settings.json), AGY_TIMEOUT / AGY_HARD_TIMEOUT (duration strings), AGY_MAX_PROMPT_BYTES (single-argv byte ceiling; the override only lowers it).
58
+ Environment: AGY_MODEL (exact display string from `agy models` — a one-run override of the host posture; empty ⇒ agy's settings.json), AGY_TIMEOUT / AGY_HARD_TIMEOUT (duration strings), AGY_MAX_PROMPT_BYTES (single-argv byte ceiling; the override only lowers it).
60
59
  Requires at run time: the agy CLI on PATH + a Google AI subscription login (--help needs neither).
61
60
  HELP
62
61
  exit 0
@@ -76,6 +75,7 @@ done < <(compgen -v 2>/dev/null | grep '_API_KEY$' || true)
76
75
 
77
76
  # This wrapper's applied settings-file subset (see the shared reader block below).
78
77
  AW_SETTINGS_APPLIED="AGY_HARD_TIMEOUT"
78
+ DEFAULT_AGY_MODEL="Gemini 3.8 Flash (High)"
79
79
 
80
80
  # --- Bridge settings file (host-level, kit-independent) — byte-identical across the four wrappers ---
81
81
  # ${XDG_CONFIG_HOME:-$HOME/.config}/agent-workflow/bridge-settings.conf holds KEY=VALUE lines,
@@ -96,7 +96,7 @@ aw_settings_file() {
96
96
  printf '%s/agent-workflow/bridge-settings.conf' "${XDG_CONFIG_HOME:-$HOME/.config}"
97
97
  }
98
98
  aw_settings_known() {
99
- case " CODEX_SERVICE_TIER CODEX_HARD_TIMEOUT CODEX_REVIEW_MAX_TOTAL_BYTES AGY_HARD_TIMEOUT AGY_REVIEW_ALLOW_ADDDIR AGY_REVIEW_MAX_TOTAL_BYTES " in
99
+ case " CODEX_SERVICE_TIER CODEX_HARD_TIMEOUT CODEX_REVIEW_MAX_TOTAL_BYTES AGY_HARD_TIMEOUT AGY_REVIEW_ALLOW_ADDDIR AGY_REVIEW_MAX_TOTAL_BYTES CODEX_MODEL CODEX_EFFORT AGY_MODEL " in
100
100
  *" $1 "*) return 0 ;;
101
101
  *) return 1 ;;
102
102
  esac
@@ -181,6 +181,35 @@ aw_apply_settings() {
181
181
  done
182
182
  return 0
183
183
  }
184
+ aw_read_posture() {
185
+ local key="$1" default="$2" empty="$3" file line value notify=1
186
+ AW_HOST_VALUE="$default"
187
+ AW_HOST_SOURCE="default"
188
+ file="$(aw_settings_file)"
189
+ [[ -n "${AW_SETTINGS_NOTIFIED:-}" ]] && notify=0
190
+ if [[ -f "$file" && -r "$file" ]]; then
191
+ line="$(grep "^${key}=" "$file" 2>/dev/null || true)"
192
+ if [[ -n "$line" ]]; then
193
+ value="${line##*$'\n'}"
194
+ value="${value#*=}"
195
+ if [[ -n "$value" && "$value" != *[$'\x01'-$'\x1f'$'\x7f']* ]]; then
196
+ AW_HOST_VALUE="$value"
197
+ AW_HOST_SOURCE="setting"
198
+ elif (( notify )); then
199
+ echo "warning: $key in bridge settings file '$file' is empty or carries a control byte — using the built-in default '$default'." >&2
200
+ fi
201
+ fi
202
+ fi
203
+ AW_RUN_VALUE="$AW_HOST_VALUE"
204
+ AW_RUN_SOURCE="$AW_HOST_SOURCE"
205
+ if [[ -n "${!key+x}" ]]; then
206
+ AW_RUN_VALUE="${!key:-$empty}"
207
+ AW_RUN_SOURCE="environment"
208
+ fi
209
+ return 0
210
+ }
211
+ aw_read_posture AGY_MODEL "$DEFAULT_AGY_MODEL" ""
212
+ AGY_MODEL="$AW_RUN_VALUE"; AGY_MODEL_SOURCE="$AW_RUN_SOURCE"
184
213
  aw_apply_settings
185
214
 
186
215
  # --- Effective-timeout resolver (D5 banner honesty; AD-061) --------------------
@@ -239,9 +268,6 @@ if ! command -v agy >/dev/null 2>&1; then
239
268
  exit 127
240
269
  fi
241
270
 
242
- # `-` (empty) => skip --model and let agy use settings.json; default to Flash (High) — asserted
243
- # frontier-grade (fork (a), maintainer 2026-08-14; the 3.8 pin AD-136, 2026-09-09).
244
- AGY_MODEL="${AGY_MODEL-Gemini 3.8 Flash (High)}"
245
271
  AGY_TIMEOUT="${AGY_TIMEOUT:-5m}"
246
272
  AGY_TIMEOUT="$(aw_effective_timeout AGY_TIMEOUT 5m)"
247
273
  # Hard wall-clock cap (defaults to AGY_TIMEOUT). agy's own --print-timeout is NOT a reliable
@@ -271,6 +297,13 @@ if [[ $# -gt 0 ]]; then
271
297
  exit 2
272
298
  fi
273
299
  fi
300
+ for _arg in ${passthrough[@]+"${passthrough[@]}"}; do
301
+ case "$_arg" in
302
+ --model*|--effort*)
303
+ echo "error: passthrough flag '$_arg' is not allowed — the model is the host posture (AGY_MODEL in $(aw_settings_file)) or the AGY_MODEL environment value for one run, never a flag." >&2
304
+ exit 2 ;;
305
+ esac
306
+ done
274
307
 
275
308
  if [[ "$prompt_src" == "-" ]]; then
276
309
  prompt="$(cat)"
@@ -321,6 +354,67 @@ if (( prompt_bytes > AGY_MAX_PROMPT_BYTES )); then
321
354
  exit 2
322
355
  fi
323
356
 
357
+ # The effective model against the installed CLI's catalog, pre-spend — skipped when agy-review read
358
+ # it once for the whole run (its marker), and when AGY_MODEL is explicitly empty (no model string).
359
+ timeout_bin="$(aw_resolve_timeout_bin)"
360
+ AGY_CATALOG_TIMEOUT=30s
361
+ aw_agy_remedy() {
362
+ if [[ -z "$1" ]]; then
363
+ echo " remedy: unset AGY_MODEL in the environment (the host posture then decides)." >&2
364
+ return 0
365
+ fi
366
+ echo " remedy: set this line in $(aw_settings_file):" >&2
367
+ echo " AGY_MODEL=$1" >&2
368
+ echo " and unset AGY_MODEL in the environment." >&2
369
+ }
370
+ aw_agy_shown_model() {
371
+ if [[ -z "$AGY_MODEL" ]]; then printf '%s' "AGY_MODEL= (explicitly empty)"; return 0; fi
372
+ if [[ "$AGY_MODEL" == *[$'\x01'-$'\x1f'$'\x7f']* ]]; then printf '%s' "AGY_MODEL (a value carrying a control byte)"; return 0; fi
373
+ printf '%s' "AGY_MODEL='$AGY_MODEL'"
374
+ }
375
+ aw_agy_catalog_check() {
376
+ local raw="" rc=0 line="" remedy="" reason="" offered=()
377
+ if [[ -n "$1" ]]; then
378
+ raw="$("$1" --kill-after=5s "$AGY_CATALOG_TIMEOUT" agy models </dev/null 2>/dev/null)" || rc=$?
379
+ else
380
+ raw="$(agy models </dev/null 2>/dev/null)" || rc=$?
381
+ fi
382
+ if (( rc == 0 )); then
383
+ while IFS= read -r line; do
384
+ line="${line%$'\r'}"
385
+ [[ "$line" == *$'\t'* ]] || continue
386
+ line="${line#*$'\t'}"
387
+ if [[ -n "$line" && "$line" != *[$'\x01'-$'\x1f'$'\x7f']* ]]; then offered+=("$line"); fi
388
+ done <<<"$raw"
389
+ fi
390
+ if (( rc == 124 || rc == 137 )); then
391
+ reason="it exceeded $AGY_CATALOG_TIMEOUT"
392
+ elif (( rc != 0 )); then
393
+ reason="agy models exited $rc"
394
+ elif (( ${#offered[@]} == 0 )); then
395
+ reason="it offers no model"
396
+ fi
397
+ if [[ -n "$reason" ]]; then
398
+ echo "warning: the agy model catalog is unreadable ($reason) — the run proceeds unchecked; agy itself refuses a model it does not serve." >&2
399
+ return 0
400
+ fi
401
+ for line in "${offered[@]}"; do
402
+ if [[ "$line" == "$AGY_MODEL" ]]; then return 0; fi
403
+ done
404
+ remedy="${offered[0]}"
405
+ for line in "${offered[@]}"; do
406
+ if [[ "$line" == "$2" ]]; then remedy="$line"; fi
407
+ done
408
+ echo "error: $(aw_agy_shown_model) ($AGY_MODEL_SOURCE) is not a model the installed agy offers — refusing before any run is spent." >&2
409
+ printf -v line '%s, ' "${offered[@]}"
410
+ echo " offered: ${line%, }" >&2
411
+ aw_agy_remedy "$remedy"
412
+ exit 2
413
+ }
414
+ if [[ -n "$AGY_MODEL" && -z "${AW_AGY_CATALOG_READ:-}" ]]; then
415
+ aw_agy_catalog_check "$timeout_bin" "$DEFAULT_AGY_MODEL"
416
+ fi
417
+
324
418
  model_flag=()
325
419
  if [[ -n "$AGY_MODEL" ]]; then
326
420
  model_flag=(--model "$AGY_MODEL")
@@ -332,7 +426,6 @@ agy_cmd=(agy "${model_flag[@]}" --print-timeout "$AGY_TIMEOUT" "${passthrough[@]
332
426
  # This is the real guard — a backgrounded, hung agy survives its own --print-timeout otherwise.
333
427
  # aw_resolve_timeout_bin: builtin type -P (an exported function can shadow neither `timeout` nor
334
428
  # `type` itself), normalized to an ABSOLUTE path fail-closed — nothing can masquerade as the cap.
335
- timeout_bin="$(aw_resolve_timeout_bin)"
336
429
 
337
430
  if [[ -z "$timeout_bin" ]]; then
338
431
  # The review child seam (flow-orchestration Phase 4): agy-review fails CLOSED at its own
@@ -357,8 +450,8 @@ rc=$?
357
450
  set -e
358
451
  if [[ $rc -eq 124 || $rc -eq 137 ]]; then
359
452
  echo "error: agy exceeded the hard cap AGY_HARD_TIMEOUT=$AGY_HARD_TIMEOUT and was terminated." >&2
360
- echo " This usually means a heavy '--add-dir' agentic run, or the slowest model looping." >&2
361
- echo " Retry with a faster model (e.g. AGY_MODEL='Gemini 3.7 Flash (Low)') or a" >&2
362
- echo " self-contained prompt without --add-dir. Raise AGY_HARD_TIMEOUT only if the run is healthy." >&2
453
+ echo " This usually means a heavy '--add-dir' agentic run, or a run looping." >&2
454
+ echo " Retry with a narrower, self-contained prompt without --add-dir. Raise AGY_HARD_TIMEOUT" >&2
455
+ echo " only if the run is healthy." >&2
363
456
  fi
364
457
  exit $rc
@@ -52,7 +52,7 @@ describe('agy.sh — hard wall-clock cap (timeout(1))', { concurrency: true }, (
52
52
  rmSync(home, { recursive: true, force: true });
53
53
  assert.ok(elapsed < 13000, `wrapper must return well under the kill-after window, took ${elapsed}ms`);
54
54
  assert.notEqual(r.status, 0, 'a timed-out run must exit non-zero');
55
- assert.match(r.stderr, /exceeded the hard cap/, 'must explain the hard-cap kill');
55
+ assert.ok(/exceeded the hard cap/.test(r.stderr) && !/faster model/i.test(r.stderr), `must explain the hard-cap kill and never send the run to a faster model: ${r.stderr}`);
56
56
  });
57
57
 
58
58
  it('passes a fast agy run through unchanged (exit 0, stdout preserved)', async () => {
@@ -511,7 +511,7 @@ describe('agy.sh — settings surface ⟷ manifest (D6, manifest-pinned)', () =>
511
511
  it('--help Settings section keys set-EQUAL the manifest appliesTo subset', () => {
512
512
  const section = helpSection(runHelpText(), SETTINGS_HEADER);
513
513
  const got = section.filter((l) => /^[A-Z][A-Z0-9_]+ —/.test(l)).map((l) => l.split(' ')[0]);
514
- const want = (MANIFEST.settings ?? []).filter((s) => s.appliesTo.includes(SETTINGS_CMD)).map((s) => s.key);
514
+ const want = (MANIFEST.settings ?? []).filter((s) => s.kind !== 'posture' && s.appliesTo.includes(SETTINGS_CMD)).map((s) => s.key);
515
515
  assert.ok(want.length > 0, 'the manifest must declare settings for this wrapper');
516
516
  setEq(got, want, 'help Settings keys ⟷ manifest settings.appliesTo');
517
517
  assert.ok(section.some((l) => l.includes('agent-workflow/bridge-settings.conf')), 'the section names the settings file');
@@ -529,7 +529,7 @@ describe('agy.sh — settings surface ⟷ manifest (D6, manifest-pinned)', () =>
529
529
  it('AW_SETTINGS_APPLIED equals the manifest appliesTo subset for this wrapper', () => {
530
530
  const m = source.match(/^AW_SETTINGS_APPLIED="([^"]*)"$/m);
531
531
  assert.ok(m, 'AW_SETTINGS_APPLIED not found');
532
- const want = ALL_SETTINGS.filter((s) => s.appliesTo.includes(SETTINGS_CMD)).map((s) => s.key);
532
+ const want = ALL_SETTINGS.filter((s) => s.kind !== 'posture' && s.appliesTo.includes(SETTINGS_CMD)).map((s) => s.key);
533
533
  assert.ok(want.length > 0);
534
534
  setEq(m[1].trim().split(/\s+/), want, 'applied subset ⟷ manifest appliesTo');
535
535
  });
@@ -538,8 +538,8 @@ describe('agy.sh — settings surface ⟷ manifest (D6, manifest-pinned)', () =>
538
538
  const body = source.match(/aw_settings_valid\(\) \{[\s\S]*?\n\}/);
539
539
  assert.ok(body, 'aw_settings_valid not found');
540
540
  const armKeys = [...body[0].matchAll(/^ ([A-Z][A-Z0-9_]*)\)/gm)].map((x) => x[1]);
541
- setEq(armKeys, ALL_SETTINGS.map((s) => s.key), 'validation arms ⟷ manifest keys');
542
- for (const s of ALL_SETTINGS) {
541
+ setEq(armKeys, ALL_SETTINGS.filter((s) => s.kind !== 'posture').map((s) => s.key), 'validation arms ⟷ manifest keys (a posture key is read by aw_read_posture, never validated here)');
542
+ for (const s of ALL_SETTINGS.filter((x) => x.kind !== 'posture')) {
543
543
  const arm = body[0].match(new RegExp(`^ ${s.key}\\) (.*) ;;$`, 'm'));
544
544
  assert.ok(arm, `no validation arm for ${s.key}`);
545
545
  if (s.kind === 'enum') for (const v of s.values) assert.ok(arm[1].includes(`"${v}"`), `${s.key}: enum value '${v}' not pinned`);
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "antigravity-cli-bridge",
5
5
  "kind": "execution-backend",
6
- "version": "5.7.0",
6
+ "version": "6.0.0",
7
7
  "provides": ["review", "probe"],
8
8
  "posture": { "model": "Gemini 3.8 Flash (High)" },
9
9
  "roles": {
@@ -31,11 +31,11 @@
31
31
  "agy-review --continue [--decided @f] [--focus \"…\"] [--nonce <n>]",
32
32
  "agy-review --conversation <id> [--decided @f] [--focus \"…\"] [--nonce <n>]"
33
33
  ],
34
- "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; durationS = integer wall-clock seconds from CLI start through verdict parsing and the wrapper prints review duration: <n>s; blocking = the count of numbered items in the first ### Blocking section; artifactPath = the normalized realpath on plan/diff receipts only (repo-relative inside the work tree, absolute otherwise), while a double quote, backslash or control byte refuses pre-spend because the receipt encoder cannot carry it; 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; delivery = how the change set REACHED the model, currently emitted as 'inline' (the whole set rode one prompt — proven by construction) or 'fed' (a chunked feed whose per-part echo proof verified); REQUIRED on every agy code receipt and its ABSENCE is what stops a pre-fed-lane receipt attesting, while the gate accepts any well-formed declaration rather than a particular value; absent by construction on plan/diff/continuation receipts, which carry no change set; 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); when the dispatch nonce seam is supplied — the AW_REVIEW_NONCE environment value or its plain-argument equivalent --nonce <n> (one seam: the flag assigns the same value; supplying both with different values refuses pre-spend) — under the safe grammar [A-Za-z0-9._-]{1,64} (anything else refuses pre-spend), the wrapper first mints the finding MANIFEST {schema, backend, nonce, fingerprint, findings} beside the receipts file (agent-workflow-finding-manifest-<backend>-<nonce>.json; atomic, no-clobber — a byte-identical rewrite is an idempotent no-op, different bytes refuse loudly) ORDERED before the receipt append — a failed manifest write EXCLUDES the receipt append, so a nonce-supplied dispatch can never land a receipt without its readable manifest; a nonce-less invocation adds NO nonce field and mints NO finding manifest (the existing wrapperVersion field still changes with each bridge release); a write failure warns, never fails the review",
34
+ "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; durationS = integer wall-clock seconds from CLI start through verdict parsing and the wrapper prints review duration: <n>s; blocking = the count of numbered items in the first ### Blocking section; artifactPath = the normalized realpath on plan/diff receipts only (repo-relative inside the work tree, absolute otherwise), while a double quote, backslash or control byte refuses pre-spend because the receipt encoder cannot carry it; 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, a one-off model (an explicitly empty AGY_MODEL included) refuses pre-spend unless AGY_PROBE=1, and a model string carrying control bytes refuses pre-spend in every mode; delivery = how the change set REACHED the model, currently emitted as 'inline' (the whole set rode one prompt — proven by construction) or 'fed' (a chunked feed whose per-part echo proof verified); REQUIRED on every agy code receipt and its ABSENCE is what stops a pre-fed-lane receipt attesting, while the gate accepts any well-formed declaration rather than a particular value; absent by construction on plan/diff/continuation receipts, which carry no change set; 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); when the dispatch nonce seam is supplied — the AW_REVIEW_NONCE environment value or its plain-argument equivalent --nonce <n> (one seam: the flag assigns the same value; supplying both with different values refuses pre-spend) — under the safe grammar [A-Za-z0-9._-]{1,64} (anything else refuses pre-spend), the wrapper first mints the finding MANIFEST {schema, backend, nonce, fingerprint, findings} beside the receipts file (agent-workflow-finding-manifest-<backend>-<nonce>.json; atomic, no-clobber — a byte-identical rewrite is an idempotent no-op, different bytes refuse loudly) ORDERED before the receipt append — a failed manifest write EXCLUDES the receipt append, so a nonce-supplied dispatch can never land a receipt without its readable manifest; a nonce-less invocation adds NO nonce field and mints NO finding manifest (the existing wrapperVersion field still changes with each bridge release); a write failure warns, never fails the review",
35
35
  "notes": [
36
36
  "transport: every review dispatch drives the CLI in --output-format json (plus --disable-slash-commands) and the returned envelope is parsed in node (bin/agy-envelope.mjs) — the operator-facing invocations and flags above do NOT change, and on a ZERO exit the wrapper still PRINTS the review text, never JSON. A missing or unreadable envelope on a zero exit is a loud failure with NO receipt, never a downgraded verdict and never a fallback to raw-stdout parsing; a non-zero CLI exit keeps its own code and message, and publishes the captured stdout unchanged from the SINGLE dispatch or the FINAL fed turn (which may therefore be a JSON or partial payload — the envelope is parsed only on a zero exit); an INTERMEDIATE feed turn is the exception, its output stays private (Invariant E) and its failure prints only a named error. Enforced by a PRE-SPEND capability probe, not a version floor: agy --help must advertise --output-format and --disable-slash-commands, node must be >= 22, and bin/agy-envelope.mjs must be present — otherwise the review refuses before any run is spent and names the missing capability",
37
37
  "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",
38
- "the review posture banner appends a banner-only timeout=<duration> field — exactly the duration agy-run hands to timeout(1); the hard-timeout preflight fails CLOSED when no timeout/gtimeout binary exists (the wrapper refuses by name before any CLI run, so an uncapped review run can no longer happen), and the field never enters the receipt posture or the D5 banner↔receipt parity",
38
+ "the review posture banner appends a banner-only source=model:<s> field — where the model came from: default, setting or environment — then a banner-only timeout=<duration> field — exactly the duration agy-run hands to timeout(1); the hard-timeout preflight fails CLOSED when no timeout/gtimeout binary exists (the wrapper refuses by name before any CLI run, so an uncapped review run can no longer happen), and neither field enters the receipt posture or the D5 banner↔receipt parity",
39
39
  "quote the posture banner verbatim when labeling this dispatch — the banner is the machine-stated posture; a prose re-type drifts"
40
40
  ]
41
41
  }
@@ -177,11 +177,11 @@
177
177
  "descriptor": "agy-run <prompt|-|@file> -- <extra agy flags...>",
178
178
  "operands": [
179
179
  { "slot": "<prompt|-|@file>", "required": true, "description": "the prompt text, - to read it from stdin, or @path to read it from a file" },
180
- { "slot": "<extra agy flags...>", "required": false, "description": "raw agy flags passed straight through after --" }
180
+ { "slot": "<extra agy flags...>", "required": false, "description": "raw agy flags after -- (a --model* or --effort* flag refuses pre-spend: the model is the host posture or the AGY_MODEL environment value)" }
181
181
  ],
182
182
  "guardrails": [
183
183
  { "value": "subscription-only — every *_API_KEY env var is unset before the run", "enforcement": "enforced", "source": "bin/agy.sh" },
184
- { "value": "any model is selectable via AGY_MODEL; the default is Gemini 3.8 Flash (High)", "enforcement": "advisory", "source": "bin/agy.sh" },
184
+ { "value": "the model is the host posture (AGY_MODEL in the bridge settings file, else Gemini 3.8 Flash (High)); AGY_MODEL in the environment sets it for one run", "enforcement": "enforced", "source": "bin/agy.sh" },
185
185
  { "value": "hard wall-clock cap AGY_HARD_TIMEOUT (built-in default 5m)", "enforcement": "enforced", "condition": "only while timeout(1)/gtimeout is on PATH — otherwise the wrapper warns and runs uncapped", "source": "capability.json settings.AGY_HARD_TIMEOUT" },
186
186
  { "value": "the prompt rides a single argv — over AGY_MAX_PROMPT_BYTES (120000) the run refuses", "enforcement": "enforced", "source": "bin/agy.sh" },
187
187
  { "value": "no review posture, no grounding, no receipt — the reply is raw model output", "enforcement": "advisory", "source": "bin/agy.sh" }
@@ -192,10 +192,10 @@
192
192
  "key": "AGY_PROBE",
193
193
  "kind": "env-hook",
194
194
  "parents": ["review.code", "review.plan", "review.diff", "review.continue", "review.conversation"],
195
- "purpose": "Silence the off-frontier model advisory for a THROWAWAY probe review.",
195
+ "purpose": "Run a one-off model for a THROWAWAY probe review — the one route to a one-off.",
196
196
  "whenToUse": [
197
197
  "a probe whose answer cannot depend on the model",
198
- "deliberately reviewing with a cheaper non-frontier model"
198
+ "trying a model other than the host posture before setting it"
199
199
  ],
200
200
  "whenNotTo": ["any run whose output informs what ships — a probe never attests"],
201
201
  "descriptor": "AGY_PROBE=1 agy-review code [--facts @<facts-file>]",
@@ -208,6 +208,13 @@
208
208
  }
209
209
  ],
210
210
  "settings": [
211
+ {
212
+ "key": "AGY_MODEL",
213
+ "kind": "posture",
214
+ "default": "Gemini 3.8 Flash (High)",
215
+ "appliesTo": ["agy-run", "agy-review"],
216
+ "effect": "the agy model every run uses (the host posture), an exact display string; a set value is checked against the installed agy's catalog first. /agent-workflow-kit bridge-settings shows the models offered."
217
+ },
211
218
  {
212
219
  "key": "AGY_HARD_TIMEOUT",
213
220
  "kind": "duration",
@@ -8,7 +8,7 @@ edits, verification, and final judgment.
8
8
  ## Delegation checklist
9
9
 
10
10
  1. Pick the narrowest useful question.
11
- 2. Choose the cheapest model that can answer it.
11
+ 2. Run on the host posture (the user's `AGY_MODEL` setting); only an `agy-run` probe names a one-run model.
12
12
  3. Include only the relevant excerpts, paths, constraints, and the expected output shape.
13
13
  4. State permission boundaries in the prompt (no edits, no git writes).
14
14
  5. Run `agy-run` headlessly.
@@ -16,17 +16,11 @@ edits, verification, and final judgment.
16
16
 
17
17
  ## Model selection
18
18
 
19
- | Task | Model |
20
- |---|---|
21
- | Reachability / smoke / "is it wired?" | `Gemini 3.8 Flash (Low)` |
22
- | Cheap probes, summaries | `Gemini 3.8 Flash (Medium)` |
23
- | Review, reasoning, careful drafting | `Gemini 3.8 Flash (High)` (wrapper default; asserted frontier-grade, AD-136) |
24
- | The previous Flash generation, still frontier-grade for review | `Gemini 3.7 Flash (High)` (fork (a)) |
25
- | Slower, deeper reasoning pass | `Gemini 3.1 Pro (High)` |
26
- | Same Pro reasoning, lower quota cost | `Gemini 3.1 Pro (Low)` |
27
- | A different engine's opinion | `Claude Sonnet 4.6 (Thinking)`, `Claude Opus 4.6 (Thinking)`, or `GPT-OSS 120B (Medium)` |
28
-
29
- The 3.7 / 3.6 / 3.5 Flash families remain served — prefer 3.8 (newest generation at the same tiers).
19
+ Reviews and kept work run on the host posture: `AGY_MODEL` in the bridge settings file, else
20
+ `Gemini 3.8 Flash (High)`; a weaker model is the user's choice in that setting, never a per-call pick.
21
+ **`/agent-workflow-kit bridge-settings`** shows the models the installed `agy` offers and sets that
22
+ setting; an `agy-run` probe may name any offered display string as its one-run model.
23
+
30
24
  Don't reach for Pro by reflex — Flash answers most reachability/probe questions for a fraction of the
31
25
  quota.
32
26
 
@@ -96,13 +90,15 @@ What it does for you, and what YOU must supply:
96
90
  `AGY_REVIEW_ALLOW_ADDDIR` is **RETIRED** (recognized, arms nothing): headless `agy` auto-denies its
97
91
  own `read_file`, so the offload it armed could return a confident fabrication with no way to tell.
98
92
  The kit never grants that permission — the feed exists so none is needed.
99
- - **Model:** frontier default `Gemini 3.8 Flash (High)`; any model is allowed (a sub-frontier one earns a
100
- silenceable `AGY_PROBE=1` advisory). The service can still **stall on large/substantive prompts**
93
+ - **Model:** the host posture (the `AGY_MODEL` setting, else `Gemini 3.8 Flash (High)`), checked once
94
+ per run against `agy models`; an `AGY_MODEL` environment value off it is a one-off, refused pre-spend
95
+ unless `AGY_PROBE=1` (a probe review never attests). The service can still **stall on large/substantive prompts**
101
96
  (Issue-001) — keep reviews **focused**; the hard timeout is the guard.
102
97
  - **Posture banner — quote it verbatim.** Every review states its ACTUAL posture on ONE stderr line
103
- (`review posture: model=… timeout=…`). When you label a dispatch for a user or a record, **quote
104
- the posture banner verbatim** — the banner is the machine-stated posture; a prose re-type drifts.
105
- The `timeout=` field is **banner-only** (exactly the duration `agy-run` hands to `timeout(1)`;
98
+ (`review posture: model=… source=… timeout=…`). When you label a dispatch for a user or a record,
99
+ **quote the posture banner verbatim** — the banner is the machine-stated posture; a prose re-type
100
+ drifts. The `source=` field (`model:<s>`, `default`, `setting` or `environment`) and the `timeout=`
101
+ field are **banner-only** (`timeout=` is exactly the duration `agy-run` hands to `timeout(1)`;
106
102
  without a capping binary `agy-review` fails CLOSED pre-spend, so an uncapped review banner no
107
103
  longer exists) — informational, never part of the receipt posture.
108
104
 
@@ -125,13 +121,13 @@ rewrite history. Return findings and suggested changes only.
125
121
 
126
122
  ## Project-context prompts
127
123
 
128
- Probe **reachability** from a project root (cheap model) — this is the one place `agy` reading its cwd
124
+ Probe **reachability** from a project root (an `agy-run` probe, so a one-run model is fine) — this is the one place `agy` reading its cwd
129
125
  context file is the point of the prompt:
130
126
 
131
127
  ```bash
132
- AGY_MODEL="Gemini 3.7 Flash (Low)" agy-run \
128
+ AGY_MODEL="<an offered display string>" agy-run \
133
129
  "Read the cwd context file and report the dialogue language plus one Hard Constraint."
134
- AGY_MODEL="Gemini 3.7 Flash (Low)" agy-run \
130
+ AGY_MODEL="<an offered display string>" agy-run \
135
131
  "Without using a file pointer, is there a project-specific planning skill in this repo? Name it and cite its path."
136
132
  ```
137
133
 
@@ -46,7 +46,7 @@ Environment:
46
46
 
47
47
  | Var | Default | Effect |
48
48
  |---|---|---|
49
- | `AGY_MODEL` | `Gemini 3.8 Flash (High)` | model display string; set empty (`AGY_MODEL=`) to drop `--model` and let `agy` use `settings.json` |
49
+ | `AGY_MODEL` | the setting, else `Gemini 3.8 Flash (High)` | model display string, checked pre-spend against `agy models`; the environment value is a one-run model (a probe's one-off); set empty (`AGY_MODEL=`) to drop `--model` and let `agy` use `settings.json` |
50
50
  | `AGY_TIMEOUT` | `5m` | value passed to `--print-timeout` |
51
51
  | `AGY_HARD_TIMEOUT` | `= AGY_TIMEOUT` | hard `timeout(1)` wall-clock cap (a duration string) |
52
52
  | `AGY_MAX_PROMPT_BYTES` | `120000` | single-argv byte ceiling. `agy` takes the prompt as ONE `-p` argv; past `MAX_ARG_STRLEN` (~131072) `execve` fails with a cryptic `Argument list too long`. The wrapper measures the resolved `-`/`@file` prompt and fails loud over the ceiling. A huge **literal** `agy-run "<huge>"` fails at the wrapper's own `exec`, so route large prompts via `-`/`@file`. |
@@ -71,8 +71,8 @@ agy-review --continue | --conversation <id> [--decided @f] [--focus "…"] #
71
71
 
72
72
  | Var | Default | Effect |
73
73
  |---|---|---|
74
- | `AGY_MODEL` | `Gemini 3.8 Flash (High)` | frontier default (AD-136, 2026-09-09; 3.7 Flash (High) stays frontier, fork (a)); **any** model is allowed — a sub-frontier one earns a silenceable advisory (quality-first, not a gate) |
75
- | `AGY_PROBE` | `0` | `1` silences the off-frontier model advisory AND lets `code` run without `--facts` (an ungrounded probe never attests — its receipt is probe-marked) |
74
+ | `AGY_MODEL` | the setting, else `Gemini 3.8 Flash (High)` | the host posture is the `AGY_MODEL` line of the bridge settings file; an environment value off it (an explicitly empty one included) is a one-off, refused pre-spend unless `AGY_PROBE=1` |
75
+ | `AGY_PROBE` | `0` | `1` is the one route to a one-off model AND lets `code` run without `--facts` (a probe never attests — its receipt is probe-marked) |
76
76
  | `AGY_REVIEW_MAX_TOTAL_BYTES` | `240000` | the ceiling on the SUM of all outgoing prompt bytes an oversized `code` review's chunked feed may send; checked BEFORE the first turn is spent |
77
77
  | `AGY_REVIEW_ALLOW_ADDDIR` | `0` | **RETIRED** — recognized so an existing settings line never warns as unknown, but it arms nothing. An oversized `code` review is a chunked feed with a per-part delivery proof; the `--add-dir` offload it armed could not be verified (headless `agy` auto-denies `read_file`) |
78
78
  | `AGY_HARD_TIMEOUT` | `30m` | the review's hard cap (longer default than a probe — reviews are slower) |
@@ -93,33 +93,16 @@ as "capability present".
93
93
 
94
94
  ## Models
95
95
 
96
- Pass the **exact display string** from `agy models`, or set `AGY_MODEL`.
97
-
98
- | Model string | Practical use |
99
- |---|---|
100
- | `Gemini 3.8 Flash (Low)` | lowest-cost smoke tests, cheap probes, simple rewrites (newest Flash) |
101
- | `Gemini 3.8 Flash (Medium)` | fast summaries, context-reachability checks |
102
- | `Gemini 3.8 Flash (High)` | wrapper + review default — asserted frontier-grade (AD-136) |
103
- | `Gemini 3.7 Flash (Low)` | previous Flash generation, still served — prefer 3.8 |
104
- | `Gemini 3.7 Flash (Medium)` | previous Flash generation, still served — prefer 3.8 |
105
- | `Gemini 3.7 Flash (High)` | previous Flash generation, still frontier-grade for review (fork (a)) |
106
- | `Gemini 3.6 Flash (Low)` | older Flash generation, still served — prefer 3.8 |
107
- | `Gemini 3.6 Flash (Medium)` | older Flash generation, still served — prefer 3.8 |
108
- | `Gemini 3.6 Flash (High)` | older Flash generation, still served — prefer 3.8 |
109
- | `Gemini 3.5 Flash (Low)` | older Flash generation, still served — prefer 3.8 |
110
- | `Gemini 3.5 Flash (Medium)` | older Flash generation, still served — prefer 3.8 |
111
- | `Gemini 3.5 Flash (High)` | older Flash generation, still served — prefer 3.8 |
112
- | `Gemini 3.1 Pro (Low)` | cheaper Pro pass for medium reasoning |
113
- | `Gemini 3.1 Pro (High)` | hard reasoning, plan critique, architecture review (slower, deeper) |
114
- | `Claude Sonnet 4.6 (Thinking)` | cross-vendor reasoning comparison |
115
- | `Claude Opus 4.6 (Thinking)` | expensive deep critique when the user wants another high-end pass |
116
- | `GPT-OSS 120B (Medium)` | open-weights-style comparison / diversity pass |
96
+ Set the **exact display string** from `agy models` as `AGY_MODEL` — in the bridge settings file for
97
+ the host posture, or in the environment for one run (`--model` after `--` is refused). The built-in
98
+ default is `Gemini 3.8 Flash (High)`. **`/agent-workflow-kit bridge-settings`** shows the models the
99
+ installed `agy` offers, in its own order, and sets the host posture after checking it against that list.
117
100
 
118
101
  Examples:
119
102
 
120
103
  ```bash
121
- AGY_MODEL="Gemini 3.7 Flash (Low)" agy-run "Read AGENTS.md and report one Hard Constraint."
122
- AGY_MODEL="Claude Sonnet 4.6 (Thinking)" AGY_TIMEOUT=10m agy-run @review-prompt.md
104
+ agy-run "Read AGENTS.md and report one Hard Constraint." # the host posture
105
+ AGY_MODEL="<an offered display string>" AGY_TIMEOUT=10m agy-run @review-prompt.md # a one-run model
123
106
  ```
124
107
 
125
108
  ## Flags (from `agy --help`, v1.1.13)
@@ -128,7 +111,7 @@ AGY_MODEL="Claude Sonnet 4.6 (Thinking)" AGY_TIMEOUT=10m agy-run @review-prompt.
128
111
  |---|---|---|
129
112
  | `-p`, `--print`, `--prompt` | run one headless prompt and print the text response | the wrapper uses `-p` |
130
113
  | `--print-timeout <dur>` | cap headless wait time | CLI default `5m0s`; wrapper default `5m` via `AGY_TIMEOUT` |
131
- | `--model <string>` | select a model | must match an `agy models` display string exactly |
114
+ | `--model <string>` | select a model | must match an `agy models` display string exactly; the wrappers set it from `AGY_MODEL` and refuse it after `--` |
132
115
  | `-i`, `--prompt-interactive` | run an initial prompt, then continue interactively | not used by the wrapper |
133
116
  | `-c`, `--continue` | continue the most recent conversation | pass after the wrapper's `--` |
134
117
  | `--conversation <id>` | resume a specific conversation by id | use only when the user provides/records the id |