feat(agent): add Antigravity (agy) CLI agent - #1287
Conversation
Adds AntigravityAgent (Agent + HookSupport surface), registry constants, camelCase stdin/stdout types for the five Antigravity hook events (PreToolUse, PostToolUse, PreInvocation, PostInvocation, Stop), transcript JSONL passthrough via shared agent.ChunkJSONL helpers, GenerateText for summary-provider integration, and a DiscoverReviewSkills stub. Layout matches docs/architecture/agent-guide.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: b1371f1a4c7c
Writes .agents/hooks.json with five event handlers and translates Antigravity's PreToolUse/PostToolUse/PreInvocation/PostInvocation/Stop into Entire's normalized lifecycle events. PreInvocation always emits TurnStart; the framework's idempotent strategy.InitializeSession (cli/lifecycle.go:406) handles first-arrival state creation. Stop with fullyIdle=false returns nil to avoid finalizing while background tasks run. Also restores two //nolint:ireturn directives removed in Chunk 1 that were blocking golangci-lint on NewCommittedReader and committedCheckpointStore. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 6e0dacb51f81
End-to-end integration test drives the five Antigravity hook events (pre-invocation, pre-tool-use, post-tool-use, post-invocation, stop) via synthetic stdin payloads against a real git repo. Verifies session state lazy-inits on first PreInvocation, write_to_file PreToolUse populates state.FilesTouched, and stop with fullyIdle=true completes the SessionEnd flow cleanly. Documents the real Antigravity 2.0 transcript layout in transcript.go (~/.gemini/antigravity-cli/brain/<conv-id>/.system_generated/logs/transcript.jsonl with a step_index/source/type/status/created_at/content/tool_calls schema) based on a captured fixture. The on-disk decoder remains deferred per the deferred-table; v1 ships only the JSONL passthrough. Drops the dead .gemini/jetski/ branch from DetectPresence since agy stores runtime data user-scope, not workspace-scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: a422980bd082
Adds the e2e/agents/Antigravity runner so the existing agent-agnostic test suite (clean, disable, doctor, attach, resume, rewind, explain, interactive, multi_session, edge_cases) automatically parameterizes over antigravity via ForEachAgent when E2E_AGENT=antigravity. Mirrors the droid/gemini patterns: -p prompt flag, --dangerously-skip-permissions, tmux-backed StartSession. PromptPattern is a placeholder (`>`); the real interactive prompt pattern will be observed and refined once `agy --print` is reliable. Antigravity-specific test cases (hook-config-location, first-prompt checkpoint, rewind) are deferred to the same follow-up since they require a working interactive agy session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 3b02d2cbf01a
Real-agy smoke testing showed our PreInvocation gate inverted: agy 1.0.0 ships invocationNum 0-indexed, so the actual first model call carries invocationNum=0 and the follow-up carries invocationNum=1. The old `!= 1` gate dropped the real turn-start and re-fired TurnStart on the follow-up, clobbering preState after tool calls had already mutated files — surfacing as "no files modified during session, skipping checkpoint" at commit time. Captured wire format: PreInvocation #1: {"invocationNum":0,"initialNumSteps":1,...} ← turn start PreInvocation #2: {"invocationNum":1,"initialNumSteps":5,...} ← follow-up The gate is now `invocationNum != 0`. Test fixtures (synthesized payload in lifecycle_test, captured fixture in testdata, integration test in integration_test) all updated to mirror the real wire shape so the test pyramid no longer agrees with the wrong invariant. transcript.go has a gofmt-only reformat of an existing doc comment. Verified end-to-end against real agy: shadow branch created, files_touched captured, `Entire-Checkpoint: <hex>` trailer appears on `git commit`, matching `Checkpoint: <hex>` lands on entire/checkpoints/v1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Entire-Checkpoint: 7bfaeb05bf4d
There was a problem hiding this comment.
Pull request overview
Adds first-class preview support for the Antigravity (agy) CLI agent, wiring it into Entire’s agent registry, hook handling, transcript lifecycle, text generation, integration tests, and optional E2E coverage.
Changes:
- Introduces a new
agent/antigravitypackage with identity, hook install/uninstall, lifecycle parsing, transcript handling, text generation, and discovery stubs. - Registers Antigravity in hook routing, agent constants, tests, and E2E agent support.
- Adds fixtures and unit/integration coverage for Antigravity hook payloads, lifecycle behavior, hook config management, and transcript preparation.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
e2e/agents/antigravity.go |
Adds E2E runner support for agy. |
e2e/agents/antigravity_test.go |
Adds basic E2E agent identity tests. |
cmd/entire/cli/integration_test/antigravity_test.go |
Adds integration coverage for Antigravity hook flow. |
cmd/entire/cli/hooks_cmd.go |
Registers Antigravity hooks command package. |
cmd/entire/cli/agent/registry.go |
Adds Antigravity agent name/type constants. |
cmd/entire/cli/agent/generate_external_test.go |
Adds Antigravity text generation test coverage. |
cmd/entire/cli/agent/antigravity/antigravity.go |
Defines Antigravity agent identity and core methods. |
cmd/entire/cli/agent/antigravity/antigravity_test.go |
Tests agent registration, interfaces, and presence detection. |
cmd/entire/cli/agent/antigravity/discovery.go |
Adds review skill discovery stub. |
cmd/entire/cli/agent/antigravity/generate.go |
Adds non-interactive agy text generation. |
cmd/entire/cli/agent/antigravity/hooks.go |
Adds .agents/hooks.json install/uninstall/status handling. |
cmd/entire/cli/agent/antigravity/hooks_test.go |
Tests hook config installation behavior. |
cmd/entire/cli/agent/antigravity/lifecycle.go |
Maps Antigravity hook payloads to Entire lifecycle events. |
cmd/entire/cli/agent/antigravity/lifecycle_test.go |
Tests lifecycle parsing and file extraction edge cases. |
cmd/entire/cli/agent/antigravity/transcript.go |
Adds JSONL transcript read/chunk/reassemble and preparation. |
cmd/entire/cli/agent/antigravity/transcript_test.go |
Tests transcript round-trip and placeholder creation. |
cmd/entire/cli/agent/antigravity/types.go |
Defines Antigravity hook payload/config types. |
cmd/entire/cli/agent/antigravity/types_test.go |
Tests fixture decoding for hook payload types. |
cmd/entire/cli/agent/antigravity/testdata/hook_stdin_pre_invocation.json |
Adds PreInvocation fixture. |
cmd/entire/cli/agent/antigravity/testdata/hook_stdin_post_invocation.json |
Adds PostInvocation fixture. |
cmd/entire/cli/agent/antigravity/testdata/hook_stdin_pre_tool_use.json |
Adds PreToolUse fixture. |
cmd/entire/cli/agent/antigravity/testdata/hook_stdin_post_tool_use.json |
Adds PostToolUse fixture. |
cmd/entire/cli/agent/antigravity/testdata/hook_stdin_stop.json |
Adds Stop fixture. |
cmd/entire/cli/agent/antigravity/testdata/transcript_sample.jsonl |
Adds sample Antigravity JSONL transcript fixture. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f141838. Configure here.
Three correctness fixes surfaced by Copilot and Cursor Bugbot review: 1. Register antigravity in summaryProviderBinaries. The GenerateText implementation in cmd/entire/cli/agent/antigravity/generate.go was dead code because IsSummaryCLIAvailable filtered antigravity out even when `agy` was installed on PATH. Adding the map entry makes `entire explain` and summary-provider selection see it. Matches the pattern for the other five agents that ship a generate.go. 2. resolveAgySymlinks now walks up to the deepest existing ancestor. The previous implementation only EvalSymlinks'd the immediate parent and silently returned the unresolved path if that parent didn't exist — which fires the moment agy creates a file inside a new nested directory (e.g. /tmp/repo/newdir/file.txt). The unresolved path then gets filtered as "outside repo" on macOS via the /tmp → /private/tmp symlink, silently breaking files_touched capture. Added two regression tests: one for the new-nested-dir case, one pinning the "no resolvable ancestor → return input" fallback. 3. Filter HOME before appending the test-home override in antigravityPromptEnv. The previous code appended HOME=... to an env that already contained HOME, and getenv returns the first match — so agy ran under the user's real home, defeating E2E test isolation. Mirrors codex.go's filtering of CODEX_HOME and pi.go's filtering of PI_CODING_AGENT_DIR. Two further bot comments about hooks.go install/uninstall over-eagerly owning the "entire" top-level key in .agents/hooks.json are skipped intentionally: by convention "entire" IS our bucket name, and the idempotency comparison in InstallHooks already protects against clobbering an identical config. Other agents (claude-code, gemini-cli) use a per-handler `entire-` prefix model because their hook schema is a flat array; antigravity's nested top-level-bucket schema is sufficiently different that adopting the prefix dance would add complexity without a real-world payoff. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Entire-Checkpoint: 58eff1cb1cf5
Three issues prevented `mise run test:e2e --agent antigravity` from actually exercising the integration: 1. Drop `--model gemini-2.5-flash`. agy 1.0.2 has no --model flag, so passing it made agy exit 2 with "flags provided but not defined". Model selection lives in settings.json; tests accept agy's default for now. 2. Drop HOME isolation. Pointing HOME at a fresh per-test dir stranded agy's auth, install id, and onboarding state under HOME/.gemini/, causing agy to re-trigger the browser auth flow on every run. Selective symlink-seeding chases a moving target as agy adds new state files. Sharing the real HOME lets agy authenticate; the test repo (cmd.Dir) still scopes workspace mutations. CI will need a proper HOME-isolation surface (or a dedicated test account) before the real-agy suite is wired into CI — out of scope here. 3. Pass `--add-dir <dir>` in print mode. Without it, agy ignores cwd and falls back to ~/.gemini/antigravity-cli/scratch/ — it init'd a brand-new git repo there and committed the test file there while the actual test repo stayed empty. Validated locally: a 14.8s real-agy run of TestSingleSessionAgentCommitInTurn now passes (hooks fire, files_touched captured, checkpoint advances on user commit). Entire-Checkpoint: 6a895268cec9
Adds two components that let entire capture agy token usage — the only surface where agy exposes token data is the JSON payload it pipes to the user-configured title/statusline command on every agent state change. Task 1 — Snapshot store (statusline.go / statusline_test.go): - AppendStatusSnapshot() parses the agy state JSON, deduplicates against the last persisted line (by compact-remarshaling the context_window), and appends a timestamped JSONL line to <ENTIRE_ANTIGRAVITY_STATUS_DIR|XDG_CACHE>/entire/antigravity/status/<conv_id>.jsonl. - Silently ignores malformed/incomplete payloads; only genuine I/O errors propagate. - Dedup reads only the last line of the file (seek-free linear scan) for O(file-size) worst-case but O(1) typical-case performance. - Prunes stale files (>14d) only when a new conversation file is first created, keeping the hot path to a single open+write. Task 2 — title-tee shim (hooks_antigravity_title.go / _test.go): - `entire hooks antigravity title-tee [--wrap '<cmd>']` reads stdin, calls AppendStatusSnapshot (best-effort), then optionally chains the user's original title command via sh -c so their window title is preserved. - Never exits non-zero; never writes noise to stdout (agy renders stdout verbatim as the terminal window title). - Registered on the antigravity hooks subtree, not through executeAgentHook, so it works outside git repos and without entire being enabled. Perf numbers (Apple M4 Pro, arm64, macOS 25.3): - End-to-end shim: 20-run warm avg = 41ms (budget ≤50ms); total = 830ms (budget ≤1000ms). - BenchmarkAppendStatusSnapshot_GrownFile (500-line file, dedup path, 100x): ~79µs/op (budget ≤2ms/op). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lDev + comments Addresses PR #1356 review (Cursor Bugbot + Copilot): - InstallHooks now runs InstallTitleTee BEFORE the repo-hooks idempotency early-return, so re-running setup repairs a missing/stale global title slot (upgrade, failed first install, or 'agent add' without --force). Regression test added. - localDev title command bakes the absolute main.go path at install time instead of a runtime $(git rev-parse) that would resolve against the wrong repo (the title slot is global). Falls back to the PATH form if unresolved. - Fix shellSingleQuote doc comment (stray curly quote) and the dedup comment to accurately describe the whole-file streaming read. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… comments) - condensation: gate out-of-band token fallback on AsOutOfBandTokenSource (purpose-built capability) instead of the !AsTokenCalculator inverse, so only OOB agents inherit accumulated SessionState.TokenUsage; add a negative-branch test proving a non-OOB agent (Cursor) does not. - title-tee: log a debug breadcrumb on AppendStatusSnapshot failure instead of discarding the error; contract unchanged (no stdout, returns nil). - comments: correct readLastContextWindow doc (streams the file), reframe AsOutOfBandTokenSource exclusion rationale, note sh -c wrap is the user's own settings.json command (not an injection surface). - lifecycle: use slog.String for the OOB warn log to match the file's local convention. - tests: current_usage change is not deduped; --wrap path still captures the snapshot; delta is zero (nil) when baseline is the latest snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test-auditor pass: - Remove TestTitleTee_WrapPipesPayloadThrough — a strict subset of TestTitleTee_WrapStillCapturesSnapshot (which makes the same passthrough assertion plus the snapshot-capture check). Zero coverage lost. - Rewrite TestCalculateTokenUsageSince_ClampsWhenTotalsGoBackwards to assert usage == nil directly (the actual all-zero path) instead of guarded conditionals that never executed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…T steps Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fixture Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion is implemented Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on for late-flush agents Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…file extraction) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n dedup in TranscriptAnalyzer
…n commit checkpointing - GetSessionDir/ResolveSessionFile compute the real agy brain-dir transcript path (~/.gemini/antigravity-cli/brain/<id>/.system_generated/logs/ transcript_full.jsonl) instead of returning empty, with a test-override env for isolation. - Implement WriteSession (was a no-op) with validation so restore/rewind can materialise transcripts. - Add USER_INPUT prompt extraction and PrepareTranscript to handle agy's asynchronous transcript write (briefly wait, then placeholder) before the framework's fileExists check, so Stop does not exit 1 and kill the turn. - Skip the redundant TurnEnd checkpoint when a mid-turn commit already condensed all tracked files (agy fires Stop after PostCommit). Verified offline against 376 real agy transcripts (0 parse errors) plus unit and integration tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1b5319f to
dd95db0
Compare
- Tolerate an empty live transcript at condensation instead of hard-erroring: agy writes its transcript after the Stop hook, so a first-turn mid-turn commit condenses against the empty placeholder. Erroring stranded the already-stamped Entire-Checkpoint trailer (commit referencing a checkpoint that never got written). Degrade to a files/prompt-only checkpoint like the shadow-branch path. - Replace the agy-specific TurnEnd skip guard with general committed-state filtering: relNewFiles now go through filterToUncommittedFiles and deletions through a new filterToUncommittedDeletions, so a Stop after a mid-turn commit skips naturally (totalChanges==0) while genuinely uncommitted late work (e.g. files created via shell after the commit) still gets checkpointed instead of being silently dropped. - Don't suppress the conditional TurnStart for stuck-ACTIVE sessions: a crashed conversation (Stop never fired) stayed ACTIVE and suppressed every resume, running it untracked. Reuse session.IsStuckActive. - Align countTranscriptItems with agy's readers (non-blank line counting) so CheckpointTranscriptStart offsets can't drift across blank lines. - Add the missing Antigravity case to generateSummary's agent switch — agy checkpoints never got auto-summaries despite agy being a summary provider. - Document the mid-turn token-scoping limitation at the OOB fallback gate. Integration pins: mid-turn commit with unwritten transcript still condenses (trailer references a real checkpoint); Stop after mid-turn commit checkpoints late shell-created files; the existing no-extra-shadow-branch test still holds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Stop installing PostToolUse/PostInvocation hooks: neither maps to a lifecycle event, so every completed tool call and model invocation spawned an `entire` subprocess that did nothing. HookNames/ParseHookEvent drop the verbs (unknown names still parse to a nil event, so stale hooks.json entries cannot fail an agy turn) and InstallHooks replaces the whole "entire" entry, so existing installs self-heal on the next enable. The HookConfig struct keeps the event fields for round-trip fidelity and idempotency detection. - Delete never-referenced hook output types (PreToolUseOutput, InvocationOutput, InjectStep, StopOutput) — the integration never writes a hook response by design. - Trim payload structs to the fields actually consumed (conversationId, transcriptPath, toolCall, invocationNum, fullyIdle); the fixtures still carry agy's full documented payloads so unknown-field tolerance stays pinned. - Deduplicate the JSON map writers (hooks.json / global agy settings.json) into writeJSONMapFile; AppendStatusSnapshot now uses statusFilePath instead of re-joining the path inline. - Comment accuracy: agy docs now state invocationNum is 0-indexed (drop the "despite the docs" claim); fix the transcript.go header to name transcript_full.jsonl (what the hook payload actually sends). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CLAUDE.md (and AGENTS.md symlink): add Antigravity to the agent list and the E2E agent enumerations/examples. - docs/architecture/agent-guide.md: add antigravity to the AgentName/AgentType registry lists and a new "Antigravity (agy) Wire-Format Quirks" pitfalls section (0-indexed invocationNum, transcript written after Stop, double-encoded tool args, title/statusline-only token surface, no SessionStart, deliberately-uninstalled post hooks). - docs/architecture/agent-integration-checklist.md: add agy to the canonical export and file-based WriteSession agent lists. - e2e: register antigravity in the workflow dispatch options with agy install + ADC secret plumbing, mise task usage/timeout defaults, and README docs. Deliberately NOT in the default all-agents matrix (runs on push to main): agy has no API-key auth and its cloudcode-pa backend is entitlement-gated, so it would fail every automatic run — dispatch it explicitly. README documents the entitlement caveat so the ADC plumbing isn't mistaken for working out of the box. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # CLAUDE.md # cmd/entire/cli/agent/agent.go # cmd/entire/cli/agent/text_generator_cli.go # cmd/entire/cli/doctor_test.go # cmd/entire/cli/strategy/manual_commit_condensation_test.go # mise-tasks/test/e2e/_default
Post-merge adjustments after merging origin/main (1,549 commits): - main renamed checkpoint.CommittedMetadata to checkpoint.Metadata (persistent vocabulary, api/checkpoint extraction) — update the merged antigravity token metadata tests. - Extract resolveCondensedTokenUsage from CondenseSession: the merge pushed the function over the maintidx threshold; the token fallback chain (out-of- band -> transcript backfill -> accumulated per-checkpoint) is now a named, documented helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Token accounting: - Drop the out-of-band fallback that copied session-cumulative state.TokenUsage into per-checkpoint metadata — it double-counted earlier turns on every checkpoint after the first and preempted the correct checkpoint-scoped state.CheckpointTokenUsage fallback (which SaveStep already feeds with the same out-of-band delta). The pinning test now sets a deliberately larger cumulative total so any regression re-inheriting it fails. - Record the out-of-band token delta even when a turn ends with no uncommitted changes (agy committing all its work mid-turn — its normal flow): the totalChanges==0 early return skipped SaveStep and then deleted the baseline, losing the turn's tokens permanently. New strategy.AccumulateSessionTokenUsage mirrors SaveStep's accounting. Committed-state filtering: - Remove filterToUncommittedDeletions and the relNewFiles filtering entirely: git status cannot report a committed deletion and untracked files are never in HEAD, so both filters were no-ops for their intended case while the deletion filter actively dropped uncommitted deletions of files created within the session — making checkpoint rewind resurrect deliberately deleted files. Only relModifiedFiles (which merges transcript-extracted paths) needs committed-state filtering. Scoping and matching: - Scope the empty-live-transcript degrade to Antigravity: other agents keep the error/retry-next-commit invariant for transient empty-file races. - UninstallTitleTee now matches the bare localDev tee by shape instead of re-resolving the repo path at uninstall time — uninstalling from a different worktree no longer orphans the global title entry (which kept spawning a failing `go run` after the original worktree was deleted). - entireHookPrefixes uses the full canonical localDev prefix (matching cursor/claudecode) instead of bare "go run ", which misclassified any user-authored go-run command as Entire-managed. - e2e WaitFor surfaces exhausted raw-tool-call retries as an error instead of returning malformed content with nil. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eline - Extract forEachNonBlankLine as the single owner of the transcript-offset metric: ExtractPrompts, GetTranscriptPosition, and ExtractModifiedFilesFromOffset each hand-rolled the same skip-blank-before- counting loop, kept in sync only by comments — a drift in any copy would silently shift offsets and attribute prompts/files to the wrong checkpoint. - SnapshotTokenBaseline reuses the streaming last-line reader (generalized from the dedup path) instead of JSON-decoding the entire per-conversation snapshot history on every TurnStart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ment antigravity limitations - The interactive agent selector and `entire agent list` now show a "(Preview)"/"(preview)" label for agents whose IsPreview() is true — the hook-install message already did; the selection surfaces users see first did not. Extracted the shared previewLabel constant. - docs/architecture/agent-guide.md gains an "Antigravity status: Preview" section listing the known limitations (silent tracking, coarse mid-turn token scoping, transcript-less first-turn mid-turn checkpoints, title-slot dependency for token capture, quota/entitlement-gated live E2E, wire format pinned to agy 1.0.14/1.0.15). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sweep of every agent enumeration outside the architecture guide (which already documents agy): README (feature line, --agent flag values, hooks-file table with .agents/hooks.json), first-time-contributors, security-and-privacy, sessions-and-checkpoints, .github/copilot-instructions, and the --summarize-agent flag help (agy is a summary provider). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follows the codex/copilotcli/cursor pattern: verdict (COMPATIBLE, Preview), binary/auth notes, hook mechanism + event mapping (3 installed hooks, 0-indexed invocationNum, conditional TurnStart for resumes), captured payload schemas, transcript layout and the after-Stop write with its handling, TranscriptAnalyzer offset contract, the out-of-band token tee design, config preservation, and the preview gaps & limitations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…des it Found by the first full live E2E run (51/59 pass, agy 1.0.16): in headless -p mode agy's "Individual quota reached" detail lands ONLY in ~/.gemini/antigravity-cli/log/cli-*.log — stderr is empty and the transcript's ERROR_MESSAGE carries just the generic "overloaded" 429 text — so the harness classified an exhausted quota as transient and retried scenarios into the wall. antigravityFatalFromLogs scans log files modified since the prompt started (E2E_ANTIGRAVITY_LOG_DIR override for tests); RunPrompt consults it before an error can be classified transient. antigravityFatalError now also matches its own generated messages so a folded fatal finding stays fatal on reclassification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Found by the first full live agy E2E run (TestSubagentCommitFlow): agy runs subagents as separate conversations with their own hooks. The subagent's fullyIdle Stop condenses normally at commit, but the parent conversation only receives fullyIdle=false Stops before the headless process exits — leaving a "ghost" session that stays ACTIVE with zero tracked files and zero checkpoints. The post-commit cleanup preserved the shadow branch for ANY active uncondensed session, so the ghost pinned the branch permanently — a guaranteed leak, since PostCommit also rebases the ghost's BaseCommit to the new HEAD, meaning any future work targets a NEW branch name. Preserve the branch only for active uncondensed sessions that still track files (their uncondensed checkpoints are the only copy of that work). Sessions with nothing to lose don't pin: SaveStep recreates shadow branches on demand. TestPostCommit_ReadOnlyActiveSessionNotCondensed pinned the leak as intended behavior; its final assertion is flipped with the rationale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolved cmd/entire/cli/setup.go: main extracted the duplicated agent-option loops into hookAgentOptions; folded this branch's preview-label logic into that helper so it applies at both call sites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes from the trail 444 agent-review findings, verified against the code: - Atomic settings write: writeJSONMapFile now goes through jsonutil.WriteFileAtomic, so a crash mid-write can no longer truncate agy's machine-global settings.json (shared title slot) or .agents/hooks.json. - Crash-resume tracking: shouldSuppressConditionalTurnStart also fires the conditional TurnStart when state.OwnerExited() detects a dead owner PID, instead of waiting out the 1h StuckActiveThreshold. - Cache-path isolation: statusDir resolves via userdirs.Cache() (the mandated resolver) so $XDG_CACHE_HOME isolation works on darwin and go-test runs fall back to a throwaway dir instead of the real user cache. - Dangling trailer: the prepare-commit-msg fast path (sessionLacksCondensableContent) stats agy's transcript file rather than trusting the non-empty path, so no Entire-Checkpoint trailer is stamped for a mid-turn commit whose condensation will return Skipped (agy writes the transcript only after Stop; shell-only edits leave FilesTouched empty). - Statusline hot path: readLastStatusSnapshot does a bounded 64KB tail-read (O(1) per title fire instead of O(file)); MkdirAll only on first append. - Wrapped title command failures now leave a Debug breadcrumb and the POSIX-only constraint of the sh -c wrap is documented. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 01KWYNWMTR2EHMVWK1FKAKC13J
The origin/main merge brought in claudecode.ClaudeErrorUnknown without a matching case in formatCheckpointSummaryError's kind switch; golangci-lint's exhaustive check fails on the tree. Route Unknown through the existing default handling explicitly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 01KWYNX0XYRTQ8NPMPPP62JGGV
…set advance Addresses the two remaining trail 444 findings: - New agent.LateTranscriptWriter capability marks agents whose transcript is written only after the Stop hook (agy). It replaces the three AgentType==Antigravity switches threaded through shared strategy code (empty-transcript degrade, offset counting in countTranscriptItems, the prepare-commit-msg content guard), and its CountTranscriptPosition method makes the agent the single owner of its offset metric — deleting the non-blank-line counter the strategy had to keep byte-identical with the agent's readers across the package boundary. The remaining generateSummary switch is a transcript-format enumeration (agy grouped with the JSONL agents), not an agent special-case, and stays. - Prompt-shift fix for mid-turn commits: HandleTurnEnd's offset advance can lose agy's transcript-flush race at Stop, leaving CheckpointTranscriptStart inside the previous turn — the next mid-turn commit's checkpoint then extracts the previous turn's prompt and re-scopes already-condensed transcript. The lost advance is now recorded in a one-shot TranscriptOffsetPending state flag and completed at the next mid-turn condensation, where a late-flushing agent's file provably contains only already-condensed turns. Carry-forward clears the flag (it restarts the offset at 0 deliberately). Regression pin covers the exact misattribution. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 01KWYNX9NHKJ6YT977RW3ZXPRT
d98d9a0 to
42abc77
Compare
…older Trail finding asked whether agy reads the prompt from the -p value (which would make GenerateText summarize a literal space). Verified live against agy 1.0.16: a prompt piped to stdin with -p " " is what the model receives and answers — same convention as the Gemini CLI, whose --help documents it while agy's does not. Record that in the comment so the pattern isn't re-flagged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 01KWYPMYBRJM2STKR93TDYTMAR
# Conflicts: # cmd/entire/cli/setup.go
agy 1.1 moved skill discovery defaults: workspace skills now live in <workspace>/.agents/skills (legacy .agent/skills still honored) and global skills in ~/.gemini/config/skills. The discovery scanned only the pre-1.1 roots, so skills created where agy's own /skills UI puts them never showed in the entire review picker. Scan new and legacy roots. Also align the wire-format claims across AGENT.md, agent-guide, and the integration-test comment: captured on 1.0.14/1.0.15, re-verified unchanged against agy 1.1.1 (docs + binary + live run, 2026-07-13). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
antigravityFatalFromLogs read agy's CLI logs from the harness process's real HOME, but in ADC mode the agy subprocess runs with HOME redirected to the per-repo test home — exactly the CI dispatch mode where the fail-fast classification matters. A quota wall visible only in agy's CLI log would be classified transient and retried into. Resolve the log dir through the same ADC-aware home resolution as the brain dir (new antigravityHomeDir). Also: create the ADC credentials file with 0600 before writing the secret in all three workflows, and fix the README's CI-matrix line to match the actual push-run matrix (antigravity is workflow_dispatch-only). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- doctor: skip the title-tee check when no agy binary is on PATH — .agents/hooks.json is committable, so a teammate who never uses agy would otherwise get a permanent false warning (whose repair writes agy's global settings); repair hint now names the agent (entire agent add antigravity). - hooks: install the Stop handler with an explicit 300s timeout; agy's 30s default can kill SaveStep mid-checkpoint on large repos with no trace. - agent remove: warn that uninstalling the global title-tee disables token capture for every other repo still using Antigravity (only when the tee was actually claimed). - docs: document the machine-global title-tee capture surface in security-and-privacy.md (conversation ID + token counts only, 14-day snapshot retention, removed with agent remove). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Conflict: cmd/entire/cli/agent/agent.go — both sides added a new capability interface at the same location (LateTranscriptWriter here, SidecarImageProvider on main); kept both. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- AreHooksInstalled parses per-entry: a malformed FOREIGN hook entry in .agents/hooks.json (free-form user content) no longer breaks detection of the entire entry — install previously succeeded while status/doctor permanently reported not-installed. - InstallHooks respects a user-set "enabled": false on the entire entry (agy's documented per-entry disable knob) instead of rewriting the entry and silently re-arming tracking; --force remains the explicit override. - computeOutOfBandTokenUsage treats a missing token baseline mid-session as no-data instead of count-from-zero: a lost/corrupt PrePromptState after turn 1 would otherwise return session-cumulative totals and double-count every earlier turn's tokens. Resolves trail 444 findings 019f5c22-ef3, 019f5c23-098, 019f5c22-f84. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Independent test report — branch I run agy daily alongside Claude Code/Codex, so I put this branch through a real workout: fresh build, What works (end-to-end): clean native build ( No format drift 1.1.1 → 1.1.10: all One real bug — silent file loss under One DX trap worth a doc line: plain Small notes: Happy to re-test after a rebase (branch is ~620 commits behind main as of today) and can share the truncated-step fixture. Thanks for building this — it's the missing piece for my fleet. |

https://entire.io/gh/entireio/cli/trails/444
Summary
First-class support for Antigravity CLI (
agy), Google's successor to Gemini CLI, as a new Entire agent — the complete integration: lifecycle hooks, transcript decoding, native token counts, review-skill discovery, resume tracking, docs, and E2E wiring. Consolidates the previously stacked PRs #1356 (tokens) and #1381 (transcript decode) plus the gap-fix and review-fix rounds into this single parent.Scope map (~7.2k insertions; ~60% tests):
cmd/entire/cli/agent/antigravity/pre-tool-use,pre-invocation,stop), transcript analyzers (prompts, positions, modified files), async-transcript handling, token tee (statusline.go/title_install.go), review-skill discoverycmd/entire/cli/lifecycle.go,state.go,event.gocmd/entire/cli/strategy/agent/skilldiscovery/Real-agy quirks (all hardened in code + tests)
invocationNumis 0-indexed; PreInvocation fires per model invocation.invocationNum > 0emits a conditional TurnStart (Event.SuppressIfSessionActive) the dispatcher drops only when a turn is genuinely mid-flight — so resumes (agy --conversation) are tracked and follow-up invocations don't clobber the pre-prompt baseline.Stop.PrepareTranscriptbriefly waits then materializes a placeholder; condensation degrades to a files/prompt-only checkpoint (agy-scoped) and prompts are re-extracted late (resolvePromptsFromLateFlushedTranscript).titleslot is claimed byentire hooks antigravity title-tee(wrap-preserving, doctor-checked); TurnStart snapshots a baseline, TurnEnd computes the delta (OutOfBandTokenSource).decodeAgyString/decodeAgyBooltolerate both shapes. macOS/tmpsymlinks resolved.Review & verification
entire agent add antigravity→ real hook wiring → mid-turn commit with unwritten transcript → checkpoint + trailer + scoped tokens +entire statusall correct. Realagyfired PreInvocation live (session state created); the model call itself is quota-gated (below).TestSingleSessionManualCommitpassed live with real token counts; fresh-repo smoke verified install → live turn → commit → condensation → resume (agy --conversation) → token scoping across two commits. agy auto-updated 1.0.16→1.1.1 mid-session; hook wire contract re-verified unchanged, but agy 1.1 moved the skill-discovery directories — fixed, along with the ADC-mode quota-log peek, a doctor false-positive for non-agy teammates, an explicit Stop-hook timeout, and anagent removewarning about the global title-tee. Deferred minors are tracked as findings on trail 444.Known limitations (preview)
cloudcode-pabackend can't be enabled on arbitrary GCP projects (subject 110002 — needs a Gemini Code Assist subscription). Hence agy is a workflow_dispatch-only E2E leg, with fail-fast classification so quota/entitlement walls read as clear errors, not retry storms. Details ine2e/README.md.entire statusis the visibility surface.entire hooks antigravity title-teeowning/wrapping agy's globaltitleslot (doctor-checked, setup-repaired).Test plan
mise run checkgreen locally (fmt, lint 0 issues, unit + integration + canary)mise run test:e2e --agent antigravity TestSingleSessionManualCommit— passed live 2026-07-13 (real agy, real tokens in the condensed checkpoint)agy --conversation→ checkpoint-scoped token deltas across two commits🤖 Generated with Claude Code
Note
Medium Risk
New agent code paths affect session lifecycle, hook-installed repo files, and checkpoint condensation; risk is mitigated by extensive tests but behavior depends on undocumented agy wire formats.
Overview
Adds preview first-class support for Antigravity CLI (
agy): a newantigravityagent package that registers with Entire, installs five workspace hooks into.agents/hooks.json(entireentry →entire hooks antigravity <verb>), and maps hook stdin to lifecycle events (TurnStart,ToolUse,TurnEnd).Lifecycle behavior is tailored to real
agyquirks:TurnStartonly wheninvocationNum == 0(follow-up pre-invocations are ignored so baselines aren’t reset);StopwithfullyIdle→TurnEnd(soSaveStep/checkpoints run); post-invocation is a no-op because transcripts aren’t ready yet;PrepareTranscriptcreates an empty placeholder when the transcript file is still missing after stop. Pre-tool-use records touched files from mutating tools, including double-encoded args and parent-dir symlink normalization (macOS/tmp).Also wires non-interactive
GenerateTextviaagy -p, JSONL transcript chunk/reassemble (passthrough v1), registry/hooks CLI imports, integration tests over subprocess hooks, and optional E2E registration whenagyis onPATH.Reviewed by Cursor Bugbot for commit f141838. Configure here.