Repository navigation
feat: Google Antigravity provider over ACP, with reusable ACP harness primitives - #371
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase 0/1 of the Antigravity ACP provider plan. - main/services/acp: process supervision (process groups, pid ledger), ACP SDK 1.7 connection with deadlines, workspace-confined fs callbacks, permission policy, loopback MCP bridge for Aiden tools, prompt reconstruction for pi-ai 1.0 transcripts, activity-to-timeline mapping, session store/resume, and a Pi provider wrapper. - main/services/antigravity: pinned 1.3.0 release table, launch definition with isolated GEMINI_HOME, model projection, protocol quirks. - Fake ACP agent fixture and behavioural suites (test:acp). - Phase 0 spike notes for Antigravity ACP 1.3.0. Adapted from pi-antigravity-acp-provider @ 07e369b and T3 Code @ f870c419fc (both MIT). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Continuation only consumes pending tool results; messages sent mid-turn stay unseen and reach the agent with the next prompt. - Abandoned bridged calls are resolved when the turn ends, so a late tool result cannot hang the next stream. - Bridged calls that arrive while no stream is attached are announced on the next stream instead of dropping the session. - A clean Stop keeps the agent session; only an agent that does not settle within the grace window is killed. - Kill the process group when the leader exits so helper processes do not outlive a crash. - Ask-mode writes require an approval for that path this turn (or an always-allow); network fetches need approval below Full. - Eviction re-checks busy state; buffered text is cleared per turn; failed discovery is attempted once per sign-in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vider registration Phase 2/3 of the Antigravity ACP provider plan. - acp/installer: pinned-release installer with free-space check, capped streaming download + SHA-256, exact two-member extraction (yauzl), live identity validation, atomic activation, leases and removal. - acp/launcher: per-process TMPDIR, pid ledger, BROWSER capture hook, crash sweep. - antigravity/auth: Google sign-in via captured authorization URL, strict URL/callback validation, paste-back fallback, ACP logout on sign-out. - antigravity/service + lazy provider registered as a desktop built-in (AIDEN_DISABLE_ANTIGRAVITY=1 hides it). Sign-out also clears the agent's own credentials. - providers:harness:* IPC and a runtime install section in the provider setup dialog (size/source disclosed before Install; progress; cancel; remove; sign-in disabled until installed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chat integration (plan phases 4-5): - acp/generation-host adapts a generation to the ACP host contract: approvals use Aiden's approval card (allow-for-this-chat maps to the agent's allow_always), agent questions use the structured question prompt, native activity becomes persisted timeline steps with new labels (delete/move/fetch/subagents/context rebuilt). - llm-client registers the host only for attended desktop chats (no Bots, Assistant, scheduled, Telegram or Remote-started runs) and skips Aiden's context trimming and compaction for agent-backed providers. - Aiden's own file/shell tools are not bridged; the agent uses its own. Review fixes: - Chats load install state themselves (first chat after restart works). - Remove runtime no longer disposes the runtime. - A permission downgrade the agent cannot honour natively cancels the continuation instead of resuming in auto-approve mode. - Messages sent mid-turn are answered in the same turn via a follow-up prompt; usage is summed; delivered messages are never mutated. - Installer sweeps interrupted staging, blocks lease/install during removal, and explains outdated runtimes; quit cancels installs. - BROWSER hook avoids paths with spaces and is rewritten per launch. - Allow-once write grants are single use; deletes/moves never grant unnamed writes. Logout always clears Pi's marker. - Runtime section: phase-only announcements, focus kept on remove confirm, progress label covers every phase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es; docs Surface gating (plan phase 6): one shared reason helper (acpHarnessUnavailableReason / isAcpHarnessProvider) applied to Bots (catalog + face studio), scheduled tasks (editor, pin/guardrail, store validation, execution), subagents (eligibility + worker), Aiden Remote model inventory and resolve, Telegram, chat titles (seed-only), side questions and advisor. The model picker labels agent-backed providers "· Agent". Review fixes: - Agent questions meet the renderer's question contract (bounded unique labels, non-empty descriptions) and answers map back exactly. - Scratch directory failures never strand a generation. - Text from a stopped or failed turn never leaks into the next reply. - Desktop approval cards receive offered scopes (pre-existing drop in the chat:approval forwarder), so "Allow for this chat" works. - Follow-ups are re-derived per continuation; tools discovered mid-turn are bridged immediately; installer sweep and service readiness are race/failure safe. Docs: AGENTS.md network posture for agent runtimes, docs/antigravity.md, plan status and index. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gating - A message sent mid-turn stays owed across further bridged tool calls and is sent as a follow-up prompt containing only the user's messages. - Unattended surfaces never inherit an agent-backed last-used provider: scheduled tasks (accurate error for unpinned tasks), the schedule tool's app default, Telegram, and dictation cleanup. - The Assistant dock treats an agent-backed selection as not ready; the advisor never offers agent-backed candidates. - The scratch-directory fallback is a private mkdtemp directory. - Tests: approval scope forwarding to the desktop card, owed follow-ups across tool calls, no post-Stop text leakage, fallback helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- An owed image for an agent without image input is sent as a short text note instead of being dropped; counts commit either way. - The scratch-directory fallback is created once per chat, so a failure does not rebuild the agent session every turn. - Test: a message owed when the turn stops is delivered exactly once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
The new file-access path bypasses the existing secret-file policy and can overwrite files outside the workspace after a symlink swap. Sign-out also leaves some agent processes outside its cleanup boundary; these need fixing before merge.
Reviewed changes Full review of the ACP harness and Antigravity provider, including the follow-up commit that landed during this review.
- ACP infrastructure: Process supervision, transport deadlines, pinned installation, runtime leases, private launch environments and crash recovery.
- Agent chat integration: Session resume/reconstruction, Pi streaming, MCP tool continuations, filesystem callbacks, permission approvals, questions and persisted activity.
- Antigravity setup: Google sign-in, isolated credentials, manual catalog discovery and effort-tier model projection.
- Desktop surfaces: Runtime install/update/remove UI, Agent picker labels and approval-scope forwarding.
- Surface eligibility: Restrictions across Bots, schedules, Remote, Telegram, subagents, Assistant, advisor, side questions and auxiliary inference.
- Verification: Latest-head
test:acppassed 111/111, five related behavioral suites passed 83/83, and TypeScript checks passed. Synthetic probes reproduced the five inline findings; real signed-in and packaged macOS acceptance remain unverified.
gpt-6.1-sol | 𝕏
Hermes Review BotConfidence: 5 Engine: SummaryThis pull request introduces the Google Antigravity provider implemented over the Agent Control Protocol (ACP), supported by reusable, process-isolated ACP harness primitives in Confidence Score: 5/5Full end-to-end trace completed across process management, credential confinement, native file descriptor verification, MCP bridge routing, session reconstruction, and UI configuration. The implementation strictly complies with repository architectural rules, security boundaries, and surface gating. 📁 Important Files Changed
FindingsNo findings. Sequence DiagramsequenceDiagram
autonumber
actor User
participant Renderer as Desktop UI
participant LLMClient as main/services/llm-client
participant Runtime as AcpHarnessRuntime
participant Subproc as Antigravity Process
participant Bridge as MCP Loopback Bridge
participant Files as ClientFiles Confinement
User->>Renderer: Send prompt in desktop chat
Renderer->>LLMClient: streamCompletion(messages, model)
LLMClient->>Runtime: generateTurn(session, prompt, tools)
Runtime->>Subproc: prompt(turnContext)
rect rgb(240, 245, 255)
note over Subproc,Bridge: Agent tool call execution
Subproc->>Bridge: tools/call (e.g. read_file / bash)
alt Internal Aiden Tool
Bridge->>Runtime: onBridgeCall(name, args)
Runtime->>Files: executeSandboxed(args)
Files-->>Runtime: confinedResult
Runtime-->>Bridge: continueTurn(result)
Bridge-->>Subproc: Tool call response
else Agent Filesystem Action (create/modify)
Subproc->>Runtime: requestPermission(path, op)
Runtime->>Renderer: Prompt user for approval
Renderer-->>Runtime: Allow / Deny
Runtime-->>Subproc: Permission response
end
end
Subproc-->>Runtime: text / turnCompletion
Runtime-->>LLMClient: Stream chunks & tool activity
LLMClient-->>Renderer: Render turn in transcript
[]
|
…uncation, timeouts) - fs callbacks keep Aiden's .env/.env.* read exclusion (also through symlink aliases; .env.example stays readable). - Reads and writes go through a descriptor opened with O_NOFOLLOW (new files with O_EXCL); identity and confinement are re-verified before any byte is read or written, so a symlink or parent swap after validation is refused instead of followed. - Sign-out closes launch admission, stops chat sessions and short-lived catalog processes, then logs out and clears credentials before reopening. - Reconstruction truncates only history; Aiden's instructions and the untrusted/no-repeat framing always reach the agent. - A bridged tool that outlives its timeout cancels the agent's turn, so a late result starts a clean prompt instead of mixing two replies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Two race conditions remain in the new sign-out and filesystem-safety fixes: pending catalog launches are not drained, and missing-file creation can escape through a replaced parent directory.
Reviewed changes Incremental review of 9741b160 against the prior Pullfrog review at 3dfa86ee.
- Hardened ACP file access: Reused the parent
.envexclusion and added descriptor identity checks and no-follow opens. - Fenced sign-out: Added launch admission closure and ownership of short-lived catalog processes before credential removal.
- Preserved prompt framing: Separated history truncation from host instructions and continuity warnings.
- Cancelled timed-out bridge turns: Prevented abandoned ACP response text from mixing into a late tool-result reply.
- Verified behavior: Passed 115 ACP tests, 56 parent coding-tool tests and TypeScript checks after syncing dependencies; deterministic probes reproduced both inline findings. Recorded the process-group test's initial failure and passing single rerun in the PR description. Live signed-in and packaged macOS acceptance remain unverified.
gpt-6.1-sol | 𝕏
- Every launch (chat and catalog) is tracked from admission until its process is disposed; sign-out disposes and waits for launches that were still starting, so none survives into the next account. - New files created through fs/write_text_file are anchored to directory identities: macOS uses a new `create` command in Aiden's packaged worktree file helper (openat/mkdirat, O_NOFOLLOW, O_EXCL); Linux walks /proc/self/fd. A parent swapped after validation can no longer redirect creation outside the folder. - Tests: in-flight catalog launch drained by sign-out; parent swapped right before creation leaves the outside directory untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
The new file-creation path still permits creation outside the workspace when an ancestor of the workspace root is substituted before root acquisition.
Reviewed changes Incremental review of eb0c020e against the prior Pullfrog review at 9741b160, with the full PR diff read for context.
- Drained starting launches: Tracked launches before awaiting the launcher and retained catalog ownership through completed disposal, so sign-out joins pending catalog work.
- Anchored descendant creation: Added descriptor-relative directory traversal on Linux and a native
createcommand on macOS, plus a descendant-symlink regression test. - Verified focused behavior: Passed 35 filesystem/runtime tests, 26 infrastructure/Antigravity tests and TypeScript checks; deterministic probes confirmed the root-acquisition finding below. The full ACP attempt timed out after two failures that passed their single focused reruns; the receipt is recorded in the PR description. Native macOS execution and live signed-in acceptance remain unverified.
gpt-6.1-sol | 𝕏
The chat host captures the folder's canonical path, device and inode once when the turn starts. File callbacks use a captured root only while its path still names that directory, so swapping an ancestor cannot move reads or writes elsewhere. New-file creation reaches the root by a no-follow walk from "/" (native helper on macOS, /proc/self/fd on Linux) and checks the captured identity before creating anything. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Failed folder-identity capture silently restores pathname-based authority, allowing later ACP callbacks to read or write outside the selected folder.
Reviewed changes Incremental review of c57fe5fa against the prior Pullfrog review at eb0c020e, with the full PR diff read for context.
- Captured turn-start folder identities: Added canonical path/device/inode roots to the generation host and adapted activity-path projection.
- Anchored initial root acquisition: Added Linux no-follow traversal from
/with descriptor identity checks and reused the captured identity for macOS creation. - Extended replacement coverage: Added an ancestor-swap test covering reads, existing-file writes and new-file creation.
- Verified focused behavior: Passed 50 filesystem, host, activity and runtime tests plus TypeScript checks after syncing dependencies. A deterministic probe confirmed the successful-capture fix and reproduced the capture-failure finding inline; native macOS execution and live signed-in acceptance remain unverified. The full ACP suite was not rerun for this delta; earlier flaky/hanging-suite receipts remain recorded in the PR description.
gpt-6.1-sol | 𝕏
If the folder identity cannot be captured when the turn starts, the agent gets no file roots for that turn instead of falling back to the mutable folder pathname. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Incremental review of f6dcc993 against the prior Pullfrog review at c57fe5fa, with the full PR diff read for context.
- Removed pathname fallback: Required the captured turn-start folder identity for ACP file access; failed capture now grants no filesystem roots.
- Logged capture failures: Recorded when folder identity capture fails and file access is disabled for that turn.
- Extended host coverage: Added the missing-identity assertion and supplied an explicit identity for the normal-access fixture.
- Verified behavior: Passed 50 focused filesystem, generation-host, activity and runtime tests plus TypeScript checks after syncing dependencies. A deterministic probe through the real host and callbacks confirmed that failed capture followed by ancestor replacement refuses reads, overwrites and new-file creation without touching outside files, while valid captured roots retain normal access. Native macOS execution and live signed-in acceptance remain unverified; earlier full-suite flaky/hanging receipts remain recorded in the PR description.
gpt-6.1-sol | 𝕏
Pullfrog's runs recorded intermittent failures in the process-group test and the Stop tests. Both were timing assumptions: - Stop tests aborted after a fixed delay that could land before the prompt reached the agent on a slow machine; they now wait for the agent's own prompt log entry. - The process-group test treated a killed-but-unreaped grandchild (zombie) as alive; it now polls until the process is gone or a zombie. - The bridge-timeout test waits for the agent's cancel instead of a clock. Verified with three sequential full runs and three concurrent runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Incremental review of 9b2687b1 against the prior Pullfrog review at f6dcc993, with the full PR diff read for context.
- Replaced startup sleeps: Synchronized four Stop/eviction tests with the fake agent's prompt log while preserving cancellation, session-reuse and late-text assertions.
- Replaced bridge-timeout delay: Waited for the agent's cancel event before delivering the late tool result.
- Corrected process liveness checks: Distinguished a killed, unreaped zombie from a running grandchild, using bounded polling rather than a fixed post-shutdown sleep.
- Verified local checks: Passed all 118 ACP tests on the first attempt, TypeScript checks and focused ESLint after synchronizing dependencies with the PR lockfile. This test-only delta does not change production behavior; native macOS and live signed-in acceptance remain unverified.
gpt-6.1-sol | 𝕏
very-hermes-bot
left a comment
There was a problem hiding this comment.
Inline review — 1 finding(s) anchored to the diff. See the pinned summary comment for the overview.
An idle agent process between turns could read the chat's files through the host captured at session creation. Reads now require a running turn and its host. Test: a read the agent attempts after its turn ended is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Incremental review of 31eb003e against the prior Pullfrog review at 9b2687b1, with the full PR diff read for context.
- Restricted file reads: Removed the creation-host fallback and required an active turn and attached host before granting ACP file-read access.
- Covered idle callbacks: Added a fake-agent delayed read and a runtime test confirming that reads between turns are refused.
- Verified behavior: Passed all 119 ACP tests on the first attempt, TypeScript checks and focused ESLint after synchronizing dependencies. A separate transport probe confirmed active reads still succeed before and after an idle interval using the same process; live signed-in Antigravity and packaged macOS acceptance remain unverified.
gpt-6.1-sol | 𝕏

Summary
Adds Google Antigravity as a provider that Aiden drives over the Agent Client Protocol (ACP). It is built on shared ACP harness primitives, so other ACP agents can be added later with one definition plus a sign-in flow.
main/services/acp/(harness-agnostic):TMPDIR.fs/read_text_fileandfs/write_text_file, enforced by Aiden.BROWSERcapture hook.main/services/antigravity/:GEMINI_HOMEprofile with file-based tokens;~/.geminiis never touched.AGENTS.md: the runtime downloads only after you click Install; there are no background checks or remote manifests; the agent starts only for sign-in, an explicit refresh, or a chat turn.chat:approvalforwarder now passes offeredscopesto the desktop approval card. They were dropped before, so "Allow for this chat" and "Always allow" (feat(approvals): once, this chat and always tool approval scopes #273) never appeared on desktop.References
zacbemis/pi-antigravity-acp-provider@07e369b(MIT).f870c419fc(MIT).docs/plans/antigravity-acp-provider-plan.md. Spike notes:docs/plans/antigravity-acp-spike.md. User guide:docs/antigravity.md.Review process
Each phase was reviewed by a fresh subagent, and every finding was fixed before the next phase. Rounds:
Test plan
npm run test:acp: 118 behavioural tests driving a protocol-faithful fake ACP agent through the real process and connection stack. They cover:node scripts/run-ci-tests.mjs --lane runtime --lane core --lane renderer: 675 files, plus the preserved native, browser and CLI suites.npx tsc --noEmit,eslint, IPC contract, main runtime dependencies, CI registry.GEMINI_HOMEisolation,BROWSERURL capture, negligibleTMPDIRuse.fs/write_text_file;modelandmodeconfig options;session/resume;🤖 Generated with Claude Code
Local review validation
At
9741b160,test:acppassed 115/115 after syncing the PR lockfile withnpm ci --ignore-scripts;coding-tools.test.tspassed 56/56 andnpx tsc --noEmitpassed. The initialtest:acpattempt also failedmain/services/acp/infrastructure.test.ts:73, "closing a process stops its whole group, including children that ignore TERM", withAssertionError: Missing expected exceptionat line 93 (process.kill(grandchild, 0)still succeeded after shutdown). This spec passed on the single rerun; the failure remains recorded rather than dismissed: review workflow run.At
eb0c020e, afternpm ci --ignore-scripts, the fullnpm run test:acpattempt reported failures inmain/services/acp/infrastructure.test.ts:73("closing a process stops its whole group, including children that ignore TERM") andmain/services/acp/runtime.test.ts:373("after a clean Stop the same agent session continues"), then timed out at 120 seconds before printing the final assertion diagnostics. Each failed spec passed its one focused rerun; this is a flaky/hanging-suite receipt, not a clean full-suite result. The focused filesystem/runtime suites passed 35/35, infrastructure/Antigravity suites passed 26/26, andnpx tsc --noEmitpassed. Review workflow run.Flake follow-up (
9b2687b1): both recorded intermittent specs were timing assumptions in the tests, and both are now fixed:Verified with three sequential full
test:acpruns (118/118 each) and three concurrent runs of the runtime and infrastructure suites.Mobile CI failures on
31eb003e(run 37579573421). This PR changes noios/orandroid/files. All four specs passed on the single rerun of the failed jobs, so they are intermittent mobile-environment failures that should be tracked separately.RootViewPicker$RootViewWithoutFocusException, because the emulator window never gained focus:AidenChatProgressUiTest.nestedAgentBackRestoresParentThenRosterAfterRecreationAidenChatProgressUiTest.chatInspectorOwnerRestoresAfterDelayedNegotiationAndRosterHydrationFBSOpenApplicationServiceErrorDomainRequestDenied). Two specs then failed:AidenChatTests.testChatOpenFetchesTheProgressSnapshotOnceAndReloadsDoNotDuplicateItAidenNativeIntegrationTests.testFreshManagerReconcilesPersistedActivityThroughAuthenticatedClientgpt-6.1-sol| 𝕏