Skip to content

✨ [feat] host: run the board on Google Antigravity (agy) #80

Open

Description

@danielegaleazzi92

Problem

super-board names three agent hosts (claude, codex, opencode; docs/hosts.md) and runs lanes on two of them. Google Antigravity ships a headless CLI (agy -p, JSON output with a schema, skills under .agents/skills, hooks in .agents/hooks.json, a status line with quota buckets) that covers everything a lane needs, but a /super-board run typed inside Antigravity today halts at the host check (exit 65), and there is no backend to send a wave to. Teams on Antigravity cannot use the loop at all, and a Claude user cannot offload lanes to it the way --codex does.

I have a working implementation, rebased on main after #71/#73, and would like to contribute it in slices, one PR each, in whatever shape fits the repo. It is the minimum for the loop to run on Antigravity. Everything is additive: claude and codex behaviour does not change.

Context

  • Where: host detection (scripts/super-board-host.sh, scripts/super-board-setup.py HOSTS, config-schema.json host), the installer (install.sh --hosts), the headless wave path (scripts/super-board-codex-wave.sh + lane launcher), the orchestrator reference (run-workflow.md), the usage guard (scripts/super-board-usage.sh), docs/hosts.md.
  • Checked against: agy 1.4.6 on Windows 11, 2026-10-23, with the CLI's bundled docs (~/.gemini/antigravity-cli/builtin/skills/agy-customizations/docs/) and antigravity.google/docs.
Need of a lane Antigravity
Headless run with a structured answer agy -p <prompt> --output-format json --json-schema <string or file> prints one JSON line {conversation_id, status, response, error?, duration_seconds, num_turns, structured_output?, usage, denied_actions?}
Model and effort --model <slug>, --effort low|medium|high|xhigh|max; the listed slugs (gemini-3.8-flash-low, ...) already carry an effort and conflict with --effort, so a lane passes the base slug (gemini-3.8-flash)
Timeout --print-timeout (0s = wait per agy --help; the headless page says 5m): always pass it
Skills discovered natively in .agents/skills/<name>/SKILL.md: #71's shared .agents/ layout already puts them there, nothing to link
Guard hooks .agents/hooks.json, events SessionStart / PreToolUse / PostToolUse / PreInvocation / PostInvocation / Stop; stdin {toolCall:{name:"run_command", args:{CommandLine}}, workspacePaths, ...}, stdout {decision: allow|deny|ask|force_ask, reason}; cwd = the folder holding hooks.json; cmd /c on Windows; fires before the permission check and fails closed
Permissions ~/.gemini/antigravity-cli/settings.json has permissions.{allow,ask,deny} with rules command(<prefix>), command(regex:...), write_file(...), read_file(...); headless auto-denies what no rule covers (exit 0, denied_actions in the JSON, notice on stderr)
Quota status line (statusLine.command, stdin JSON) carries quota: {<bucket>: {remaining_fraction, reset_time, reset_in_seconds}}; over quota a run exits 3 with AGY_ERROR: {"status":"RESOURCE_EXHAUSTED","error_code":429,"retryable":true,...} on stderr
Host sign ANTIGRAVITY_AGENT=1 in every shell run_command runs (plus ANTIGRAVITY_CONVERSATION_ID, ANTIGRAVITY_LS_VERSION=cli-1.4.6, ...); not documented, observed with cmd /c set inside a headless run
Shells run_command runs PowerShell 5.1 on Windows, hooks run under cmd /c
  • Who: anyone whose daily host is Antigravity; Claude users who want Build/QA lanes on a second provider (usage_fallback: "agy") while Claude is paused.

Fix

Ship in slices behind the existing host key and a --agy[=<model>] run flag, mirroring --codex. Each item is one PR, tested offline with a fake agy (same pattern as tests/fixtures/fake_codex.py). All four are open as drafts, stacked #81 → #82 → #83 → #84: merge in that order, each later diff shows the earlier slices until then.

Acceptance Criteria

Risk

🟡 Medium · a new backend, additive.

  • Door: two-way · each slice reverts on its own; no data, board state or project file format changes.
  • Blast radius: install and host detection (every host runs them; covered by the existing suites) · the new lane path (Antigravity users only).

Blocked by

What the proof run taught about headless agy 1.4.6 on Windows (9 waves; the first 7 each died on one of these)
  1. Model slugs carry the effort: --model gemini-3.8-flash-low --effort medium is rejected as a conflict. Pass the base slug with --effort.
  2. Permission rules match the whole command exactly on Windows: command(python) does not allow python --version; only command(regex:(?s)python(\s.*)?) does. Prefix rules are a Unix convenience.
  3. A per-program allowlist still does not cover a lane: it improvised python for python3, a ; chain, a multi-line python -c, a PowerShell here-string, each denied in turn. What worked: command(*) plus explicit deny rules for the dangerous forms, with the guard hooks as the real safety net (they run before the permission check and fail closed). --dangerously-skip-permissions is the wrong tool: it also skips the ask / deny evaluation the deny rules need.
  4. File writes follow the same rule: a write outside the workspace (a mktemp file) is auto-denied; write_file(*) / read_file(*) with deny rules on ~/.ssh, ~/.gemini, ~/.gitconfig* and .env let the lane run; the brief should keep scratch files under .claude/super-board/inflight/.
  5. python3 does not exist under cmd / PowerShell on Windows (Store alias): hook commands and the brief's python3 ... examples need python or py -3 there. A hook that fails to start blocks every matched tool call with a misleading reason.
  6. The brief's cmd1 && cmd2 and a | python ... examples mislead the lane in PowerShell 5.1 (&& is a parse error there); the brief should say which shell it is in.
  7. guard-worktree-path.py denies .claude/worktrees/... on Windows (🐛 [bug] guards: Windows Git Bash paths and prose trip three guard hooks #72): git rev-parse prints C:/x, os.path.join adds \.claude\worktrees, startswith never matches. normcase(normpath(...)) on both sides fixes it. guard-secrets.py also denies any Bash command whose text contains the word credentials (a commit message, for one).
  8. Denials are structured: the JSON result carries denied_actions: [{action, display_name}]; the lane should read that, not grep stderr (whose text is "auto-denied", not "soft-denied").
  9. Over quota is a hard failure (exit 3, AGY_ERROR JSON on stderr, status: ERROR), not a soft denial: map it to halted with a retry-after. Quota is per model: gemini-3.8-flash kept working while the main bucket was exhausted.
  10. Two lanes that finished their work (card moved, comments posted, PR merged) still ended with no structured_output, and the launcher reported returned no valid result; the raw run was not kept, so the cause (prose answer, a backend INTERNAL 500 retry seen once, schema lost) cannot be told apart. Keep the raw run on failure and let reconcile re-read the card's column before calling a lane failed.
  11. Required GitHub reads under PowerShell: gh ... --jq "\(.headRefName)" from the brief is mangled by PowerShell quoting and fails 3 times, leaving a github-halt-*.json; the lane went on regardless, so an exit-79 halt is not binding on a headless lane unless the launcher checks the halt file after the run.
  12. Every run logs You are not logged into Antigravity warnings from a start-up cache refresh while proceeding with cached credentials; a sign-in check must not grep for them.
  13. super-board-setup.py fix/check --host accepts only claude and codex; onboard for Antigravity has to run it as --host claude until it knows agy.
  14. The suite on Windows Git Bash, before any change: tests/test-setup.sh fails at the first fix (setup.py hands a Windows path to bash and the backslashes vanish) and tests/test-install.sh at "symlink layout" (no symlink rights). The CI matrix is the check there.

Activity

  1. changed the title [-]✨ [feat] host: run the board on Google Antigravity (agy) as a fourth host[/-] [+]✨ [feat] host: run the board on Google Antigravity (agy)[/+] on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions