@sabaiway/agent-workflow-kit 1.49.0 → 2.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 +100 -0
- package/SKILL.md +1 -1
- package/bridges/antigravity-cli-bridge/SKILL.md +17 -4
- package/bridges/antigravity-cli-bridge/bin/agy-review.sh +73 -17
- package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +271 -13
- package/bridges/antigravity-cli-bridge/bin/agy.test.mjs +76 -0
- package/bridges/antigravity-cli-bridge/capability.json +166 -5
- package/bridges/antigravity-cli-bridge/references/driving-agy.md +6 -2
- package/bridges/antigravity-cli-bridge/references/models-and-flags.md +3 -2
- package/bridges/antigravity-cli-bridge/references/review-prompt.md +1 -1
- package/bridges/codex-cli-bridge/SKILL.md +8 -1
- package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +133 -0
- package/bridges/codex-cli-bridge/bin/codex-review.sh +22 -9
- package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +165 -2
- package/bridges/codex-cli-bridge/capability.json +118 -2
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/modes/review-ledger.md +1 -1
- package/references/modes/review-state.md +2 -2
- package/tools/detect-backends.mjs +6 -5
- package/tools/manifest/schema.md +62 -0
- package/tools/manifest/validate.mjs +327 -0
- package/tools/review-ledger-core.mjs +74 -0
- package/tools/review-ledger-write.mjs +19 -10
- package/tools/review-ledger.mjs +21 -12
- package/tools/review-state.mjs +89 -28
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,106 @@ 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
|
+
## 2.1.0 — agy code review fails CLOSED pre-spend: grounded facts required, `--ungrounded` is the explicit escape (AD-058)
|
|
8
|
+
|
|
9
|
+
> ### ⚠ the bundled antigravity bridge takes MAJOR 3.0.0 — bare `agy-review code` now refuses
|
|
10
|
+
>
|
|
11
|
+
> `agy-review code` without a NON-EMPTY `--facts` payload exits 2 **before spending a run**
|
|
12
|
+
> (previously: a loud warning, then a spent subscription run whose `grounded:false` receipt the
|
|
13
|
+
> review-state gate rejects — a guaranteed-wasted spend). Scripts calling bare `agy-review code`
|
|
14
|
+
> must add `--facts @f` (grounded) or `--ungrounded` (explicit throwaway opinion; the receipt still
|
|
15
|
+
> records `grounded:false` and never attests). `plan`/`diff` modes and continuations are unchanged.
|
|
16
|
+
> The kit itself is a MINOR carrier — the incompatibility is created, and declared, by the bridge.
|
|
17
|
+
|
|
18
|
+
A **fail-closed** release (kit MINOR carrying antigravity-cli-bridge **3.0.0** MAJOR in-tarball;
|
|
19
|
+
codex-cli-bridge 2.8.0 / engine 1.17.0 / memory 2.3.0 unchanged; the deployment-lineage head stays
|
|
20
|
+
`2.0.0`). One theme: **a run that cannot produce a usable result refuses before the money is spent.**
|
|
21
|
+
|
|
22
|
+
- **The refusal prints the recovery:** the exact `grounding.mjs` invocation — resolved from the
|
|
23
|
+
wrapper's own location across the three real install layouts (monorepo canon / deployed skills
|
|
24
|
+
sibling / kit-bundled mirror), quoted so an install path with spaces still yields a runnable
|
|
25
|
+
command — plus the `agy-review code --facts @<file>` re-run line.
|
|
26
|
+
- **Escapes, both honest:** `--ungrounded` (code-mode only, contradicts `--facts`, refused on a
|
|
27
|
+
continuation) and `AGY_PROBE=1` (a probe may now run ungrounded — a probe receipt never attests
|
|
28
|
+
either way; its `modeCatalog` descriptor now marks the facts file optional).
|
|
29
|
+
- **Every declaration home moves in lockstep** (drift-guarded both directions): `--help` ⟷
|
|
30
|
+
`capability.json` (`roles.review.contract` + `modeCatalog` `review.code` operands/guardrails +
|
|
31
|
+
the `AGY_PROBE` env-hook) ⟷ the kit registry mirror (`tools/detect-backends.mjs`) ⟷ `SKILL.md` ⟷
|
|
32
|
+
`references/driving-agy.md` / `models-and-flags.md` / `review-prompt.md`.
|
|
33
|
+
- **Receipt contract scoped honestly:** in `code` mode an absent/empty facts payload now means NO
|
|
34
|
+
run and NO receipt; the `grounded:false`-on-empty clause applies to `plan`/`diff` only.
|
|
35
|
+
|
|
36
|
+
## 2.0.0 — Bridge mode catalog (manifest-as-source) + a review receipt that SELF-DECLARES (AD-057)
|
|
37
|
+
|
|
38
|
+
> ### ⚠ BREAKING — a review receipt written before this release no longer attests a tree
|
|
39
|
+
>
|
|
40
|
+
> The kit now **rejects an unmarked receipt**: a receipt must self-declare whether it came from a
|
|
41
|
+
> probe run, and silence is not a declaration. Every receipt on disk from kit ≤ 1.49.0 / bridges
|
|
42
|
+
> ≤ 2.7.1 / ≤ 2.6.1 predates the marker, so `review-state --check` and `review-ledger --check` will
|
|
43
|
+
> RED on it where they previously passed.
|
|
44
|
+
>
|
|
45
|
+
> **How to upgrade:** `npx @sabaiway/agent-workflow-kit@latest init`, which also ATTEMPTS to refresh
|
|
46
|
+
> the placed bridges — then read its per-bridge outcome. **`skipped-readonly` or `could not refresh`
|
|
47
|
+
> means a compatible writer is not guaranteed:** the new reader may still be paired with an old bridge
|
|
48
|
+
> writer, whose reviews write unmarked receipts this gate now rejects. Re-run the refresh from a
|
|
49
|
+
> writable environment (using the recovery command if one was printed), then **re-run the review** on
|
|
50
|
+
> the tree you are working on. That is the whole migration; no project file changes, and the
|
|
51
|
+
> deployment-lineage stamp is untouched.
|
|
52
|
+
>
|
|
53
|
+
> **Why it is not opt-in.** The pre-marker wrappers already honoured `CODEX_PROBE` / `AGY_PROBE` and
|
|
54
|
+
> wrote no marker, so an unmarked receipt is **indistinguishable from a probe receipt** — a review
|
|
55
|
+
> that ran with the frontier-model/max-effort guard switched off. Any transitional window that keeps
|
|
56
|
+
> accepting unmarked receipts keeps the hole fully open for exactly the receipts it targets: it would
|
|
57
|
+
> not defer the break, it would cancel the fix.
|
|
58
|
+
|
|
59
|
+
A **breaking + feature** release (kit MAJOR carrying codex-cli-bridge **2.8.0** + antigravity-cli-bridge
|
|
60
|
+
**2.7.0** MINOR in-tarball — the bridges only ADD a field to the receipt they write, which is additive;
|
|
61
|
+
the incompatibility is created by the kit READER that now refuses the old form. engine 1.17.0 / memory
|
|
62
|
+
2.3.0 unchanged; the deployment-lineage head is a separate axis and stays `2.0.0`). Two independent
|
|
63
|
+
contracts, one theme: **what a bridge offers, and what a receipt claims, must both be readable off the
|
|
64
|
+
artifact itself — never inferred from source or from silence.**
|
|
65
|
+
|
|
66
|
+
- **`modeCatalog` — a machine-readable answer to "what modes does this bridge offer, and why?"** A new
|
|
67
|
+
**top-level, additive-optional** manifest block (schema stays 1), typed-validated exactly like
|
|
68
|
+
`settings`: absent → valid (a bridge predating it keeps validating), present-but-malformed → invalid.
|
|
69
|
+
Both bridges now declare their real mode set — codex `{exec, exec.resume-last, exec.resume,
|
|
70
|
+
review.plan, review.code, CODEX_PROBE}`, agy `{review.code/plan/diff, review.continue,
|
|
71
|
+
review.conversation, run, AGY_PROBE}` — each entry carrying a closed taxonomy (`primary` /
|
|
72
|
+
`continuation` / `env-hook`, where an env-hook names `parents[]` rather than faking a role), a
|
|
73
|
+
required one-line `purpose` + `whenToUse`, and — declared only where they apply — `whenNotTo`, typed
|
|
74
|
+
`operands[]`, structured `guardrails` `{value, enforcement, condition?, source}` and `customHooks[]`
|
|
75
|
+
(`exec.resume` carries no `guardrails`; a mode with no operands omits `operands`). Invocation forms compose **by
|
|
76
|
+
reference** (`invocationRefs[]`) into the existing AD-033 driving contract — the catalog is the
|
|
77
|
+
user-facing DISCOVERY layer and never shadows it.
|
|
78
|
+
- **Descriptor honesty is enforced, not promised.** Declared operand slots must set-EQUAL the
|
|
79
|
+
placeholders the referenced forms really carry, in **both** directions over the deduplicated union of
|
|
80
|
+
an entry's forms: an undeclared placeholder is as dishonest as an invented slot, since either way the
|
|
81
|
+
render shows a form as ready-to-run that the reader cannot actually fill. `enforced` is claimable only
|
|
82
|
+
for an OS- or code-enforced fact; a runtime bound rides in `condition`; anything a prompt merely asks
|
|
83
|
+
for renders `advisory`. Catalog `submode` values are drift-guarded against the wrappers' real parser
|
|
84
|
+
arms, and every declared env-hook must be a real EXECUTABLE condition (heredocs and comments excluded,
|
|
85
|
+
so a name-grep cannot stay green after the logic is deleted).
|
|
86
|
+
- **A probe review can no longer attest a tree — and the receipt says so itself.** Both wrappers wrote
|
|
87
|
+
receipts unconditionally, so a `CODEX_PROBE=1` / `AGY_PROBE=1` review — which runs with the
|
|
88
|
+
frontier-model/max-effort guard **off** — minted a `fresh:true`/`grounded:true` receipt the
|
|
89
|
+
review-state gate accepted. Both wrappers now write `probe` on **every** successful review, `true` or
|
|
90
|
+
`false`, through the shared byte-identical `write_review_receipt` block: a receipt self-declares and
|
|
91
|
+
nothing has to infer it. The kit rejects a probe-marked receipt (a probe never attests) and **equally
|
|
92
|
+
rejects an unmarked one — silence is not a declaration**.
|
|
93
|
+
- **One attesting predicate, three consumers.** `classifyReviewReceiptForTree` /
|
|
94
|
+
`summarizeReviewReceiptsForTree` / `describeMissingReviewAttestation` live in the neutral
|
|
95
|
+
`review-ledger-core.mjs` and are read by `review-state.mjs`, `receiptCrossCheck` and the round writer
|
|
96
|
+
— two gates disagreeing about what attests is precisely the class AD-050 closed, and a second copy
|
|
97
|
+
would re-open it. The shared summary also fixes a latent hole: the ledger took `own[own.length - 1]`,
|
|
98
|
+
so a probe landing **after** a real review became the authoritative verdict — a probe SHIP could bury
|
|
99
|
+
a real REWORK and let both gates report convergence. The summary now returns the latest **attesting**
|
|
100
|
+
receipt, never the last line.
|
|
101
|
+
- **Scope of the claim.** What a marker carries is UNTRUSTWORTHINESS, never provenance — receipts are
|
|
102
|
+
not authenticated, and a forger could write `probe:false` as easily as any other field. This is
|
|
103
|
+
self-discipline made legible, not a security boundary. See the BREAKING callout above for the upgrade
|
|
104
|
+
path; full record, including the mid-execution amendment of the original design and the stated
|
|
105
|
+
residuals, in AD-057.
|
|
106
|
+
|
|
7
107
|
## 1.49.0 — Honesty/robustness bundle: refresh EROFS stated skip · settings integer-overflow parity (AD-056)
|
|
8
108
|
|
|
9
109
|
A small **honesty/robustness** release (kit MINOR carrying the two bridge PATCH bumps in-tarball —
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: agent-workflow-kit
|
|
|
3
3
|
description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
metadata:
|
|
6
|
-
version: '1.
|
|
6
|
+
version: '2.1.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-kit
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: antigravity-cli-bridge
|
|
3
3
|
description: Delegate work to Google's Antigravity CLI (`agy`) — the successor to Gemini CLI — to reach Gemini, Claude, and GPT-OSS models under a Google AI Pro/Ultra subscription from the terminal. Use when the user wants to run a headless `agy` prompt, hand a focused task or second-opinion review to `agy`, install or authenticate Antigravity CLI, check or economise its quota/models, bridge project context into `agy`, set up a second delegated-execution backend beside Codex, or troubleshoot `agy` flags, models, auth, conversations, or its no-JSON headless behaviour.
|
|
4
4
|
metadata:
|
|
5
|
-
version: '
|
|
5
|
+
version: '3.0.0'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# antigravity-cli-bridge
|
|
@@ -69,6 +69,14 @@ list wins.
|
|
|
69
69
|
|
|
70
70
|
## Usage
|
|
71
71
|
|
|
72
|
+
> **The machine-readable mode catalog lives in [`capability.json`](capability.json) `modeCatalog`** —
|
|
73
|
+
> every documented mode (`agy-run` raw prompts, the three `agy-review` modes, their continuations,
|
|
74
|
+
> the `AGY_PROBE` escape) with its purpose, when to use it (and when not), the exact invocation form
|
|
75
|
+
> with its operand slots, and the guardrails that really apply. The catalog tracks **the documented
|
|
76
|
+
> wrapper mode set** (never "the CLI's modes"): an upstream Antigravity CLI change reaches it through
|
|
77
|
+
> a bridge release, where the source-level drift tests fail loudly until the catalog is updated.
|
|
78
|
+
> Nothing probes a live CLI. The prose below stays the human tour.
|
|
79
|
+
|
|
72
80
|
Drive `agy` only through the wrapper [`bin/agy.sh`](bin/agy.sh) (installed on `PATH` as `agy-run`):
|
|
73
81
|
|
|
74
82
|
```bash
|
|
@@ -110,11 +118,16 @@ review **guesses** (stale-model and partial-diff false positives). `agy-review`
|
|
|
110
118
|
POSTURE + a **model/cutoff GUARD** + your **`--facts`** (the verified facts the model reviews AGAINST)
|
|
111
119
|
+ **`--decided`** (the anti-circling list) + **`--focus`** + the artifact + a strict output shape, then
|
|
112
120
|
delegates execution to `agy-run` (one home for the timeout, the subscription invariant, and the byte
|
|
113
|
-
ceiling).
|
|
121
|
+
ceiling). In `code` mode grounding **fails closed**: without a non-empty `--facts` payload the wrapper
|
|
122
|
+
refuses **before spending a run** (an ungrounded code receipt records `grounded:false`, which the
|
|
123
|
+
review-state gate rejects — the run would attest nothing). The explicit escapes are `--ungrounded`
|
|
124
|
+
(a throwaway opinion) and `AGY_PROBE=1` (a probe never attests anyway); `plan`/`diff` keep the loud
|
|
125
|
+
warning and proceed.
|
|
114
126
|
|
|
115
127
|
```bash
|
|
116
|
-
agy-review code
|
|
117
|
-
agy-review
|
|
128
|
+
agy-review code --facts @facts.md [--decided @decided.md] [--focus "…"] # the repo-complete diff (facts REQUIRED — fails closed pre-spend)
|
|
129
|
+
agy-review code --ungrounded # explicit escape: throwaway ungrounded opinion (receipt never attests)
|
|
130
|
+
agy-review plan <plan-file> [--facts @f] … # critique a plan (no facts ⇒ loud warning)
|
|
118
131
|
agy-review diff <diff-file> [--facts @f] … # review a supplied diff
|
|
119
132
|
agy-review --continue --decided @round1.md --focus "still-open items" # round-2 delta, no re-assembly
|
|
120
133
|
```
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
# 1. POSTURE read-only second-opinion reviewer; findings only, no edits/commits
|
|
15
15
|
# 2. GUARD do NOT opine on AI model names/versions or your knowledge cutoff
|
|
16
16
|
# 3. FACTS "## Grounded facts — review AGAINST these, do NOT guess the code"
|
|
17
|
-
# (
|
|
17
|
+
# (code mode REFUSES pre-spend without a non-empty payload — escapes:
|
|
18
|
+
# --ungrounded / AGY_PROBE=1; plan/diff omitted -> a LOUD stderr warning)
|
|
18
19
|
# 4. DECIDED "## Decisions already made / already addressed — do NOT re-raise"
|
|
19
20
|
# (optional; the anti-circling lever — the round-2 payload)
|
|
20
21
|
# 5. FOCUS the merged --focus / trailing focus text (optional)
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
# facts (--facts), the already-decided list (--decided), and the focus (--focus).
|
|
28
29
|
#
|
|
29
30
|
# Usage (installed on PATH as `agy-review`):
|
|
30
|
-
# agy-review code [--facts @f] [--decided @f] [--focus "…"] [extra focus…]
|
|
31
|
+
# agy-review code [--facts @f] [--ungrounded] [--decided @f] [--focus "…"] [extra focus…]
|
|
31
32
|
# agy-review plan <plan-file> [--facts @f] [--decided @f] [--focus "…"]
|
|
32
33
|
# agy-review diff <diff-file> [--facts @f] [--decided @f] [--focus "…"]
|
|
33
34
|
# agy-review --continue [--decided @f] [--focus "…"] # round-2 delta (no mode, no re-assembly)
|
|
@@ -55,19 +56,22 @@ case "${1:-}" in
|
|
|
55
56
|
agy-review — grounded read-only ADVISORY review by Google's Antigravity CLI (agy; subscription-only).
|
|
56
57
|
|
|
57
58
|
Usage:
|
|
58
|
-
agy-review code [--facts @f] [--decided @f] [--focus "…"] [extra focus…]
|
|
59
|
+
agy-review code [--facts @f] [--ungrounded] [--decided @f] [--focus "…"] [extra focus…]
|
|
59
60
|
agy-review plan <plan-file> [--facts @f] [--decided @f] [--focus "…"]
|
|
60
61
|
agy-review diff <diff-file> [--facts @f] [--decided @f] [--focus "…"]
|
|
61
62
|
|
|
62
63
|
Flags:
|
|
63
|
-
--facts @f — verified facts the review runs AGAINST (
|
|
64
|
+
--facts @f — verified facts the review runs AGAINST (code mode REQUIRES a non-empty payload; plan/diff warn loudly when omitted)
|
|
65
|
+
--ungrounded — deliberately ungrounded CODE review, a throwaway opinion (code mode only, contradicts --facts; the receipt records grounded:false and never attests)
|
|
64
66
|
--decided @f — already-decided / already-addressed list; do NOT re-raise (anti-circling; the round-2 payload)
|
|
65
67
|
--focus "…" — extra focus (repeatable; code mode also takes trailing focus words)
|
|
66
68
|
|
|
67
69
|
Grounding:
|
|
68
70
|
grounded review — agy reads NOTHING by default, an ungrounded review GUESSES:
|
|
69
71
|
--facts @f = the verified facts to review AGAINST; --decided @f = decisions
|
|
70
|
-
already made, do NOT re-raise (anti-circling)
|
|
72
|
+
already made, do NOT re-raise (anti-circling). code mode REQUIRES a non-empty
|
|
73
|
+
--facts payload and refuses BEFORE spending a run (escapes: --ungrounded,
|
|
74
|
+
AGY_PROBE=1); plan/diff proceed with a loud warning
|
|
71
75
|
|
|
72
76
|
Notes:
|
|
73
77
|
pre-dispatch host-diff: before the FIRST dispatch of this bridge, diff its declared networkHosts
|
|
@@ -88,17 +92,21 @@ Receipt:
|
|
|
88
92
|
sockets — are excluded from the domain entirely, untracked symlinks/directories ride as
|
|
89
93
|
name-only notes) in code mode, the artifact-file sha256 in plan/diff mode; verdict
|
|
90
94
|
recorded verbatim from the mandated '### Verdict' section (SHIP / SHIP WITH NITS / REWORK);
|
|
91
|
-
grounded = whether a NON-EMPTY --facts payload was supplied (
|
|
95
|
+
grounded = whether a NON-EMPTY --facts payload was supplied (code mode refuses pre-spend without
|
|
96
|
+
one — no run, no receipt — unless --ungrounded/AGY_PROBE=1; in plan/diff an empty payload records
|
|
92
97
|
grounded:false — fail-closed, the state gate rejects it), factsHash = sha256 of the facts
|
|
93
98
|
payload; a continuation receipt is fresh:false (informational-only — it cannot attest the
|
|
94
|
-
folded tree);
|
|
99
|
+
folded tree); probe = whether the run relaxed the quality guards (AGY_PROBE=1), written on EVERY
|
|
100
|
+
receipt so it self-declares — the kit's review-state gate rejects a probe-marked receipt (a probe
|
|
101
|
+
review never attests) and equally rejects an unmarked one (silence is not a declaration); a write
|
|
102
|
+
failure warns, never fails the review
|
|
95
103
|
|
|
96
104
|
Settings file (KEY=VALUE, parsed never sourced; env wins over file, file wins over built-in default):
|
|
97
105
|
${XDG_CONFIG_HOME:-~/.config}/agent-workflow/bridge-settings.conf
|
|
98
106
|
AGY_HARD_TIMEOUT — hard wall-clock cap, duration string like 5m/30m/90s (built-in default 30m)
|
|
99
107
|
AGY_REVIEW_ALLOW_ADDDIR — boolean 0/1: 1 arms the oversized --add-dir escape (re-enables the Issue-001 stall risk; default 0)
|
|
100
108
|
|
|
101
|
-
Closed grammar: unknown flags are rejected; no '--' passthrough (the
|
|
109
|
+
Closed grammar: unknown flags are rejected; no '--' passthrough (the flag escape is --ungrounded; the env escapes are AGY_PROBE=1 and AGY_REVIEW_ALLOW_ADDDIR=1).
|
|
102
110
|
Requires at run time: the agy CLI on PATH + a Google AI subscription login (--help needs neither).
|
|
103
111
|
HELP
|
|
104
112
|
exit 0
|
|
@@ -217,7 +225,7 @@ DEFAULT_AGY_REVIEW_MODEL="Gemini 3.1 Pro (High)"
|
|
|
217
225
|
# Review-receipt identity (AD-038). AW_BRIDGE_VERSION mirrors this bridge's SKILL.md/capability.json
|
|
218
226
|
# version (drift-guarded by agy-review.test.mjs against capability.json).
|
|
219
227
|
AW_RECEIPT_BACKEND="agy"
|
|
220
|
-
AW_BRIDGE_VERSION="
|
|
228
|
+
AW_BRIDGE_VERSION="3.0.0"
|
|
221
229
|
# `-` not `:-` so an EXPLICIT empty AGY_MODEL= survives (drop --model, use settings.json — agy.sh:52).
|
|
222
230
|
AGY_MODEL="${AGY_MODEL-$DEFAULT_AGY_REVIEW_MODEL}"
|
|
223
231
|
# Frontier review models. ANY model is allowed; a sub-frontier one only earns a soft, silenceable warning.
|
|
@@ -228,6 +236,10 @@ FRONTIER_SET=("Gemini 3.1 Pro (High)" "Claude Opus 4.6 (Thinking)" "Claude Sonne
|
|
|
228
236
|
AGY_HARD_TIMEOUT="${AGY_HARD_TIMEOUT:-30m}"
|
|
229
237
|
AGY_TIMEOUT="${AGY_TIMEOUT:-$AGY_HARD_TIMEOUT}"
|
|
230
238
|
AGY_PROBE="${AGY_PROBE:-0}"
|
|
239
|
+
# A probe run is RECORDED, not just silently allowed: the receipt carries probe:true so the kit's
|
|
240
|
+
# review-state gate rejects it — a guards-relaxed review must never attest a tree.
|
|
241
|
+
REVIEW_PROBE=false
|
|
242
|
+
if [[ "$AGY_PROBE" == "1" ]]; then REVIEW_PROBE=true; fi
|
|
231
243
|
AGY_REVIEW_ALLOW_ADDDIR="${AGY_REVIEW_ALLOW_ADDDIR:-0}"
|
|
232
244
|
AGY_MAX_PROMPT_BYTES="${AGY_MAX_PROMPT_BYTES:-120000}"
|
|
233
245
|
if [[ ! "$AGY_MAX_PROMPT_BYTES" =~ ^[0-9]+$ ]]; then
|
|
@@ -432,13 +444,18 @@ receipt_json_scalar() {
|
|
|
432
444
|
if [[ -z "${1:-}" ]]; then printf 'null'; else printf '"%s"' "$1"; fi
|
|
433
445
|
}
|
|
434
446
|
|
|
435
|
-
# write_review_receipt <artifact|""> <fresh: true|false> <fingerprint|""> <verdict> <grounded: true|false> <factsHash|"">
|
|
447
|
+
# write_review_receipt <artifact|""> <fresh: true|false> <fingerprint|""> <verdict> <grounded: true|false> <factsHash|""> [probe: true|false]
|
|
436
448
|
# Appends ONE receipt line (the AD-038 fixture shape) as a side effect of a SUCCESSFUL review —
|
|
437
449
|
# to $AW_REVIEW_RECEIPTS when set, else <git dir>/agent-workflow-review-receipts.jsonl (inside the
|
|
438
450
|
# git dir by construction, so it is never committable). Fail-safe: every failure here warns loudly
|
|
439
451
|
# and returns 0 — a missing receipt fails the kit's review-state CHECKER, never the review run.
|
|
452
|
+
# The optional 7th argument marks a PROBE run (CODEX_PROBE=1 / AGY_PROBE=1 — the quality guards
|
|
453
|
+
# relaxed), which the kit's review-state gate rejects: a probe review must never attest a tree. The
|
|
454
|
+
# marker is written ALWAYS, true or false: the receipt SELF-DECLARES, so the gate reads the fact
|
|
455
|
+
# itself instead of inferring it from this wrapper's version (which bumps in a different release
|
|
456
|
+
# phase). Silence is not a declaration — an unmarked receipt is untrustworthy and the gate rejects it.
|
|
440
457
|
write_review_receipt() {
|
|
441
|
-
local artifact="$1" fresh="$2" fingerprint="$3" verdict="$4" grounded="$5" facts_hash="$6"
|
|
458
|
+
local artifact="$1" fresh="$2" fingerprint="$3" verdict="$4" grounded="$5" facts_hash="$6" probe="${7:-false}"
|
|
442
459
|
local receipts="${AW_REVIEW_RECEIPTS:-}"
|
|
443
460
|
if [[ -z "$receipts" ]]; then
|
|
444
461
|
local receipt_git_dir
|
|
@@ -448,11 +465,12 @@ write_review_receipt() {
|
|
|
448
465
|
fi
|
|
449
466
|
receipts="$receipt_git_dir/agent-workflow-review-receipts.jsonl"
|
|
450
467
|
fi
|
|
451
|
-
local line
|
|
452
|
-
|
|
468
|
+
local line probe_field=',"probe":false'
|
|
469
|
+
if [[ "$probe" == "true" ]]; then probe_field=',"probe":true'; fi
|
|
470
|
+
line="$(printf '{"schema":1,"artifact":%s,"fresh":%s,"fingerprint":%s,"backend":"%s","verdict":"%s","grounded":%s,"factsHash":%s,"wrapperVersion":"%s","timestamp":"%s"%s}' \
|
|
453
471
|
"$(receipt_json_scalar "$artifact")" "$fresh" "$(receipt_json_scalar "$fingerprint")" \
|
|
454
472
|
"$AW_RECEIPT_BACKEND" "$verdict" "$grounded" "$(receipt_json_scalar "$facts_hash")" \
|
|
455
|
-
"$AW_BRIDGE_VERSION" "$(date -u +%Y-%m-%dT%H:%M:%SZ)")"
|
|
473
|
+
"$AW_BRIDGE_VERSION" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$probe_field")"
|
|
456
474
|
if ! printf '%s\n' "$line" >>"$receipts" 2>/dev/null; then
|
|
457
475
|
echo "warning: could not append the review receipt to $receipts — the review itself succeeded;" >&2
|
|
458
476
|
echo " the review-state gate will read the current tree as un-receipted." >&2
|
|
@@ -528,7 +546,7 @@ case "${1:-}" in
|
|
|
528
546
|
esac
|
|
529
547
|
|
|
530
548
|
usage() {
|
|
531
|
-
echo "usage: $0 code [--facts @f] [--decided @f] [--focus \"…\"] [extra focus…]" >&2
|
|
549
|
+
echo "usage: $0 code [--facts @f] [--ungrounded] [--decided @f] [--focus \"…\"] [extra focus…]" >&2
|
|
532
550
|
echo " $0 plan <plan-file> [--facts @f] [--decided @f] [--focus \"…\"]" >&2
|
|
533
551
|
echo " $0 diff <diff-file> [--facts @f] [--decided @f] [--focus \"…\"]" >&2
|
|
534
552
|
echo " $0 --continue [--decided @f] [--focus \"…\"]" >&2
|
|
@@ -567,6 +585,7 @@ fi
|
|
|
567
585
|
# --- Flag parse (--facts / --decided / --focus + trailing focus) -------------
|
|
568
586
|
FACTS_RAW=""
|
|
569
587
|
DECIDED_RAW=""
|
|
588
|
+
UNGROUNDED=0
|
|
570
589
|
FOCUS_PARTS=()
|
|
571
590
|
# A value-taking flag must be followed by a real value — never end-of-args and never another flag.
|
|
572
591
|
# Otherwise `agy-review code --facts --focus x` would silently take "--focus" as the facts and spend a
|
|
@@ -585,6 +604,12 @@ while [[ $# -gt 0 ]]; do
|
|
|
585
604
|
exit 2
|
|
586
605
|
fi
|
|
587
606
|
need_value "$1" "${2:-}"; FACTS_RAW="$2"; shift 2 ;;
|
|
607
|
+
--ungrounded)
|
|
608
|
+
if [[ -n "$resume_mode" ]]; then
|
|
609
|
+
echo "error: --ungrounded is not valid on a continuation (the original round already set its grounding)." >&2
|
|
610
|
+
exit 2
|
|
611
|
+
fi
|
|
612
|
+
UNGROUNDED=1; shift ;;
|
|
588
613
|
--decided)
|
|
589
614
|
need_value "$1" "${2:-}"; DECIDED_RAW="$2"; shift 2 ;;
|
|
590
615
|
--focus)
|
|
@@ -610,6 +635,18 @@ done
|
|
|
610
635
|
# Merge --focus values and trailing focus words, in parse order, into ONE focus block.
|
|
611
636
|
FOCUS="${FOCUS_PARTS[*]:-}"
|
|
612
637
|
|
|
638
|
+
# --ungrounded closed grammar (D4): code-mode only, and an explicit contradiction with --facts refuses.
|
|
639
|
+
if [[ "$UNGROUNDED" == "1" ]]; then
|
|
640
|
+
if [[ -n "$FACTS_RAW" ]]; then
|
|
641
|
+
echo "error: --ungrounded contradicts --facts — pass the verified facts (grounded) or drop them (--ungrounded), never both." >&2
|
|
642
|
+
exit 2
|
|
643
|
+
fi
|
|
644
|
+
if [[ "$mode" != "code" ]]; then
|
|
645
|
+
echo "error: --ungrounded is only valid in code mode — $mode mode already proceeds ungrounded with a loud warning." >&2
|
|
646
|
+
exit 2
|
|
647
|
+
fi
|
|
648
|
+
fi
|
|
649
|
+
|
|
613
650
|
# Resolve @file / literal for --facts and --decided NOW (cwd = invocation, before any code-mode cd).
|
|
614
651
|
# The `@file` existence check runs at TOP LEVEL (not inside a command substitution) so its exit-2 exits
|
|
615
652
|
# the whole script, not just a subshell.
|
|
@@ -635,6 +672,25 @@ if [[ -n "$DECIDED_RAW" ]]; then
|
|
|
635
672
|
fi
|
|
636
673
|
|
|
637
674
|
if [[ -z "$FACTS_CONTENT" && -z "$resume_mode" ]]; then
|
|
675
|
+
# code mode fails CLOSED before the spend (D4): an ungrounded CODE receipt records grounded:false,
|
|
676
|
+
# which the review-state gate rejects — the run would be paid for and attest nothing. Keyed on the
|
|
677
|
+
# resolved CONTENT, so --facts naming an empty payload refuses identically.
|
|
678
|
+
if [[ "$mode" == "code" && "$UNGROUNDED" != "1" && "$AGY_PROBE" != "1" ]]; then
|
|
679
|
+
# The recovery hint resolves the kit's grounding tool from THIS wrapper's location (monorepo
|
|
680
|
+
# canon / deployed skills sibling / kit-bundled mirror) — a repo-relative path would not exist
|
|
681
|
+
# for a globally installed kit. Quoted: an install path may carry spaces.
|
|
682
|
+
grounding_tool="node <agent-workflow-kit>/tools/grounding.mjs"
|
|
683
|
+
for _g in "$HERE/../../agent-workflow-kit/tools/grounding.mjs" "$HERE/../../../tools/grounding.mjs"; do
|
|
684
|
+
if [[ -f "$_g" ]]; then grounding_tool="node \"$_g\""; break; fi
|
|
685
|
+
done
|
|
686
|
+
echo "error: 'agy-review code' requires grounded facts and refuses BEFORE spending a run — an" >&2
|
|
687
|
+
echo " ungrounded code review GUESSES, and its receipt (grounded:false) never attests." >&2
|
|
688
|
+
echo " Assemble the verified facts, then re-run:" >&2
|
|
689
|
+
echo " $grounding_tool --constraints [--plan <plan-file>] --out <facts-file>" >&2
|
|
690
|
+
echo " agy-review code --facts @<facts-file>" >&2
|
|
691
|
+
echo " Explicit escapes: --ungrounded (throwaway opinion) · AGY_PROBE=1 (a probe never attests)." >&2
|
|
692
|
+
exit 2
|
|
693
|
+
fi
|
|
638
694
|
echo "warning: no --facts supplied. agy reads NOTHING by default, so an ungrounded review GUESSES" >&2
|
|
639
695
|
echo " (stale-model and partial-diff false positives). Pass --facts @file with the verified" >&2
|
|
640
696
|
echo " facts the model must review AGAINST. Proceeding without grounding." >&2
|
|
@@ -795,7 +851,7 @@ if [[ $rc -eq 0 ]]; then
|
|
|
795
851
|
# A continuation never re-embeds the current artifact (agy holds the ORIGINAL round server-side;
|
|
796
852
|
# --facts is rejected above), so it cannot attest the folded tree: fresh:false, artifact /
|
|
797
853
|
# fingerprint / factsHash null, grounded false — informational-only, ignored by the state gate.
|
|
798
|
-
write_review_receipt "" false "" "$verdict" false ""
|
|
854
|
+
write_review_receipt "" false "" "$verdict" false "" "$REVIEW_PROBE"
|
|
799
855
|
echo "notice: a continuation receipt is fresh:false (informational-only) — only a fresh grounded run" >&2
|
|
800
856
|
echo " (agy-review code --facts @f) mints a receipt that satisfies the review-state gate." >&2
|
|
801
857
|
else
|
|
@@ -805,7 +861,7 @@ if [[ $rc -eq 0 ]]; then
|
|
|
805
861
|
grounded=true
|
|
806
862
|
facts_hash="$(printf '%s' "$FACTS_CONTENT" | sha256_stdin || true)"
|
|
807
863
|
fi
|
|
808
|
-
write_review_receipt "$REVIEW_ARTIFACT" true "$REVIEW_FINGERPRINT" "$verdict" "$grounded" "$facts_hash"
|
|
864
|
+
write_review_receipt "$REVIEW_ARTIFACT" true "$REVIEW_FINGERPRINT" "$verdict" "$grounded" "$facts_hash" "$REVIEW_PROBE"
|
|
809
865
|
fi
|
|
810
866
|
fi
|
|
811
867
|
exit $rc
|