@estebanforge/pi-antigravity-bridge 1.4.8 → 1.4.10
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 +30 -0
- package/README.md +42 -7
- package/docs/ACP-ADOPTION-PLAN.md +83 -18
- package/docs/ACP-PROTOCOL-REFERENCE.md +4 -3
- package/docs/ARCHITECTURE.md +12 -5
- package/docs/DEVELOPMENT.md +16 -0
- package/docs/PI-BRIDGE-GAPS.md +26 -5
- package/docs/TODO.md +21 -0
- package/extensions/index.ts +221 -22
- package/package.json +1 -1
- package/src/acp/connection.ts +12 -0
- package/src/acp/driver.ts +17 -10
- package/src/acp/events.ts +17 -0
- package/src/approval-detect.ts +146 -0
- package/src/approval-gate.ts +208 -0
- package/src/approval-hook.ts +252 -0
- package/src/config.ts +43 -0
- package/src/daily-log.ts +11 -10
- package/src/driver-types.ts +13 -9
- package/src/driver.ts +6 -5
- package/src/mcp-registration.ts +127 -0
- package/src/mcp-server.ts +192 -10
- package/src/models.ts +2 -2
- package/src/provider.ts +216 -31
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.4.10] - 2026-09-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Approval gate for agy native tool calls. agy runs its own agent loop, and its mutating native tools (`run_command`, `create_file`, `edit_file`, ...) executed with no pi involvement: pi's permission extensions never saw them. The gate routes the calls through a pi-side approval in builtin shape, so the existing permission-extension ecosystem gates them with zero changes: a staged `.agents/hooks.json` `PreToolUse` hook parks the call in the bridge, the provider emits a pi `toolUse` for a builtin-shaped shadow tool (`bash`/`write`/`edit`), and the decision - allow, or deny with a reason the model sees - travels back to the hook. Marker calls never execute locally and are verified against the bridge's pending-ticket set (a forged marker denies even in allow mode); non-marker calls delegate to factory twins of the real builtins, so normal pi behavior is unchanged. Read-only agy tools stay ungated. Opt-in via `approvals.gateMode` (`auto`, the default, keeps it off until a known pi permission extension is detected; `shadow` forces on; `off` forces off) and `approvals.mode` (`ask`, the default, shows a pi confirm dialog and denies headless; `allow`/`deny` skip the dialog). Timeout, an unwired gate, and shutdown all deny fail-closed. Every decision lands in the daily log with tool names, source, and latency. README has the full section plus a sample gate extension.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Concurrent pi sessions on the same workspace no longer disable each other's approval gate. The staged `hooks.json` group was one shared key, so a second session resolving the gate to `off` deleted the first session's live gate, and two gate-on sessions overwrote each other's port/token/script. Groups are now keyed per session (`pi-bridge-gate-<pid>`), shutdown removes only the session's own group, and the next staging sweeps groups whose owning session is dead (found by an external pre-release audit).
|
|
14
|
+
- The shared `~/.gemini/config/mcp_config.json` now lands `0600` (dir `0700`). It carries the bridge's shared-secret token and previously landed at the umask default (typically world-readable) (found by an external pre-release audit).
|
|
15
|
+
- Bridge tools now register for the stream-json engine. That engine registered nothing: the agy CLI discovers MCP servers from `~/.gemini/config/mcp_config.json`, which the bridge never wrote (only the per-invocation `--add-dir` config existed), and the gap was masked because the daily engine is ACP. The bridge now registers itself there per-pid (`pi-bridge-<pid>`) at session start, sweeps stale entries left by crashed sessions, and unregisters on shutdown. Foreign servers in the shared file are preserved; a corrupt file is refused, never rewritten. Probe-verified live: agy discovers the server and completes tool calls through its native `call_mcp_tool` wrapper.
|
|
16
|
+
- Image blocks in tool results now reach the model on the stream-json engine too (they were ACP-only). The engine gate downgraded pixels to a text label over an unverified transport concern; a live probe settled it - the CLI's MCP client delivers tool-result image content, and the model named a two-tone PNG's halves from the tool result alone with no decoders in the frame trail. `read` on an image file now gives agy real pixels on both engines. Stream-json prompt attachments and the late-delivery prompt stay text-only by design.
|
|
17
|
+
|
|
18
|
+
## [1.4.9] - 2026-09-05
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Warn toasts in the pi UI: bridge tool failures, stalls, timeouts, process exits, and other warnings surface as native warning notifications the moment they happen, so users see them and can report them. Over SSH or without a UI the same text falls back to stderr. Deliberate aborts, connection exits (the turn's own error block carries real crashes), and `call-tool-fail` (same-instant duplicate of `round-trip-fail`) stay silent.
|
|
23
|
+
- Gate B watch in `/agy doctor`: the ACP connection latches the first `session/update` payload that carries usage/token fields, and doctor prints one "acp tokens: AVAILABLE" line when that happens. Silent until then; the day the line appears, wiring real token counts becomes a small mapping job. Auth-style string `"token"` keys inside tool frames cannot trip the latch.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Esc-abort on the ACP engine no longer dumps the dying server's raw stderr tail (a google3 stack trace) into the transcript. Teardown exits (abort kill, shutdown, idle recycle) are marked expected and never render; a genuine mid-turn crash surfaces as the turn's own clean error block instead. Raw tails still land in the file log for post-mortems.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- The ACP engine is now beta. Parity is verified live against RC01 (text streaming, multi-turn resume, bridge tools, effort switching, serialization, abort recovery - see `scripts/parity-live.mjs`), so it graduates from opt-in-experimental to a supported alternative engine. It stays behind `config.engine` for now; the two known RC01 gaps (no usage fields, kill+reload abort) are documented in the README.
|
|
32
|
+
- Daily log volume: the default tier now writes ONLY errors, so a regular session costs the disk nothing. Warns live in the UI (see above); `AGY_DEBUG=1` restores the full debug/info/warn/error trail for reproducing a problem. Docs: README debug-logs section, `/agy doctor` hint.
|
|
33
|
+
- The tool-priority note now steers agy's native `view_file` (artifact-sandboxed on RC01) to the Pi Bridge file tools (`read`, `ls`, `grep`, `find`, `edit`, `execute`) for any real filesystem path. Observed live: repeated `invalid_args` rejections on `operator/pkg/tmux/client.go` before the model fell back to `edit`.
|
|
34
|
+
|
|
5
35
|
## [1.4.8] - 2026-09-05
|
|
6
36
|
|
|
7
37
|
### Added
|
package/README.md
CHANGED
|
@@ -21,15 +21,16 @@ Multi-turn works. The provider binds a pi session to an agy conversation id (per
|
|
|
21
21
|
Turns run through one of two engines behind the same provider surface (`config.engine`, default `stream-json`):
|
|
22
22
|
|
|
23
23
|
- **stream-json** (default): the persistent `agy` CLI process. The tested default; live token usage; conversation resume via `--conversation`.
|
|
24
|
-
- **acp
|
|
24
|
+
- **acp** (beta): Google's official ACP server (`agy_acp_server.par`), JSON-RPC 2.0 over stdio. Beta: parity-verified live against the current build (RC01) - text streaming, multi-turn resume via `session/load`, bridge tools, effort switching, serialization, abort recovery (see `scripts/parity-live.mjs`). Two known RC01 gaps remain: no usage fields (token display shows zero) and no cancel (abort tears the server down and reloads it next turn).
|
|
25
25
|
|
|
26
26
|
Engine-dependent features: pi image attachments ride natively only on the ACP engine (the picker offers image attach automatically when `config.engine` is `acp`; the stream-json CLI prompt is text-only). With the optional G1 digest enabled, its delivery also differs: ACP ships it as a native `embeddedContext` resource block, stream-json prepends it to the prompt text. The `AskAntigravity` delegation tool is unaffected by `config.engine` and runs the `stream-json` CLI (`agy -p`) across both configurations.
|
|
27
27
|
|
|
28
|
-
| Capability | `stream-json` (default) | `acp` |
|
|
28
|
+
| Capability | `stream-json` (default) | `acp` (beta) |
|
|
29
29
|
| --- | --- | --- |
|
|
30
30
|
| Show thinking text | No (token count only, floor 64, no text body) | Yes (streams thought text via `agent_thought_chunk`; sparse on RC01 where reasoning often arrives in message text) |
|
|
31
31
|
| Live token usage | Yes (live metrics from CLI step events) | No (absent in RC01, displays zero tokens) |
|
|
32
32
|
| Image prompt input | No (CLI prompt is text-only; images dropped) | Yes (native image blocks forwarded to server) |
|
|
33
|
+
| Image tool results | Yes (bridge tool results carry pixels; probe-verified 2026-09-07) | Yes (probe-verified 2026-09-05) |
|
|
33
34
|
| Audio prompt input | No (dropped) | Protocol advertised (`promptCapabilities.audio: true`) |
|
|
34
35
|
| Review-only plan mode | Yes (`--mode plan` review-only via `/agy mode plan`) | No (RC01 modes are permission levels; plan mode refused) |
|
|
35
36
|
| Leading slash commands in prompt | Disabled via `--disable-slash-commands` (sent as plain text) | Server intercepts recognized commands (e.g. `/plan`) and executes them under the active policy |
|
|
@@ -57,7 +58,7 @@ agy runs its own closed tool loop (`read_file`, `write_file`, `edit_file`, `run_
|
|
|
57
58
|
Residual limits (with or without the bridge):
|
|
58
59
|
|
|
59
60
|
- agy's own edits still land directly on disk; pi's inline diff review does not engage for them.
|
|
60
|
-
- agy commands run without per-action approval, same as every other tool in pi. See [Permissions](#permissions) below.
|
|
61
|
+
- agy commands run without per-action approval by default, same as every other tool in pi. The [Approval gate](#approval-gate-agy-native-tools) can put pi-side review in front of agy's mutating native tools (off by default; `auto` enables it only when a pi permission extension is installed). See also [Permissions](#permissions) below.
|
|
61
62
|
- No cost accounting: cost stays zero because agy runs on your subscription quota. Token usage is live.
|
|
62
63
|
|
|
63
64
|
## MCP tool bridge (agy uses pi's tools)
|
|
@@ -91,6 +92,38 @@ your pi Agent Skills catalog; calling it returns the SKILL.md body. The bridge
|
|
|
91
92
|
answers it directly, no pi round-trip. `/agy doctor` prints driver counters,
|
|
92
93
|
bridge port, and the last lifecycle events without spending tokens.
|
|
93
94
|
|
|
95
|
+
## Approval gate (agy native tools)
|
|
96
|
+
|
|
97
|
+
agy is not a plain model: it runs its own agent loop with its own native tools (`run_command`, `create_file`, `edit_file`, ...). Those calls execute inside agy with no pi involvement, so pi's permission extensions never saw them. The approval gate closes that gap: agy native tool calls pass through a pi-side approval in a form the existing permission-extension ecosystem gates with zero changes.
|
|
98
|
+
|
|
99
|
+
Mechanics: the extension stages an `.agents/hooks.json` group in the workspace; the Antigravity server/CLI fires a `PreToolUse` hook before each mutating native tool runs. The hook script (generated, per-pid, mode 0600 because it embeds the bridge token) POSTs the call to the bridge and polls for a decision. The bridge parks it, the provider interrupts the pi-side view of the agy turn with a `toolUse` for a SHADOW tool named `bash`/`write`/`edit` (same schema as the real builtin plus internal `__agy*` marker fields), and pi's whole `tool_call` surface applies: any installed permission extension gates the call unchanged, and only if nothing blocks does the fallback policy run. The decision travels back to the hook and agy enforces it; on deny the reason text is what agy's model sees. Marker calls never execute locally (a ticket check denies forged ones); non-marker calls delegate to a factory twin of the real builtin, so normal pi bash/write/edit behavior is unchanged. Read-only agy tools stay ungated. Every decision lands in the daily log with tool names, source, and latency.
|
|
100
|
+
|
|
101
|
+
Configuration (`/agy` config keys or environment):
|
|
102
|
+
|
|
103
|
+
```jsonc
|
|
104
|
+
{
|
|
105
|
+
"approvals": {
|
|
106
|
+
"gateMode": "auto", // auto | shadow | dedicated | off
|
|
107
|
+
"mode": "ask" // ask | allow | deny (fallback when no extension gates)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// env: AGY_APPROVALS=shadow AGY_APPROVALS_MODE=ask
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`auto` (default) keeps the gate OFF until one of the known pi permission packages is detected (pi settings `packages` name-match or known config markers). `shadow` forces it on; `off` forces it off. `dedicated` currently stages the same shadow tools (the explicit `antigravity_approve` variant is planned; the config value is accepted today so the schema is stable). The fallback `mode` is consulted only when no extension blocked the call: `ask` shows a pi confirm dialog (headless runs deny, fail-closed), `allow` approves, `deny` blocks. Timeouts deny fail-closed: the staged hook timeout always exceeds the park budget, but a hook that outlives its timeout soft-passes upstream (verified against the ACP server), so the park always answers first.
|
|
114
|
+
|
|
115
|
+
If you write your own gate extension, it sees a normal pi tool call:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
export default function (pi) {
|
|
119
|
+
pi.on("tool_call", async (event) => {
|
|
120
|
+
if (event.input?.__agyGate && event.input.command?.startsWith("rm ")) {
|
|
121
|
+
return { block: true, reason: "rm is not allowed through the agy gate" };
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
94
127
|
## Install
|
|
95
128
|
|
|
96
129
|
> **No patch required.** The bridge runs on pi's public APIs only; the extension never edits your pi install. If an older version of this extension patched your pi (adding `pi.invokeTool()`), the leftover is inert and a pi update removes it. The extension detects it once and offers `/agy patch-cleanup` to restore the original files from the backup immediately.
|
|
@@ -157,7 +190,7 @@ The `activate_skill` catalog mirrors pi's directory-based skill discovery: the t
|
|
|
157
190
|
/agy system-prompt on|off send pi's system prompt + AGENTS.md + the Pi Bridge tool-priority note to new agy conversations (default on)
|
|
158
191
|
/agy bridge all|mcp|none which pi tools the MCP bridge exposes to agy (default all; none = bridge off)
|
|
159
192
|
/agy acp-bin <path|auto> point the ACP engine at a specific server binary (auto = setup installs, or AGY_ACP_BIN; applies on the next ACP turn)
|
|
160
|
-
/agy engine acp|stream-json switch the turn engine (restart to apply; default stream-json; acp runs self-service setup: binary install + auth bootstrap)
|
|
193
|
+
/agy engine acp|stream-json switch the turn engine (restart to apply; default stream-json; acp is beta and runs self-service setup: binary install + auth bootstrap)
|
|
161
194
|
/agy auth-manual manual ACP credential setup (fallback; auto-setup normally covers this; default login = your Antigravity subscription, same account as the agy CLI)
|
|
162
195
|
/agy patch-cleanup restore the original pi files if an older version patched them
|
|
163
196
|
/agy clear drop all session bindings (force fresh conversations)
|
|
@@ -171,6 +204,8 @@ Because agy runs non-interactively under this provider (nothing can answer a `y/
|
|
|
171
204
|
|
|
172
205
|
If you want agy to execute nothing, use `/agy mode plan`. Do not combine `--sandbox` with skip-permissions ([#36](https://github.com/google-antigravity/antigravity-cli/issues/36)).
|
|
173
206
|
|
|
207
|
+
For per-action review of agy's mutating native tools (`run_command`, `create_file`, `edit_file`, ...), see the [Approval gate](#approval-gate-agy-native-tools): with it on, the call must pass a pi-side approval (your permission extension, or the built-in ask/allow/deny fallback) before agy executes it.
|
|
208
|
+
|
|
174
209
|
### Run pi inside a sandbox
|
|
175
210
|
|
|
176
211
|
For isolation when running any agent that executes commands without a confirmation gate, run pi inside [**construct-cli**](https://github.com/EstebanForge/construct-cli) - EstebanForge's sandbox for AI agents. Isolated container, no path escape, ephemeral filesystem, `strict` / `offline` network modes, secret redaction. The blast radius of a bad command stays in the container, not your host. Install and usage instructions are in that repo.
|
|
@@ -188,7 +223,7 @@ For isolation when running any agent that executes commands without a confirmati
|
|
|
188
223
|
| `AGY_SKIP_PERMISSIONS` | `1`/`true` (default) to pass `--dangerously-skip-permissions` so commands don't hang on an unanswerable prompt in `-p` mode. `0`/`false` to prompt (hangs any `run_command` non-interactively). Wins over the config file. |
|
|
189
224
|
| `AGY_DEFAULT_MODEL` | Default model alias for the `AskAntigravity` tool (`flash`/`pro`/`gemini`, or a tier/version qualifier). Wins over the config file. |
|
|
190
225
|
| `AGY_DEFAULT_THINKING` | Default thinking tier for the `AskAntigravity` tool: `low`/`medium`/`high`. Anything else falls back to `medium`. Wins over the config file. |
|
|
191
|
-
| `AGY_DEBUG` | `1`/`true`/`on` writes
|
|
226
|
+
| `AGY_DEBUG` | `1`/`true`/`on` writes the full trail to the daily log (driver lifecycle, raw bridge traffic). Default off: **only `error` records land on disk** - routine disk writes are zero for regular users, and warnings surface as UI toasts instead. |
|
|
192
227
|
|
|
193
228
|
## Debug logs
|
|
194
229
|
|
|
@@ -198,14 +233,14 @@ The extension keeps a daily log on your machine, sorted by day:
|
|
|
198
233
|
~/.pi/extensions-data/estebanforge/pi-antigravity-bridge/logs/<YYYY-MM-DD>.ndjson
|
|
199
234
|
```
|
|
200
235
|
|
|
201
|
-
One JSON record per line. Two verbosity tiers keep the disk cost
|
|
236
|
+
One JSON record per line. Two verbosity tiers keep the disk cost at zero for regular users: by default only `error` records land on disk - everything routine (turn starts, tool calls, escalations, commands, driver failures) is withheld. Warnings are not lost: the extension toasts each one in the pi UI (bridge tool failures, stalls, timeouts, process exits), so users see them and can report them; deliberate aborts and failures pi already renders as the turn's own error block stay silent. Set `AGY_DEBUG=1` before reproducing a problem for the full trail: per-event driver lifecycle (spawn, exit, session load/new, unparks), turn starts and outcomes, bridge tool calls, escalations and poll traffic, late deliveries, list-tools traffic, recycle causes, and the raw bridge chatter. `/agy doctor` prints the log directory.
|
|
202
237
|
|
|
203
238
|
Notes:
|
|
204
239
|
|
|
205
240
|
- Retention: 14 days. Older files are pruned automatically.
|
|
206
241
|
- Privacy: prompt text, tool arguments, and tool output never land in the log. Secret-shaped values (tokens, API keys, credentials, header blocks) are redacted, and long strings are truncated. The `auth-url` record strips the login URL's query string.
|
|
207
242
|
- Logging never throws: an unwritable directory is skipped silently and retried on the next record.
|
|
208
|
-
- SSD wear: default volume is
|
|
243
|
+
- SSD wear: default volume is effectively zero until something actually errors. Verbose mode (`AGY_DEBUG=1`) writes more; turn it off after reproducing.
|
|
209
244
|
|
|
210
245
|
When you report an issue, attach the last day or two of files from that directory. For anything that needs reproduction, run with `AGY_DEBUG=1` once and attach that day's file. They usually contain the exact failure sequence (engine, session, bridge call, error) with no need to guess.
|
|
211
246
|
|
|
@@ -46,8 +46,11 @@ Adopt the official Google ACP server (`agy_acp_server.par`, registry id
|
|
|
46
46
|
`antigravity-acp`) as a second turn engine for the bridge, behind a config
|
|
47
47
|
switch. The existing stream-json engine stays the default until the ACP
|
|
48
48
|
engine proves parity. Every change is an improvement or a one-to-one
|
|
49
|
-
replacement.
|
|
50
|
-
|
|
49
|
+
replacement.
|
|
50
|
+
|
|
51
|
+
STANDING DECISION (user, 2026-09-07): BOTH engines are permanently
|
|
52
|
+
maintained peers. The streaming engine is never deleted - no phase removes
|
|
53
|
+
it, regardless of upstream progress (including Gate B).
|
|
51
54
|
|
|
52
55
|
Cross-references: [ARCHITECTURE.md](./ARCHITECTURE.md),
|
|
53
56
|
[PI-BRIDGE-GAPS.md](./PI-BRIDGE-GAPS.md), [DEVELOPMENT.md](./DEVELOPMENT.md).
|
|
@@ -165,8 +168,8 @@ is an unmaintained contract. ACP is the maintained one.
|
|
|
165
168
|
| Module | Role today | Disposition under ACP |
|
|
166
169
|
| --- | --- | --- |
|
|
167
170
|
| `src/provider.ts` | streamSimple: pi Context to agy turn to pi events; G9 round-trips; G1 digest; G10 system prompt | KEEP unchanged (additive thought-delta `if` only). Engine-agnostic by contract |
|
|
168
|
-
| `src/driver.ts` | persistent stream-json process, turn queue, recycle, timers | KEEP
|
|
169
|
-
| `src/stream-events.ts` | NDJSON parser + usage mapping | KEEP
|
|
171
|
+
| `src/driver.ts` | persistent stream-json process, turn queue, recycle, timers | KEEP permanently - both engines are maintained peers |
|
|
172
|
+
| `src/stream-events.ts` | NDJSON parser + usage mapping | KEEP permanently - both engines are maintained peers |
|
|
170
173
|
| `src/sessions.ts` | pi session to agy conversation store | KEEP. Add `engine` tag (section 9.4) |
|
|
171
174
|
| `src/config.ts` | runtime config | KEEP. Add engine + acp block (section 9.5) |
|
|
172
175
|
| `src/models.ts` | `agy models` to pi Model projection | KEEP. Catalog source stays the CLI until ACP exposes one (probe A.6) |
|
|
@@ -200,7 +203,7 @@ in git history.
|
|
|
200
203
|
| Cancel | Kill process group; in-flight turn dies | `session/cancel` to `stopReason: cancelled`, process survives | **REGRESSION-MANAGED (Gate D FAIL on RC01): cancel NOT implemented.** Fallback kill + `session/load` VERIFIED; re-check per build |
|
|
201
204
|
| Process lifecycle | One agy child per provider; recycle on model/effort/mode/cwd/conversation drift | One server hosts N sessions | IMPROVEMENT |
|
|
202
205
|
| Model + effort selection | CLI flags + recycle | `session/set_config_option` (`configId`) | PASS (VERIFIED live, Gate A): per-session switching, no recycle |
|
|
203
|
-
| Usage tokens | `toPiUsage` from step events | Not in any payload (Gate B FINAL) | **ABSENT on RC01.** Zero-usage documented
|
|
206
|
+
| Usage tokens | `toPiUsage` from step events | Not in any payload (Gate B FINAL) | **ABSENT on RC01.** Zero-usage documented and ACCEPTED for the flip (user decision 2026-09-07: Gate B no longer blocks the default). Both engines are permanently maintained - no deletion |
|
|
204
207
|
| MCP tools (G9) | Our HTTP bridge server via `--add-dir` config | `mcpServers` param (`{name,type:"http",url,headers:[]}`) | PARITY at shape level (verified). Phase-1 acceptance: bridge `tools/list`+`tools/call` end-to-end |
|
|
205
208
|
| Skills | `--disable-slash-commands`; bridge owns skills | Unknown slash behavior; `available_commands_update` exists | PARITY. Keep our bridge; probe F.7 |
|
|
206
209
|
| G1 digest, G10 system prompt | Provider-side prompt assembly | Same (we compose the prompt either way) | PARITY. `embeddedContext` is a later enhancement |
|
|
@@ -318,7 +321,7 @@ Tested with the parity suite (section 11) and `scripts/parity-live.mjs`
|
|
|
318
321
|
|
|
319
322
|
| Risk | Impact | Mitigation |
|
|
320
323
|
| --- | --- | --- |
|
|
321
|
-
| Usage tokens absent (CONFIRMED, Gate B) | Cost/token display zeros on ACP |
|
|
324
|
+
| Usage tokens absent (CONFIRMED, Gate B) | Cost/token display zeros on ACP | ACCEPTED 2026-09-07 (user decision): Gate B no longer blocks the default flip - zero-usage is documented behavior on ACP. Both engines are permanently maintained; no deletion (standing decision), so zero-usage is opt-in per user forever (review 4, finding 2, as amended) |
|
|
322
325
|
| ~~No model/effort switch per session~~ RESOLVED: Gate A PASS | — | `session/set_config_option` verified live; per-session switching, no recycle |
|
|
323
326
|
| Slash commands expanded server-side | Could double-expand with our prompt assembly | Probe F.7. If present: keep our prefixes out of command-looking lines, or ignore server command list |
|
|
324
327
|
| `request_permission` with no pi-side permission UI | Cannot render a native dialog | Single `auto` policy (parity with `skipPermissions: true`); per-tool gating for pi tools belongs to the tools/extensions and is preserved end-to-end by G9 (9.3). Never hang |
|
|
@@ -463,7 +466,7 @@ src/acp/connection.ts process lifecycle: spawn AGY_ACP_BIN, initialize
|
|
|
463
466
|
/ load / prompt / cancel / set_config_option, client-side
|
|
464
467
|
method handlers (request_permission policy, fs, terminal),
|
|
465
468
|
outbound event queue.
|
|
466
|
-
src/acp/driver.ts AcpDriver: implements the
|
|
469
|
+
src/acp/driver.ts AcpDriver: implements the StreamDriver surface (section 9.2)
|
|
467
470
|
so provider.ts keeps working unchanged. State machine,
|
|
468
471
|
timers, parks, snapshot, close.
|
|
469
472
|
src/acp/events.ts session/update to DriverActivity mapping + stopReason
|
|
@@ -475,7 +478,7 @@ scripts/smoke-acp.mjs live smoke, gated by AGY_ACP_LIVE=1 (spends quota),
|
|
|
475
478
|
|
|
476
479
|
### 9.2 Driver contract (unchanged surface, additive only)
|
|
477
480
|
|
|
478
|
-
`AcpDriver` matches the existing `
|
|
481
|
+
`AcpDriver` matches the existing `StreamDriver` public surface: `state`,
|
|
479
482
|
`activeHandle`, `run()`, `reentry()`, `kickIdle()`, `set onTurnEnd()`,
|
|
480
483
|
`snapshot()`, `close()`. `DriverActivity` gains one additive variant; the
|
|
481
484
|
streaming engine never emits it:
|
|
@@ -490,8 +493,9 @@ streaming engine never emits it:
|
|
|
490
493
|
the current token-count behavior. One `if`, additive, streaming untouched.
|
|
491
494
|
|
|
492
495
|
Interface extraction (review 2, finding 7): `provider.ts` imports the
|
|
493
|
-
concrete `
|
|
494
|
-
the
|
|
496
|
+
concrete `StreamDriver` class today; without a neutral type the two engine
|
|
497
|
+
wirings would each drag the other's module in. Phase 1 extracts a
|
|
498
|
+
`TurnDriver` interface into a neutral module
|
|
495
499
|
(`src/driver-types.ts`); both drivers implement it; `provider.ts` and
|
|
496
500
|
`ToolRoundTrips` depend on the interface only. `/agy engine` changes require
|
|
497
501
|
a pi restart (driver wiring happens at extension load); a live engine router
|
|
@@ -771,21 +775,22 @@ Acceptance: parity suite remains 14/14, doctor parity, no breakage to stream-jso
|
|
|
771
775
|
|
|
772
776
|
Status: 🚧 Phase 3 remaining items are COMPLETE (2026-09-04): 168/168 tests,
|
|
773
777
|
tsc clean, live parity 14/14, embeddedContext verified live (resource block
|
|
774
|
-
with a secret word answered correctly).
|
|
775
|
-
|
|
776
|
-
|
|
778
|
+
with a secret word answered correctly). Phase-3 acceptance: nothing deletes
|
|
779
|
+
in phase 3 — the streaming modules stay (permanently, see the standing
|
|
780
|
+
decision at the top and Phase 4).
|
|
777
781
|
|
|
778
|
-
### Phase 4: default flip
|
|
782
|
+
### Phase 4: default flip (deferred)
|
|
779
783
|
|
|
780
784
|
All items below are deferred until a full soak cycle of both engines has completed and upstream conditions are met:
|
|
781
785
|
|
|
782
786
|
1. AskAntigravity migration to ACP one-shot (migrating while `stream-json` is default breaks streaming-only users who haven't onboarded ACP auth; streaming conversation ids cannot resume under ACP). `mode: "plan"` delegations keep the `agy -p --mode plan` path (committed exception).
|
|
783
787
|
2. Delete `src/discovery.ts` (`/proc` fd-scan) once AskAntigravity migration completes.
|
|
784
|
-
3. Default flip: `config.engine` default becomes `"acp"` after one full release soak cycle with both engines shipping. Gate A PASS is verified.
|
|
785
|
-
4. Upstream Gate B resolution: Google ships usage counters in ACP payloads.
|
|
786
|
-
|
|
788
|
+
3. Default flip: `config.engine` default becomes `"acp"` after one full release soak cycle with both engines shipping. Gate A PASS is verified. Gate B is NOT a precondition (lifted as a blocker 2026-09-07); the soft items in section 17 ship in the same release.
|
|
789
|
+
4. Upstream Gate B resolution (optional, informational): Google ships usage counters in ACP payloads. The `/agy doctor` watch reports it when it happens. Mapping it in is a small additive job; the streaming engine stays regardless.
|
|
790
|
+
|
|
791
|
+
NO deletion phase: the streaming engine is a permanently maintained peer (standing user decision, 2026-09-07). The old phase-4 "streaming deletion" item is void.
|
|
787
792
|
|
|
788
|
-
Acceptance: default-flip release ships with the parity suite as acceptance evidence
|
|
793
|
+
Acceptance: the default-flip release ships with the parity suite as acceptance evidence.
|
|
789
794
|
|
|
790
795
|
## 11. Test strategy
|
|
791
796
|
|
|
@@ -873,3 +878,63 @@ answers: model catalog ships in `session/new` (CLI catalog unnecessary on
|
|
|
873
878
|
ACP); edits surface as diffs inside `tool_call` content even with fs
|
|
874
879
|
capabilities off; no usage fields anywhere; available_commands_update carries
|
|
875
880
|
`plan` and `logout`; cold start ~5-6 s, steady RSS ~327 MB.
|
|
881
|
+
|
|
882
|
+
## 17. Default-flip readiness (phase 4) — analysis as of 2026-09-07
|
|
883
|
+
|
|
884
|
+
Standing analysis so nobody re-derives it: what blocks flipping the default
|
|
885
|
+
engine from stream-json to ACP. Re-verify only the dated facts (Gate B
|
|
886
|
+
status via `/agy doctor`); the structural conclusions hold.
|
|
887
|
+
|
|
888
|
+
**Verdict: nothing blocks the flip. Gate B was REMOVED as a blocker on
|
|
889
|
+
2026-09-07 (user decision: token usage does not matter for the extension's
|
|
890
|
+
purpose - agy runs on subscription quota, cost stays zero either way).
|
|
891
|
+
Zero-usage on ACP is accepted as documented behavior. Remaining before the
|
|
892
|
+
flip: the four soft items below, shipped in the same release.**
|
|
893
|
+
|
|
894
|
+
Already green:
|
|
895
|
+
|
|
896
|
+
- Parity contract (section 6) is ALL `[x]`, live-verified on both engines
|
|
897
|
+
(parity suite 14/14).
|
|
898
|
+
- Everything shipped since 1.4.9 is engine-aware: bridge registration is
|
|
899
|
+
ACP-native (`session/new` mcpServers) AND stream-json-native
|
|
900
|
+
(`~/.gemini/config/mcp_config.json`); tool-result images ride both engines
|
|
901
|
+
(probe-verified on each); the approval gate's ACP hook firing is the
|
|
902
|
+
LIVE-verified side (stream-json is docs-attested only), so the flip does
|
|
903
|
+
not weaken it.
|
|
904
|
+
- Rollback is one config flip; sessions are engine-scoped so bindings never
|
|
905
|
+
cross.
|
|
906
|
+
|
|
907
|
+
Former blocker — Gate B, LIFTED 2026-09-07:
|
|
908
|
+
|
|
909
|
+
- RC01 sends no usage/token fields in ANY payload, so ACP shows zero
|
|
910
|
+
tokens. This used to block the default flip; the user lifted it: agy
|
|
911
|
+
runs on subscription quota and cost is zero regardless, so the display
|
|
912
|
+
gap is cosmetic for this extension. Zero-usage on ACP is documented
|
|
913
|
+
behavior.
|
|
914
|
+
- Both engines are PERMANENTLY maintained (standing user decision
|
|
915
|
+
2026-09-07): no deletion phase exists, regardless of Gate B. stream-json
|
|
916
|
+
is the supported fallback/secondary forever; zero-usage is opt-in per
|
|
917
|
+
user by choosing the engine.
|
|
918
|
+
- The `/agy doctor` Gate B watch stays armed as INFORMATIONAL: it prints
|
|
919
|
+
"acp tokens: AVAILABLE" if upstream ever ships usage, at which point the
|
|
920
|
+
mapping is a small additive job.
|
|
921
|
+
|
|
922
|
+
Soft items to ship alongside the flip (not blockers):
|
|
923
|
+
|
|
924
|
+
1. Clean-machine first-run: ACP as DEFAULT means fresh installs hit the
|
|
925
|
+
self-setup path (binary install + auth bootstrap) immediately. Self-heal
|
|
926
|
+
exists; never tested as the first-run experience. Test once on a clean
|
|
927
|
+
env.
|
|
928
|
+
2. User-visible abort change: Esc on ACP = kill + reconnect + reload (RC01
|
|
929
|
+
has no `session/cancel`). Document in README and `/agy status`.
|
|
930
|
+
3. Pull soak evidence from the daily logs (warn rates per engine, 1.4.9+)
|
|
931
|
+
and attach to this section.
|
|
932
|
+
4. Note that `AskAntigravity` stays on `agy -p` regardless (phase 4+).
|
|
933
|
+
|
|
934
|
+
Mechanics of the flip (minutes): default in `src/config.ts` + the
|
|
935
|
+
`acp-config` test default + README engine table + AGENTS.md + beta wording.
|
|
936
|
+
`AGY_ENGINE` env override keeps an escape hatch either way.
|
|
937
|
+
|
|
938
|
+
Recommendation on record: Gate B is no longer a condition. Remaining
|
|
939
|
+
pre-flip work is the soft items above; the flip itself is a small,
|
|
940
|
+
mechanical change whenever the soak cycle is judged complete.
|
|
@@ -259,9 +259,10 @@ unreachable on RC01 — no cancel method).
|
|
|
259
259
|
|
|
260
260
|
NO usage/token fields appeared anywhere in `initialize`, `session/new`,
|
|
261
261
|
`set_config_option`, `agent_message_chunk`, prompt results, or tool flows
|
|
262
|
-
(run 6). Gate B FINAL: ABSENT on RC01. Consequence in the plan
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
(run 6). Gate B FINAL: ABSENT on RC01. Consequence in the plan (updated
|
|
263
|
+
2026-09-07): Gate B is INFORMATIONAL - zero-usage is documented and accepted
|
|
264
|
+
on ACP, never a blocker. Both engines are permanently maintained peers; no
|
|
265
|
+
deletion is planned.
|
|
265
266
|
|
|
266
267
|
## session/cancel
|
|
267
268
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -26,7 +26,11 @@ src/sessions.ts atomic JSON store: pi session -> agy conversation + waterm
|
|
|
26
26
|
src/config.ts persisted runtime config (engine + acp block, bridgeTools, digest, mode, permissions, model/thinking defaults)
|
|
27
27
|
src/daily-log.ts daily NDJSON support log (one file per day, 14-day retention, secret redaction, AGY_DEBUG verbose gate); fed by both drivers, the bridge, round-trips, /agy, and ask-tool
|
|
28
28
|
src/ask-tool.ts the AskAntigravity one-shot delegation tool (model/thinking defaults)
|
|
29
|
-
src/mcp-server.ts MCP tool bridge server: ferries tools/list + tools/call; calls park in the provider round-trip
|
|
29
|
+
src/mcp-server.ts MCP tool bridge server: ferries tools/list + tools/call; calls park in the provider round-trip. Also the approval park: POST /approval (ticket early-ack) + GET /approval/<id>, fail-closed on timeout/unwired/close
|
|
30
|
+
src/mcp-registration.ts registers/unregisters the bridge in ~/.gemini/config/mcp_config.json for the stream-json CLI (per-pid, atomic, stale sweep)
|
|
31
|
+
src/approval-gate.ts shadow tool factory (bash/write/edit): marker calls are ticket-verified approval round-trips, non-marker calls delegate; maps agy native tools onto the shadow surface
|
|
32
|
+
src/approval-detect.ts third-party pi permission-extension detection; resolves approvals.gateMode auto (off until a gate extension exists)
|
|
33
|
+
src/approval-hook.ts merge-safe .agents/hooks.json staging (PreToolUse) + generated 0600 early-ack/poll hook script; staged timeout exceeds the park budget (hook timeouts soft-pass)
|
|
30
34
|
src/diff-render.ts stream-json: render agy's file edits as git diffs in pi's thinking stream; formatInlineDiff (no git) renders ACP's native diffs
|
|
31
35
|
src/driver-types.ts TurnDriver contract shared by both engines (request/handle/snapshot types)
|
|
32
36
|
src/acp/jsonrpc.ts NDJSON JSON-RPC 2.0 framing with line buffering and typed error results
|
|
@@ -71,9 +75,10 @@ The pre-1.3.0 engine (spawn `agy -p`, poll the SQLite conversation DB, decode pr
|
|
|
71
75
|
|
|
72
76
|
`config.engine: "acp"` (or `/agy engine acp`) routes turns through Google's
|
|
73
77
|
official ACP server (`agy_acp_server.par`, registry id `antigravity-acp`)
|
|
74
|
-
over JSON-RPC stdio. Off by default; stream-json remains the default
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
over JSON-RPC stdio. Off by default; stream-json remains the default. BOTH
|
|
79
|
+
engines are permanently maintained peers (standing decision - no deletion,
|
|
80
|
+
regardless of Gate B). Gate B (absent usage fields) is informational:
|
|
81
|
+
zero-usage is documented on ACP. See docs/ACP-ADOPTION-PLAN.md section 17.
|
|
77
82
|
|
|
78
83
|
Modules: `src/acp/jsonrpc.ts` (framing/correlation), `src/acp/connection.ts`
|
|
79
84
|
(process + protocol methods + in-connection `auto` permission answering),
|
|
@@ -85,7 +90,9 @@ Phase-2/3 additions (all ACP-only, verified live):
|
|
|
85
90
|
|
|
86
91
|
- **Images**: pi image attachments ride as typed content blocks in the
|
|
87
92
|
prompt array; models advertise `input: ["text","image"]` only when the
|
|
88
|
-
engine is `acp` (decided at extension load). stream-json
|
|
93
|
+
engine is `acp` (decided at extension load). stream-json prompt input
|
|
94
|
+
stays text-only (tool-RESULT images ride both engines; see
|
|
95
|
+
PI-BRIDGE-GAPS).
|
|
89
96
|
- **Digest delivery**: with `config.digest` on, ACP ships the G1 digest as
|
|
90
97
|
a native `embeddedContext` resource block (images → resource → text);
|
|
91
98
|
stream-json keeps it inline. Same cache churn either way.
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -57,6 +57,18 @@ AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
|
57
57
|
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
58
58
|
npx tsx scripts/probe-acp-phase2.mjs
|
|
59
59
|
|
|
60
|
+
# Live probe: does the ACP server deliver MCP tool-result IMAGE content to
|
|
61
|
+
# the model? One bridge tool returns a two-tone PNG in its result; the model
|
|
62
|
+
# must name both halves from the tool result alone.
|
|
63
|
+
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
64
|
+
npx tsx scripts/probe-acp-image-result.mjs
|
|
65
|
+
|
|
66
|
+
# Live probe: same image question for the stream-json engine. AGY
|
|
67
|
+
# bridge tool returns a two-tone PNG in its result; model must name both
|
|
68
|
+
# halves. AGY_PROBE_REG_ONLY=1 skips the turn and dumps MCP registration
|
|
69
|
+
# state (no quota).
|
|
70
|
+
AGY_LIVE=1 npx tsx scripts/probe-stream-json-image.mjs
|
|
71
|
+
|
|
60
72
|
# Live parity run: the SAME scenario set (streaming, continuity, bridge
|
|
61
73
|
# round-trip, effort switch, serialization, abort+recover, usage) through
|
|
62
74
|
# BOTH engines. Needs the agy CLI AND the ACP binary. Spends ~13 flash-low
|
|
@@ -86,6 +98,10 @@ Most "stuck" reports trace to one of:
|
|
|
86
98
|
- `tests/acp-driver.test.ts` - the ACP driver over the fake server (`tests/helpers/fake-acp-server.mjs`, scenario-selected): happy flow, load-replay, permission auto-answer, Gate D abort (cancel probe, teardown, `cancelSupported` memory), the stale-exit race (a killed connection's late exit must not fail its replacement - `ACP_FAKE_SLOW_DEATH_MS`), auth errors, park/kickIdle timer pause with remaining budget.
|
|
87
99
|
- `tests/acp-config.test.ts` - engine selection narrowing (`AGY_ENGINE`/`config.engine`), acp block parsing.
|
|
88
100
|
- `tests/daily-log.test.ts` - the support log: day rotation, retention cutoff boundary, secret redaction (incl. header blocks), the 4 KB record cap, never-throw on a broken dir, and the two-tier gate (debug records dropped unless `AGY_DEBUG`).
|
|
101
|
+
- `tests/mcp-registration.test.ts` - the `~/.gemini/config/mcp_config.json` registration for the stream-json CLI: exact agy entry shape, foreign servers preserved, corrupt config refused, atomic writes, stale-entry sweep.
|
|
102
|
+
- `tests/provider-escalation.test.ts` - the early-ack + poll pipeline (escalation registry, poll views, late-delivery tombstones) and tool-result image forwarding on both engines.
|
|
103
|
+
- `tests/approval-gate.test.ts` - the shadow tool factory: marker calls never execute, ticket verification denies forged/stale markers before the policy, denials throw, native-to-shadow mapping.
|
|
104
|
+
- `tests/approval-park.test.ts` - the approval park end-to-end over a real (port 0) server: POST ticket early-ack, poll pending -> terminal, timeout deny, ungated/unwired deny, close fail-closed, provider round-trip (allow / block-deny / timeout), `__agy*` strip on G9 args.
|
|
89
105
|
|
|
90
106
|
## Module map
|
|
91
107
|
|
package/docs/PI-BRIDGE-GAPS.md
CHANGED
|
@@ -61,13 +61,34 @@ Weighed and rejected; kept so they are not re-proposed.
|
|
|
61
61
|
credentials, so agy already uses pi's creds for every tool; a
|
|
62
62
|
credential never crosses the bridge. A `pi_get_setting` accessor was
|
|
63
63
|
predicated on credential reuse that does not apply.
|
|
64
|
-
- **Image / binary content blocks over the bridge** —
|
|
65
|
-
|
|
64
|
+
- **Image / binary content blocks over the bridge** — DONE (ACP engine).
|
|
65
|
+
Reopened 2026-09-05: the prior verdict below was falsified. On the ACP
|
|
66
|
+
engine, native `view_file` rejects real filesystem paths (artifact sandbox;
|
|
67
|
+
the tool-priority note steers agy to bridge tools), and bridge `read`
|
|
68
|
+
flattened pi's tool result with `blocksToText`, which drops the image block.
|
|
69
|
+
agy received only the label text and fell back to shell + `mcp-cli-ent
|
|
70
|
+
ai-vision`. Probe `scripts/probe-acp-image-result.mjs` (2026-09-05) proved
|
|
71
|
+
the ACP server delivers MCP tool-result image content to the model (PASS:
|
|
72
|
+
the model identified a two-tone PNG from the tool result alone, with no
|
|
73
|
+
image in the prompt). Fix: image blocks in parked pi tool results now ride
|
|
74
|
+
bridge results as MCP image content on the ACP engine (fast resolve path,
|
|
75
|
+
escalation registry, and `bridge_poll_result`), so `read` on an image file
|
|
76
|
+
gives agy real pixels. DONE on stream-json too (probe
|
|
77
|
+
`scripts/probe-stream-json-image.mjs`, 2026-09-07: the CLI's MCP client
|
|
78
|
+
delivers tool-result image content to the model — two-tone PNG named from
|
|
79
|
+
the result alone, bridge tool called once, zero decoders in the frame
|
|
80
|
+
trail). Image blocks now ride parked pi tool results on both engines
|
|
81
|
+
(fast resolve path, escalation registry, and `bridge_poll_result`), so
|
|
82
|
+
`read` on an image file gives agy real pixels everywhere. Still
|
|
83
|
+
text-only, deliberately: the late-delivery prompt
|
|
84
|
+
(`buildLateResultPrompt`), and the stream-json prompt attachments.
|
|
85
|
+
Superseded verdict (kept for the record): NOT NEEDED. pi shares the path to
|
|
86
|
+
any image it produces (e.g. `/tmp/pi-clipboard-<uuid>.png`), and agy
|
|
66
87
|
reaches and reads those files directly via the bridge's `read` tool, so
|
|
67
88
|
returning image content blocks over the transport would duplicate a path
|
|
68
|
-
that already works end-to-end. No agy transport change or pi patch
|
|
69
|
-
Update (2026-09-04): user-provided image *attachments* now ride
|
|
70
|
-
the ACP engine as typed prompt content blocks (see README, Two
|
|
89
|
+
that already works end-to-end. No agy transport change or pi patch
|
|
90
|
+
required. Update (2026-09-04): user-provided image *attachments* now ride
|
|
91
|
+
natively on the ACP engine as typed prompt content blocks (see README, Two
|
|
71
92
|
engines); the stream-json CLI prompt stays text-only, and the bridge
|
|
72
93
|
direction above is unchanged.
|
|
73
94
|
- **File-watching / live state** — DECLINED. agy is request-response
|
package/docs/TODO.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# TODO
|
|
2
|
+
|
|
3
|
+
## 1. Approval gate: live end-to-end verification
|
|
4
|
+
|
|
5
|
+
The gate is wired and unit-pinned (304 tests) but has never run against a live
|
|
6
|
+
agy turn. Enable it, drive an agy turn that mutates a file, and watch the
|
|
7
|
+
round trip: PreToolUse hook -> POST /approval park -> shadow toolUse ->
|
|
8
|
+
decision -> hook stdout -> agy enforces.
|
|
9
|
+
|
|
10
|
+
- Enable without a third-party extension: `AGY_APPROVALS=shadow AGY_APPROVALS_MODE=ask` (interactive pi; headless denies). Deny path: a fake gate extension that blocks marker calls (`pi.on("tool_call")` + `{block: true, reason}`).
|
|
11
|
+
- Probe artifacts live outside the repo: `~/tmp/pi-antigravity-bridge-probes/` (run scripts via `npx tsx` from the repo cwd - they import src/*.ts).
|
|
12
|
+
- Live-behavior risks to watch: hook timeout soft-passes (V3) - the staged timeout must keep exceeding the park budget; denied calls emit no `tool_call` session/update frames on ACP (V2); edit-class arg names beyond `create_file` are docs-attested, never live-captured - check the confirm-dialog text on a real `run_command` and a real `replace_file_content`.
|
|
13
|
+
- On pass: clear the "NOT yet live-verified" notes (AGENTS.md, this file).
|
|
14
|
+
|
|
15
|
+
## 2. Explicit `antigravity_approve` variant (dedicated mode)
|
|
16
|
+
|
|
17
|
+
`approvals.gateMode: "dedicated"` currently stages the same shadow tools
|
|
18
|
+
(warn-logged remap). Planned: one registered tool `antigravity_approve` with
|
|
19
|
+
input `{toolName, args}`, for setups that prefer explicit names (gotgenes
|
|
20
|
+
`shellTools` alias users). Full v2 spec preserved in git history:
|
|
21
|
+
`dd7845b:docs/TODO.md` (sections 2.1-2.9).
|