feat: Antigravity CLI harness support — agent.json, native skills, install/uninstall workflow#562
feat: Antigravity CLI harness support — agent.json, native skills, install/uninstall workflow#562mhenke wants to merge 4 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Antigravity CLI as a sixth harness: updates docs/Makefile/.gitignore, implements AntigravityAdapter to emit .antigravity artifacts, wires generator/pruner/validator, adds tools/install_antigravity CLI, and introduces tests for emission, install/uninstall, round-trip counts, and validation. ChangesAntigravity CLI Harness Support
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
de680eb to
1de2200
Compare
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds Antigravity as a first-class harness alongside Codex/Copilot/Cursor/OpenCode/Gemini, including generation, validation, installation helpers, and test coverage.
Changes:
- Introduces
AntigravityAdapterand registers it in generation + capabilities. - Adds Antigravity artifact validation, round-trip tests, and install/uninstall symlink helper.
- Updates docs/Makefile to expose the new harness workflows.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/validate_generated.py | Adds Antigravity validator and registers it in _VALIDATORS. |
| tools/tests/test_validate_generated.py | Adds unit tests for validate_antigravity. |
| tools/tests/test_round_trip.py | Adds round-trip consistency checks for generated Antigravity artifacts. |
| tools/tests/test_install_antigravity.py | Adds tests for Antigravity install/uninstall helper behavior. |
| tools/tests/test_adapters.py | Adds adapter-level tests verifying Antigravity JSON/skill emission and tool rewriting. |
| tools/install_antigravity.py | New helper CLI to symlink .antigravity artifacts into user config dirs. |
| tools/generate.py | Registers antigravity harness and output paths; adds pruning support. |
| tools/doc_gardener.py | Adds stale-artifact drift detection for .antigravity outputs. |
| tools/adapters/capabilities.py | Adds Antigravity capability row + tool/model alias mappings. |
| tools/adapters/base.py | Adds aliases accessor (used by Antigravity workflow emission). |
| tools/adapters/antigravity.py | New Antigravity adapter emitting agent.json, SKILL.md, and workflows. |
| plugins/plugin-eval/tests/test_stats.py | Import formatting tweak (no functional change). |
| plugins/plugin-eval/tests/test_parser.py | Import cleanup/formatting (no functional change). |
| plugins/plugin-eval/tests/test_monte_carlo.py | Removes unused AsyncMock import; formatting. |
| plugins/plugin-eval/tests/test_models.py | Removes unused imports. |
| plugins/plugin-eval/tests/test_judge.py | Removes unused AsyncMock import. |
| plugins/plugin-eval/tests/test_harness_portability.py | Formatting + removes unused pytest import. |
| plugins/plugin-eval/tests/test_engine.py | Removes unused pytest import. |
| plugins/plugin-eval/tests/test_corpus.py | Removes unused pytest import. |
| plugins/backend-development/skills/api-design-principles/assets/rest-api-template.py | Formatting + removes unused FastAPI imports. |
| docs/harnesses.md | Adds Antigravity to harness list, matrix, and regeneration instructions. |
| Makefile | Adds install-antigravity/uninstall-antigravity targets and adds harness to HARNESSES. |
| AGENTS.md | Mentions Antigravity as a consumer + adds generation instructions. |
| .gitignore | Adjusts generated/runtime ignores (Codex/.agent/.agents). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
618fc43 to
4c33f17
Compare
There was a problem hiding this comment.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tools/tests/test_adapters.py (1)
8-25:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix import ordering to satisfy ruff.
The pipeline reports that the import block is un-sorted. The
AntigravityAdapterimport at line 25 should be moved before thebaseimport (line 15) to maintain alphabetical order by module name.📦 Proposed fix
from __future__ import annotations import json import re from pathlib import Path # tools.adapters.* imports happen via the conftest sys.path injection +from tools.adapters.antigravity import AntigravityAdapter from tools.adapters.base import PluginSource, parse_frontmatter from tools.adapters.codex import CodexAdapter, _split_body_if_oversized from tools.adapters.copilot import ( CopilotAdapter, _build_tools_list, _needs_yaml_quoting, ) from tools.adapters.cursor import CursorAdapter from tools.adapters.gemini import _INLINE_BODY_THRESHOLD, GeminiAdapter from tools.adapters.opencode import OpenCodeAdapter, _opencode_skill_id -from tools.adapters.antigravity import AntigravityAdapterAs per coding guidelines: use ruff for linting and formatting Python code.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/tests/test_adapters.py` around lines 8 - 25, The import block in tools/tests/test_adapters.py is unsorted per ruff: move the local adapter import for AntigravityAdapter (currently imported from tools.adapters.antigravity) so it appears alphabetically among the other tools.adapters.* imports — specifically place the "from tools.adapters.antigravity import AntigravityAdapter" line before "from tools.adapters.base import PluginSource, parse_frontmatter" (and ensure the entire tools.adapters.* group is alphabetized), keeping grouping of stdlib/third-party vs local imports intact.Makefile (1)
25-25:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate help header harness list to include Copilot and Antigravity.
The section title is now stale versus actual supported harnesses and targets in this file.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Makefile` at line 25, Update the Makefile help header string that currently echoes "Multi-harness adapter (Codex / Cursor / OpenCode / Gemini):" so it lists all supported harnesses including Copilot and Antigravity; locate the echo line (the `@echo` "Multi-harness adapter (...)" statement) and edit the text to include ", Copilot / Antigravity" (or equivalent ordering/format) so the header matches the actual supported harnesses and targets.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.gitignore:
- Around line 45-53: Add the missing .copilot/ entry back into the
generated-artifact ignore section so generated Copilot outputs stay untracked:
update the .gitignore to include a line with ".copilot/" alongside the existing
".codex/" and ".agents/" entries (ensure the trailing slash is present and no
contradictory entries later in the file), preserving the invariant that
generated harness artifacts are not committed.
In `@AGENTS.md`:
- Line 64: The Antigravity artifact path examples in AGENTS.md use
hyphen-separated names (`.antigravity/skills/<plugin>-<skill>/SKILL.md` and
similar) which contradict the PR contract; update the documented examples to use
the proper namespacing with double underscores (`<plugin>__<skill>` and
`<plugin>__<agent>`) wherever the hyphenated forms appear (including the entries
around the shown line and the one reported at 76), and ensure the text
consistently references `.antigravity/skills/<plugin>__<skill>/SKILL.md` and
`.antigravity/agents/<plugin>__<agent>/AGENT.md`.
- Around line 48-49: Update the note for the make target so it reflects the new
harness count: change the text after "make generate-all" from "all five" to "all
six" to account for the added Antigravity harness (see the make generate
HARNESS=antigravity entry that emits .antigravity/agents/ and
.antigravity/skills/ and the make generate-all line).
In `@docs/authoring.md`:
- Around line 108-110: The markdown table in docs/authoring.md has a malformed
separator row with too many columns, so update the separator row that follows
the header line "| Source field | Codex | Cursor | OpenCode | Gemini | Copilot |
Antigravity CLI |" to contain exactly seven column separators (e.g.,
"|---|---|---|---|---|---|---|") so it matches the header and the data row
(e.g., the "`model: opus`" row) to restore correct table rendering.
In `@docs/harnesses.md`:
- Line 18: The Antigravity CLI capability entries are inconsistent about
slash-command emission and output locations; update the "Antigravity CLI" row in
the capability matrix and the related prose sections (the entries referenced
around lines 26-27, 53, and 65) so they express one unified contract: explicitly
state whether Antigravity emits slash-commands or not, where outputs are written
(e.g., `.antigravity/agents/`, `.antigravity/skills/`), and define
graceful-degradation behavior when a feature is unsupported; ensure the matrix,
the "Antigravity CLI" description, and any examples all match this single agreed
behavior and output path convention.
In `@docs/round-trip-results.md`:
- Around line 114-120: Update the docs snippet to reflect the actual emitted
artifacts and installer target: replace the commands path
`.antigravity/commands/` with `.antigravity/workflows/`, and change the install
comment/target from symlinking to `~/.antigravity/` to symlinking to
`~/.gemini/antigravity-cli/` (the `make install-antigravity` step should
reference that target); ensure the listing lines and the "Global install
(optional)" installer instruction use these corrected paths so the documentation
matches the PR behavior.
In `@README.md`:
- Line 145: Update the README table row that currently lists the Antigravity CLI
install path as `.antigravity/` so it matches the actual installer destination
used by make install-antigravity; replace `.antigravity/` with
`~/.gemini/antigravity-cli/` (and verify the adjacent text mentioning `make
install-antigravity` remains consistent with this path) so the documented global
install location reflects the real installer output.
In `@tools/adapters/antigravity.py`:
- Around line 36-41: The current _rewrite_body_lowercase_tools only replaces
backticked tool names; update it to also replace plain-word occurrences by
iterating TOOL_NAME_MAPS["antigravity"] and performing two replacements per
mapping: the existing backtick replacement and a word-boundary/plain replacement
(use regex word boundaries or equivalent) so strings like "use the Read tool"
are converted to the Antigravity name; preserve existing behavior for backticked
names and ensure you reference TOOL_NAME_MAPS["antigravity"] and the function
name _rewrite_body_lowercase_tools when making the change.
- Around line 20-33: The _antigravity_frontmatter function currently builds YAML
by concatenating unquoted scalars and list items which breaks on characters like
:, #, commas or newlines; replace the hand-rolled serializer with a proper YAML
emitter (e.g., use yaml.safe_dump) to render the frontmatter safely: import
yaml, build the frontmatter dict in _antigravity_frontmatter and call
yaml.safe_dump(fm, default_flow_style=False, sort_keys=False) (or dump
individual values with yaml.safe_dump for scalars/lists) so booleans, lists,
multiline strings and special characters are correctly quoted/escaped and then
wrap the emitted YAML with the leading/trailing --- markers.
In `@tools/doc_gardener.py`:
- Around line 253-269: The stale-check currently only maps hyphenated
antigravity skill IDs to plugin command markdown under PLUGINS_DIR but
Antigravity command outputs are stored as workflows; update the logic around
antigravity_skills / skill_md / name to also scan the antigravity_root /
"workflows" directory and match hyphenated names to plugin workflow artifacts:
for names with "-" iterate list_plugins() to find plugin_name and cmd_name (as
you already do), then look for a source workflow under PLUGINS_DIR / plugin_name
/ "workflows" (use a glob for common extensions like .yaml/.yml/.json or pattern
f"{cmd_name}.*") and if src.is_file() append (src, skill_md) to pairs; keep the
existing SKILL.md resolution (PLUGINS_DIR / plugin / "skills" / leaf /
"SKILL.md") for the "__" case.
In `@tools/generate.py`:
- Line 37: clean_output() and prune_orphans() currently ignore
.antigravity/workflows, leaving stale workflow artifacts; update the antigravity
target list (the "antigravity" entry in tools/generate.py that currently
contains ".antigravity/agents" and ".antigravity/skills") to also include
".antigravity/workflows", and likewise add ".antigravity/workflows" to the other
target arrays referenced in the same file (the block around lines 168-172) so
both clean_output() and prune_orphans() will remove/handle workflows.
In `@tools/install_antigravity.py`:
- Around line 13-16: ARTIFACT_GLOBS currently maps only "agents" and "skills",
causing workflows to be skipped; update the ARTIFACT_GLOBS constant to include a
"workflows" entry (e.g., "workflows": "*") and then ensure the install/uninstall
code paths that iterate these globs (such as the functions handling artifact
discovery/processing in install_antigravity.py) treat "workflows" the same as
"agents"/"skills" so workflow artifacts are discovered and managed during
install and uninstall.
In `@tools/validate_generated.py`:
- Around line 741-779: The code currently allows customAgentSpec = null because
only non-dict non-null values hit the existing error branch; update the
validation after spec = data.get("customAgentSpec") to explicitly treat spec is
None as an error: add a branch that calls report.add (using the same
harness="antigravity", path=agent_json_path, and an appropriate
message/remediation) when spec is None, and keep the existing elif spec is not
None branch for other wrong types; ensure you reference the same variables
(spec, custom_agent, customAgentSpec, agent_json_path, report.add) so behavior
is consistent with surrounding validations.
- Around line 690-790: validate_antigravity currently only checks skills_dir and
agents_dir; add a commands_dir check (e.g., commands_dir = WORKTREE /
".antigravity" / "commands") and validate generated command workflow artifacts
similarly to agents: for each workflow file (e.g., glob("*/workflow.json") or
"*.json" under each command dir) attempt JSON.parse and report JSONDecodeError
via report.add, ensure required top-level keys exist (suggest at minimum "id",
"name", and "steps") and that "id" or "name" matches the parent directory when
present, ensure "steps" is a list and that each step is an object with required
keys (e.g., "action" or "run" and "inputs"), and use the same report.add pattern
(severity, harness="antigravity", path=..., message=..., remediation=...) for
missing fields or structural type errors; follow the patterns in
validate_antigravity (json.loads, report.add messages, checks for dict/list) and
place this new validation after the agents_dir block.
---
Outside diff comments:
In `@Makefile`:
- Line 25: Update the Makefile help header string that currently echoes
"Multi-harness adapter (Codex / Cursor / OpenCode / Gemini):" so it lists all
supported harnesses including Copilot and Antigravity; locate the echo line (the
`@echo` "Multi-harness adapter (...)" statement) and edit the text to include ",
Copilot / Antigravity" (or equivalent ordering/format) so the header matches the
actual supported harnesses and targets.
In `@tools/tests/test_adapters.py`:
- Around line 8-25: The import block in tools/tests/test_adapters.py is unsorted
per ruff: move the local adapter import for AntigravityAdapter (currently
imported from tools.adapters.antigravity) so it appears alphabetically among the
other tools.adapters.* imports — specifically place the "from
tools.adapters.antigravity import AntigravityAdapter" line before "from
tools.adapters.base import PluginSource, parse_frontmatter" (and ensure the
entire tools.adapters.* group is alphabetized), keeping grouping of
stdlib/third-party vs local imports intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6110976e-71a8-47ce-a3ff-b39b5618b7fc
📒 Files selected for processing (20)
.gitignoreAGENTS.mdARCHITECTURE.mdCONTRIBUTING.mdMakefileREADME.mddocs/authoring.mddocs/harnesses.mddocs/round-trip-results.mdtools/adapters/antigravity.pytools/adapters/base.pytools/adapters/capabilities.pytools/doc_gardener.pytools/generate.pytools/install_antigravity.pytools/tests/test_adapters.pytools/tests/test_install_antigravity.pytools/tests/test_round_trip.pytools/tests/test_validate_generated.pytools/validate_generated.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use
uvas the package manager for Python projects, not pipUse
rufffor linting and formatting Python code, not black or other lintersUse
tyfor type checking Python code, not mypy
Files:
tools/tests/test_install_antigravity.pytools/adapters/base.pytools/doc_gardener.pytools/adapters/capabilities.pytools/validate_generated.pytools/adapters/antigravity.pytools/tests/test_round_trip.pytools/generate.pytools/tests/test_validate_generated.pytools/install_antigravity.pytools/tests/test_adapters.py
AGENTS.md
📄 CodeRabbit inference engine (CLAUDE.md)
AGENTS.md: Import the canonical AGENTS.md file following Anthropic's recommended cross-harness convention pattern for repository setup
Honor thetools:frontmatter verbatim in agent configurations for per-agent tool allowlist specificationKeep AGENTS.md file lean and under ~150 lines per OpenAI's harness-engineering practice; push procedural detail to skills and reference material to
docs/
Files:
AGENTS.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:19:17.043Z
Learning: Generated artifacts are gitignored and must never be hand-edited; source-of-truth lives only under `plugins/`
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:19:17.043Z
Learning: Never commit secrets to the repository
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:19:17.043Z
Learning: Never run destructive git operations (force-push, `reset --hard`, `branch -D`) without explicit approval
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:19:17.043Z
Learning: Run `make validate STRICT=1`, `make garden`, `make test`, and `make smoke-test` before pushing code
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:19:17.043Z
Learning: Codex/Cursor/OpenCode/Gemini CLI/Antigravity CLI must read from a single Markdown source-of-truth for plugins, agents, and skills
🪛 GitHub Actions: Code Quality / 0_Python (ruff + ty).txt
tools/tests/test_adapters.py
[error] 8-25: Ruff check failed due to unsorted/unformatted imports. Ruff: "Import block is un-sorted or un-formatted". Run ruff check --fix (help: Organize imports).
🪛 GitHub Actions: Code Quality / Python (ruff + ty)
tools/tests/test_adapters.py
[error] 8-25: ruff check failed: Import block is un-sorted or un-formatted. (help: Organize imports)
🔇 Additional comments (6)
tools/tests/test_adapters.py (2)
1185-1309: LGTM!
1311-1323: LGTM!tools/tests/test_install_antigravity.py (1)
1-96: LGTM!tools/tests/test_round_trip.py (1)
334-366: LGTM!tools/tests/test_validate_generated.py (1)
11-11: LGTM!Also applies to: 422-497
CONTRIBUTING.md (1)
3-5: LGTM!Also applies to: 48-59
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tools/install_antigravity.py (1)
147-147:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd the missing
listsubcommand to match the install helper contract.Line 147 only allows
install/uninstall, but the PR objective for issue#560calls for install/uninstall/list support. Right now users can’t inspect what would be managed without performing install/uninstall.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/install_antigravity.py` at line 147, The CLI parser currently restricts the "action" argument to only ("install", "uninstall") in the parser.add_argument call; update that call to include "list" (e.g., choices=("install","uninstall","list")) so the script supports the list subcommand required by the install helper contract, and ensure any action-handling code in functions like the action dispatcher recognizes and handles the "list" case.
♻️ Duplicate comments (1)
docs/harnesses.md (1)
18-18:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlign Antigravity command support docs to a single contract.
Line 18 (and Line 65) documents workflow emission, but the matrix still says Antigravity has no slash commands (Line 26) and Line 53 says commands are “converted to skill.” Please make these sections consistent around workflow-based command emission.
Suggested doc patch
-| Slash commands | ✅ | converted to skills | ✅ | ✅ | TOML at `commands/` | — | +| Slash commands | ✅ | converted to skills | ✅ | ✅ | TOML at `commands/` | ✅ via `.antigravity/workflows/` | @@ -| Slash command (`commands/<x>.md`) | converted to skill | passed through | rewritten to `.opencode/commands/` | TOML at `commands/<plugin>/<x>.toml` | converted to skill | +| Slash command (`commands/<x>.md`) | converted to skill | passed through | rewritten to `.opencode/commands/` | TOML at `commands/<plugin>/<x>.toml` | rewritten to `.antigravity/workflows/<plugin>-<x>.md` |🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/harnesses.md` at line 18, Unify the Antigravity command support documentation by making the matrix row for "Antigravity CLI" and the descriptive paragraphs about command handling consistent: update the table cell that currently lists `.antigravity/agents/, .antigravity/skills/, .antigravity/workflows/` (the "Antigravity CLI" row) and the paragraphs mentioning "workflow emission", "no slash commands", and "converted to skill" so they all state the same contract (e.g., that Antigravity emits workflow-based slash commands via `.antigravity/workflows/`), and adjust the wording in the sections referencing "workflow emission" and "converted to skill" to reflect that slash commands are emitted as workflows rather than absent or merely converted to skills.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tools/doc_gardener.py`:
- Around line 275-281: The prefix-matching loop in tools/doc_gardener.py can
pick the wrong plugin when plugin names overlap because it breaks on the first
name.startswith(f"{plugin_name}-") match; change the logic to find the best
(longest) matching plugin name instead of breaking early: iterate over
list_plugins() and track the plugin with the longest matching prefix for the
given name, compute cmd_name and src from that selected plugin (using
PLUGINS_DIR, cmd_name, src, pairs as in the diff), and only append if the best
match yields src.is_file(); apply the same longest-prefix selection fix to the
analogous block around lines 293-299.
In `@tools/generate.py`:
- Line 37: The Antigravity clean targets list variable (the mapping that
includes the "antigravity" key) is missing the ".agent/skills" path while
prune_orphans() scans that directory; update the "antigravity" array to include
".agent/skills" so --clean removes those artifacts as well—locate the
"antigravity" list in generate.py (the entry currently containing
".antigravity/agents", ".antigravity/skills", ".antigravity/workflows",
".agent/workflows", ".agents/workflows", ".agents/skills") and add the missing
".agent/skills" string to that list.
In `@tools/validate_generated.py`:
- Around line 732-734: The validation currently lets a present-but-null
description pass because it only checks desc is not None before validating;
change the condition to treat a key present with None as invalid by checking
membership and content: use the presence of "description" in data (e.g., if
"description" in data and (not isinstance(desc, str) or not desc.strip())) so
that desc == None triggers report.add; update the check around desc, data, and
report.add accordingly.
---
Outside diff comments:
In `@tools/install_antigravity.py`:
- Line 147: The CLI parser currently restricts the "action" argument to only
("install", "uninstall") in the parser.add_argument call; update that call to
include "list" (e.g., choices=("install","uninstall","list")) so the script
supports the list subcommand required by the install helper contract, and ensure
any action-handling code in functions like the action dispatcher recognizes and
handles the "list" case.
---
Duplicate comments:
In `@docs/harnesses.md`:
- Line 18: Unify the Antigravity command support documentation by making the
matrix row for "Antigravity CLI" and the descriptive paragraphs about command
handling consistent: update the table cell that currently lists
`.antigravity/agents/, .antigravity/skills/, .antigravity/workflows/` (the
"Antigravity CLI" row) and the paragraphs mentioning "workflow emission", "no
slash commands", and "converted to skill" so they all state the same contract
(e.g., that Antigravity emits workflow-based slash commands via
`.antigravity/workflows/`), and adjust the wording in the sections referencing
"workflow emission" and "converted to skill" to reflect that slash commands are
emitted as workflows rather than absent or merely converted to skills.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f59095a2-7970-4331-a15f-b69cb97a9497
📒 Files selected for processing (8)
docs/harnesses.mddocs/round-trip-results.mdtools/adapters/antigravity.pytools/adapters/capabilities.pytools/doc_gardener.pytools/generate.pytools/install_antigravity.pytools/validate_generated.py
✅ Files skipped from review due to trivial changes (2)
- tools/adapters/capabilities.py
- docs/round-trip-results.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use 'ruff' for linting and formatting (not black or other formatters)
Use 'ty' for type checking (not mypy)
Files:
tools/doc_gardener.pytools/generate.pytools/validate_generated.pytools/adapters/antigravity.pytools/install_antigravity.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:26:30.376Z
Learning: Never commit secrets to the repository
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:26:30.376Z
Learning: Never run destructive git operations (force-push, reset --hard, branch -D) without explicit ask
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T20:26:30.376Z
Learning: Generated artifacts are gitignored and must never be hand-edited; source-of-truth lives only under plugins/
🔇 Additional comments (1)
tools/adapters/antigravity.py (1)
156-160: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tools/adapters/antigravity.py (1)
3-18:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix import ordering to unblock CI (Ruff I001).
Ruff is failing on this import block, so this PR cannot merge until imports are normalized.
Suggested fix
from __future__ import annotations import json import re from pathlib import Path from tools.adapters.base import ( AgentSource, CommandSource, EmitResult, HarnessAdapter, PluginSource, SkillSource, h1_from_body, ) from tools.adapters.capabilities import TOOL_NAME_MAPS, resolve_modelAs per coding guidelines: "
**/*.py: Use ... ruff for linting/formatting".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/adapters/antigravity.py` around lines 3 - 18, The import block in antigravity.py must be reordered to satisfy Ruff (I001): keep the from __future__ import at top, then standard-library imports (json, re, Path from pathlib) grouped and alphabetized, then third-party (none here), then local application imports; move the tools.adapters.base imports (AgentSource, CommandSource, EmitResult, HarnessAdapter, PluginSource, SkillSource, h1_from_body) together and alphabetize the names, and finally the tools.adapters.capabilities imports (TOOL_NAME_MAPS, resolve_model) as the last group so Ruff’s import-order rule passes.
♻️ Duplicate comments (1)
tools/doc_gardener.py (1)
280-287:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid breaking on first prefix match when source file does not exist.
Line 286andLine 306break on the first matching plugin prefix even whensrcis missing, which can miss valid mappings for overlapping names (e.g.,datavsdata-analysis) and hide stale artifacts.Suggested fix
for plugin_name in sorted(plugin_names, key=len, reverse=True): if name.startswith(f"{plugin_name}-"): cmd_name = name[len(plugin_name) + 1 :] src = PLUGINS_DIR / plugin_name / "commands" / f"{cmd_name}.md" if src.is_file(): pairs.append((src, workflow_md)) - break + break @@ for plugin_name in sorted(plugin_names, key=len, reverse=True): if name.startswith(f"{plugin_name}-"): cmd_name = name[len(plugin_name) + 1 :] src = PLUGINS_DIR / plugin_name / "commands" / f"{cmd_name}.md" if src.is_file(): pairs.append((src, f)) - break + breakAlso applies to: 300-307
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/doc_gardener.py` around lines 280 - 287, The loop over plugin_names currently breaks on the first prefix match regardless of whether the constructed source file exists, which skips checking longer/overlapping plugin prefixes; update the logic in the block using plugin_names, name.startswith(...) and constructing cmd_name/ src (the PLUGINS_DIR / plugin_name / "commands" / f"{cmd_name}.md" path) so that you only break after appending to pairs (pairs.append((src, workflow_md))) — i.e., if src.is_file() is false, continue the loop to try other matching prefixes instead of breaking; apply the same fix to the other identical block that builds src and appends to pairs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tools/install_antigravity.py`:
- Around line 155-160: In list_installed (tools/install_antigravity.py) the else
branch that prints foreign symlinks (the f" foreign: {subdir}/{dst.name} ->
{target}" line) never updates the report counters; modify that branch to
increment the appropriate counter (report.skipped += 1) so _print_report()
reflects the foreign total correctly, keeping the print statement and report
variable as-is.
---
Outside diff comments:
In `@tools/adapters/antigravity.py`:
- Around line 3-18: The import block in antigravity.py must be reordered to
satisfy Ruff (I001): keep the from __future__ import at top, then
standard-library imports (json, re, Path from pathlib) grouped and alphabetized,
then third-party (none here), then local application imports; move the
tools.adapters.base imports (AgentSource, CommandSource, EmitResult,
HarnessAdapter, PluginSource, SkillSource, h1_from_body) together and
alphabetize the names, and finally the tools.adapters.capabilities imports
(TOOL_NAME_MAPS, resolve_model) as the last group so Ruff’s import-order rule
passes.
---
Duplicate comments:
In `@tools/doc_gardener.py`:
- Around line 280-287: The loop over plugin_names currently breaks on the first
prefix match regardless of whether the constructed source file exists, which
skips checking longer/overlapping plugin prefixes; update the logic in the block
using plugin_names, name.startswith(...) and constructing cmd_name/ src (the
PLUGINS_DIR / plugin_name / "commands" / f"{cmd_name}.md" path) so that you only
break after appending to pairs (pairs.append((src, workflow_md))) — i.e., if
src.is_file() is false, continue the loop to try other matching prefixes instead
of breaking; apply the same fix to the other identical block that builds src and
appends to pairs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c147d5a0-a87a-497e-ba80-afae86b9881a
📒 Files selected for processing (30)
.gitignoreAGENTS.mdMakefileREADME.mddocs/authoring.mddocs/harnesses.mdtools/adapters/antigravity.pytools/adapters/base.pytools/adapters/codex.pytools/adapters/copilot.pytools/adapters/cursor.pytools/adapters/gemini.pytools/adapters/opencode.pytools/check_agent_name_collisions.pytools/doc_gardener.pytools/generate.pytools/install_antigravity.pytools/install_opencode.pytools/tests/conftest.pytools/tests/test_adapters.pytools/tests/test_cli_smoke.pytools/tests/test_doc_gardener.pytools/tests/test_install_antigravity.pytools/tests/test_install_copilot.pytools/tests/test_install_opencode.pytools/tests/test_real_world.pytools/tests/test_round_trip.pytools/tests/test_validate_generated.pytools/validate_generated.pytools/yt-design-extractor/yt-design-extractor.py
✅ Files skipped from review due to trivial changes (18)
- tools/tests/test_install_opencode.py
- tools/adapters/cursor.py
- tools/check_agent_name_collisions.py
- tools/tests/conftest.py
- tools/adapters/copilot.py
- tools/tests/test_install_copilot.py
- AGENTS.md
- tools/adapters/gemini.py
- docs/authoring.md
- tools/tests/test_cli_smoke.py
- tools/adapters/codex.py
- tools/adapters/opencode.py
- tools/yt-design-extractor/yt-design-extractor.py
- tools/install_opencode.py
- tools/tests/test_doc_gardener.py
- tools/tests/test_real_world.py
- .gitignore
- README.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use uv for Python package management (not pip), ruff for linting/formatting (not black), and ty for type checking (not mypy)
Files:
tools/tests/test_install_antigravity.pytools/adapters/base.pytools/tests/test_round_trip.pytools/generate.pytools/install_antigravity.pytools/validate_generated.pytools/adapters/antigravity.pytools/doc_gardener.pytools/tests/test_validate_generated.pytools/tests/test_adapters.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T21:27:56.295Z
Learning: Plugin names must use lowercase, hyphen-separated format; never use double underscores `__` (reserved for adapter namespace separator)
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T21:27:56.295Z
Learning: Never commit secrets; never run destructive git operations (force-push, reset --hard, branch -D) without explicit ask
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T21:27:56.295Z
Learning: Plugin source-of-truth lives only under plugins/; generated artifacts are gitignored and must never be hand-edited
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T21:27:56.295Z
Learning: Before pushing, run quality gates: make validate STRICT=1, make garden, make test, and make smoke-test
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-26T21:27:56.295Z
Learning: Read and follow portable-content style guide in docs/authoring.md before adding new plugins
🪛 GitHub Actions: Code Quality / 2_Python (ruff + ty).txt
tools/adapters/antigravity.py
[error] 3-18: ruff check failed (I001). Import block is un-sorted or un-formatted. Rule: I001. Tool: Ruff. Suggested: organize imports; 1 fixable with --fix.
🪛 GitHub Actions: Code Quality / Python (ruff + ty)
tools/adapters/antigravity.py
[error] 3-18: Ruff check failed: import block is un-sorted or un-formatted. File path reported: /home/runner/work/agents/agents/tools/adapters/antigravity.py:3:1. Help: Organize imports. (Found 1 error; 1 fixable with --fix.)
🔇 Additional comments (7)
docs/harnesses.md (1)
26-26: LGTM!Also applies to: 53-53
Makefile (1)
25-25: LGTM!tools/tests/test_install_antigravity.py (1)
72-75: LGTM!tools/adapters/base.py (1)
102-104: LGTM!Also applies to: 128-132, 359-361, 372-374, 382-384, 452-454, 464-466
tools/tests/test_round_trip.py (1)
83-85: LGTM!Also applies to: 151-153, 181-183, 187-192, 201-203, 236-238, 273-278, 289-291, 295-297, 329-333, 345-347, 360-362, 385-392, 403-405
tools/generate.py (1)
37-45: LGTM!Also applies to: 76-78
tools/validate_generated.py (1)
42-46: LGTM!Also applies to: 125-127, 639-644, 661-666, 705-875, 880-882, 886-888, 914-916
| if _is_relative_to(target, generated_root): | ||
| print(f" linked: {subdir}/{dst.name} -> {target}") | ||
| report.linked += 1 | ||
| else: | ||
| print(f" foreign: {subdir}/{dst.name} -> {target}") | ||
| return report |
There was a problem hiding this comment.
Increment foreign count in list_installed.
Foreign symlinks are printed on Line 159, but report.skipped is never incremented, so _print_report() shows an incorrect foreign= total.
Suggested fix
if _is_relative_to(target, generated_root):
print(f" linked: {subdir}/{dst.name} -> {target}")
report.linked += 1
else:
print(f" foreign: {subdir}/{dst.name} -> {target}")
+ report.skipped += 1🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tools/install_antigravity.py` around lines 155 - 160, In list_installed
(tools/install_antigravity.py) the else branch that prints foreign symlinks (the
f" foreign: {subdir}/{dst.name} -> {target}" line) never updates the report
counters; modify that branch to increment the appropriate counter
(report.skipped += 1) so _print_report() reflects the foreign total correctly,
keeping the print statement and report variable as-is.
|
Need to clean up some extra files that were added in my last commit |
1562530 to
f1c3abf
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tools/validate_generated.py (1)
710-721:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd frontmatter validation before accessing
fm.get("name").Unlike the workflow validation below (lines 841-849) and other validators in this file (e.g., Codex at line 167, OpenCode at line 481), the skills validation doesn't check for missing/invalid frontmatter before accessing
fm.get("name"). This produces a misleading error message like "frontmatter name None != directory 'demo-skill'" instead of the clearer "missing or invalid frontmatter".Suggested fix
if skills_dir.is_dir(): for skill_md in skills_dir.glob("*/SKILL.md"): content = skill_md.read_text(encoding="utf-8") fm, _ = parse_frontmatter(content) + if not fm: + report.add( + severity="error", + harness="antigravity", + path=skill_md, + message="missing or invalid frontmatter", + remediation="SKILL.md must start with `---\\nname: ...\\n---`.", + ) + continue if fm.get("name") != skill_md.parent.name:🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/validate_generated.py` around lines 710 - 721, The skills validator reads frontmatter via parse_frontmatter(skill_md.read_text()) then unconditionally compares fm.get("name") to the directory name, which yields confusing messages when frontmatter is missing or invalid. Before accessing fm.get("name") in the loop over skills_dir.glob("*/SKILL.md"), validate that fm is a dict and that "name" exists/non-empty; if not, call report.add (same pattern/severity/harness/path/remediation used elsewhere) with a clear message like "missing or invalid frontmatter" and skip the name comparison for that file. Ensure you reference skill_md and use the existing report.add signature so behavior is consistent with other validators.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tools/validate_generated.py`:
- Around line 763-771: The current validation treats missing `hidden` as error
because isinstance(None, bool) is False; change the check to allow the field to
be optional by replacing the condition with a nil-aware check such as: only call
report.add when `hidden is not None and not isinstance(hidden, bool)` so that
absent `hidden` passes, leaving the required fields tuple unchanged; locate the
validation block that uses `hidden`, `agent_json_path`, and `report.add` in
validate_generated.py and update the conditional accordingly.
---
Outside diff comments:
In `@tools/validate_generated.py`:
- Around line 710-721: The skills validator reads frontmatter via
parse_frontmatter(skill_md.read_text()) then unconditionally compares
fm.get("name") to the directory name, which yields confusing messages when
frontmatter is missing or invalid. Before accessing fm.get("name") in the loop
over skills_dir.glob("*/SKILL.md"), validate that fm is a dict and that "name"
exists/non-empty; if not, call report.add (same
pattern/severity/harness/path/remediation used elsewhere) with a clear message
like "missing or invalid frontmatter" and skip the name comparison for that
file. Ensure you reference skill_md and use the existing report.add signature so
behavior is consistent with other validators.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 976a5613-c2b9-4dd7-9735-faeed79e1a4c
📒 Files selected for processing (13)
.gitignoreAGENTS.mdMakefileREADME.mddocs/authoring.mddocs/harnesses.mdtools/adapters/antigravity.pytools/doc_gardener.pytools/generate.pytools/install_antigravity.pytools/tests/test_adapters.pytools/validate_generated.pytools/yt-design-extractor/yt-design-extractor.py
✅ Files skipped from review due to trivial changes (5)
- AGENTS.md
- .gitignore
- docs/harnesses.md
- README.md
- tools/yt-design-extractor/yt-design-extractor.py
🚧 Files skipped from review as they are similar to previous changes (7)
- docs/authoring.md
- tools/generate.py
- Makefile
- tools/adapters/antigravity.py
- tools/tests/test_adapters.py
- tools/doc_gardener.py
- tools/install_antigravity.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use
rufffor linting and formatting (not black or other formatters)Use
tyfor type checking (not mypy)
Files:
tools/validate_generated.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T12:57:22.027Z
Learning: Never commit secrets to the repository
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T12:57:22.027Z
Learning: Never run destructive git operations (force-push, `reset --hard`, `branch -D`) without explicit ask
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T12:57:22.027Z
Learning: Run `make validate STRICT=1`, `make garden`, `make test`, and `make smoke-test` before pushing
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T12:57:22.027Z
Learning: Generated artifacts under harness-specific directories (`.codex/`, `.cursor/`, `.opencode/`, etc.) are gitignored and auto-generated—never hand-edit them
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T12:57:22.027Z
Learning: Document authoring conventions and plugin style guidelines in `docs/authoring.md` before adding new plugins
🔇 Additional comments (3)
tools/validate_generated.py (3)
42-46: LGTM!Also applies to: 125-127, 639-666, 880-888, 914-916
723-834: LGTM!
836-876: LGTM!
| hidden = data.get("hidden") | ||
| if not isinstance(hidden, bool): | ||
| report.add( | ||
| severity="error", | ||
| harness="antigravity", | ||
| path=agent_json_path, | ||
| message="`hidden` must be a boolean", | ||
| remediation="Set `hidden` to false (or true) in agent.json.", | ||
| ) |
There was a problem hiding this comment.
hidden validation inconsistent with required fields list.
The hidden field is not in the required fields list (lines 737-743), but this validation reports an error if hidden is missing (since isinstance(None, bool) is False). Either add "hidden" to the required fields tuple, or make this check optional-aware.
Option A: Add to required fields
for key in (
"name",
"displayName",
"description",
"model",
"customAgentSpec",
+ "hidden",
):Option B: Allow optional hidden
hidden = data.get("hidden")
- if not isinstance(hidden, bool):
+ if hidden is not None and not isinstance(hidden, bool):
report.add(📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| hidden = data.get("hidden") | |
| if not isinstance(hidden, bool): | |
| report.add( | |
| severity="error", | |
| harness="antigravity", | |
| path=agent_json_path, | |
| message="`hidden` must be a boolean", | |
| remediation="Set `hidden` to false (or true) in agent.json.", | |
| ) | |
| hidden = data.get("hidden") | |
| if hidden is not None and not isinstance(hidden, bool): | |
| report.add( | |
| severity="error", | |
| harness="antigravity", | |
| path=agent_json_path, | |
| message="`hidden` must be a boolean", | |
| remediation="Set `hidden` to false (or true) in agent.json.", | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tools/validate_generated.py` around lines 763 - 771, The current validation
treats missing `hidden` as error because isinstance(None, bool) is False; change
the check to allow the field to be optional by replacing the condition with a
nil-aware check such as: only call report.add when `hidden is not None and not
isinstance(hidden, bool)` so that absent `hidden` passes, leaving the required
fields tuple unchanged; locate the validation block that uses `hidden`,
`agent_json_path`, and `report.add` in validate_generated.py and update the
conditional accordingly.
f1c3abf to
d900f7d
Compare
- Add Antigravity CLI adapter, installer, and tests - Add Antigravity CLI references to documentation - Gitignore .agents/ (OpenCode) and .agent/ (Cursor) artifacts
d900f7d to
89beaec
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
docs/authoring.md (1)
108-110:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix the model-alias table separator width.
Line 109 has one extra separator cell, so the table column count is inconsistent.
Suggested fix
-|---|---|---|---|---|---|---|---| +|---|---|---|---|---|---|---|🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/authoring.md` around lines 108 - 110, The table's separator row has one extra cell causing a column mismatch: replace the current separator row string "|---|---|---|---|---|---|---|---|" with exactly seven separators to match the header (e.g. "|---|---|---|---|---|---|---|") so the header row ("| Source field | Codex | Cursor | OpenCode | Gemini | Copilot | Antigravity CLI |") and the data row ("| `model: opus` | `gpt-5` | `inherit` | `anthropic/claude-opus-4-7` | `gemini-2.5-pro` | `gpt-5` | `gemini-2.5-pro` |") all have the same number of columns.
🧹 Nitpick comments (2)
tools/tests/test_validate_generated.py (1)
488-493: ⚡ Quick winMake the name-mismatch fixture otherwise valid.
This test should fail only on the directory/name mismatch. Line 492 currently omits additional fields, which can couple it to unrelated validator behavior.
Suggested fix
(tmp_path / ".antigravity" / "agents" / "demo-agent" / "agent.json").write_text( - '{"name": "wrong-agent", "displayName": "Demo", "description": "Desc", "customAgentSpec": {}}' + json.dumps( + { + "name": "wrong-agent", + "displayName": "Demo", + "description": "Desc", + "hidden": False, + "model": "gemini-2.5-pro", + "customAgentSpec": {}, + } + ) )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/tests/test_validate_generated.py` around lines 488 - 493, The agent.json fixture in test_agent_name_mismatch_errors must be a valid agent manifest except for the name mismatch so the test isolates that error; update the JSON written to (.antigravity/agents/demo-agent/agent.json) in test_agent_name_mismatch_errors to include the full minimal required manifest fields (keep "name": "wrong-agent" to trigger the mismatch) such as "displayName", "description", "customAgentSpec" and any required metadata like "schemaVersion" and "version" (or other keys your validator expects) so the only failing condition is the directory/name mismatch.tools/tests/test_round_trip.py (1)
345-351: ⚡ Quick winAdd an explicit Antigravity workflow count assertion.
These tests validate agents and skills, but they don’t currently fail when
.antigravity/workflowsemission regresses.Suggested addition
class TestAntigravityRoundTrip: @@ def test_antigravity_skill_count_matches_source(self): n = len(list((WORKTREE / ".antigravity" / "skills").glob("*/SKILL.md"))) expected = _source_skill_count() + _source_command_count() assert n == expected, ( f"skill count mismatch: source_skills={_source_skill_count()} " f"source_commands={_source_command_count()} expected={expected} antigravity={n}" ) + + def test_antigravity_workflow_count_matches_source_commands(self): + n = len(list((WORKTREE / ".antigravity" / "workflows").glob("*.md"))) + assert n == _source_command_count(), ( + f"workflow count mismatch: source_commands={_source_command_count()} antigravity={n}" + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/tests/test_round_trip.py` around lines 345 - 351, Add an explicit assertion that the emitted .antigravity/workflows count matches the source workflow count: in or next to test_antigravity_skill_count_matches_source compute n_workflows = len(list((WORKTREE / ".antigravity" / "workflows").glob("*/WORKFLOW.md"))) (or similar pattern used for skills), get expected_workflows = _source_workflow_count() (or add that helper if missing), and assert n_workflows == expected_workflows with a clear message (e.g., include values for _source_workflow_count() and n_workflows) so regression of emitted workflows will fail the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/authoring.md`:
- Line 143: Update the docs table entry that currently lists Antigravity
emitting `.antigravity/commands/` so it shows the correct output path
`.antigravity/workflows/`; locate the table row containing "Slash commands |
Codex converts to skills. Gemini transpiles to TOML. Copilot emits
`.copilot/commands/` prompt files. Antigravity emits `.antigravity/commands/`
SKILL.md files." and change the Antigravity path fragment to
`.antigravity/workflows/`.
---
Duplicate comments:
In `@docs/authoring.md`:
- Around line 108-110: The table's separator row has one extra cell causing a
column mismatch: replace the current separator row string
"|---|---|---|---|---|---|---|---|" with exactly seven separators to match the
header (e.g. "|---|---|---|---|---|---|---|") so the header row ("| Source field
| Codex | Cursor | OpenCode | Gemini | Copilot | Antigravity CLI |") and the
data row ("| `model: opus` | `gpt-5` | `inherit` | `anthropic/claude-opus-4-7` |
`gemini-2.5-pro` | `gpt-5` | `gemini-2.5-pro` |") all have the same number of
columns.
---
Nitpick comments:
In `@tools/tests/test_round_trip.py`:
- Around line 345-351: Add an explicit assertion that the emitted
.antigravity/workflows count matches the source workflow count: in or next to
test_antigravity_skill_count_matches_source compute n_workflows =
len(list((WORKTREE / ".antigravity" / "workflows").glob("*/WORKFLOW.md"))) (or
similar pattern used for skills), get expected_workflows =
_source_workflow_count() (or add that helper if missing), and assert n_workflows
== expected_workflows with a clear message (e.g., include values for
_source_workflow_count() and n_workflows) so regression of emitted workflows
will fail the test.
In `@tools/tests/test_validate_generated.py`:
- Around line 488-493: The agent.json fixture in test_agent_name_mismatch_errors
must be a valid agent manifest except for the name mismatch so the test isolates
that error; update the JSON written to
(.antigravity/agents/demo-agent/agent.json) in test_agent_name_mismatch_errors
to include the full minimal required manifest fields (keep "name": "wrong-agent"
to trigger the mismatch) such as "displayName", "description", "customAgentSpec"
and any required metadata like "schemaVersion" and "version" (or other keys your
validator expects) so the only failing condition is the directory/name mismatch.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: cdd65842-28a3-48f3-b20f-50918fd25ab8
📒 Files selected for processing (21)
.gitignoreAGENTS.mdARCHITECTURE.mdCONTRIBUTING.mdMakefileREADME.mddocs/authoring.mddocs/harnesses.mddocs/round-trip-results.mdtools/adapters/antigravity.pytools/adapters/base.pytools/adapters/capabilities.pytools/doc_gardener.pytools/generate.pytools/install_antigravity.pytools/tests/test_adapters.pytools/tests/test_install_antigravity.pytools/tests/test_round_trip.pytools/tests/test_validate_generated.pytools/validate_generated.pytools/yt-design-extractor/yt-design-extractor.py
✅ Files skipped from review due to trivial changes (6)
- CONTRIBUTING.md
- AGENTS.md
- docs/harnesses.md
- ARCHITECTURE.md
- docs/round-trip-results.md
- .gitignore
🚧 Files skipped from review as they are similar to previous changes (9)
- README.md
- tools/yt-design-extractor/yt-design-extractor.py
- tools/doc_gardener.py
- tools/tests/test_install_antigravity.py
- tools/adapters/capabilities.py
- tools/install_antigravity.py
- tools/validate_generated.py
- tools/adapters/antigravity.py
- tools/tests/test_adapters.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use
rufffor linting and formatting instead of black/pylintUse
tyfor type checking instead of mypy
Files:
tools/adapters/base.pytools/generate.pytools/tests/test_round_trip.pytools/tests/test_validate_generated.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T15:47:48.243Z
Learning: Never commit secrets to the repository
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T15:47:48.243Z
Learning: Never run destructive git operations (force-push, `reset --hard`, `branch -D`) without explicit request
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T15:47:48.243Z
Learning: Generated artifacts in per-harness directories (`.codex/`, `.cursor/`, `.opencode/`, `.gemini/`, `.antigravity/`) are auto-generated and must never be hand-edited
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T15:47:48.243Z
Learning: Source-of-truth for all plugins, skills, and agents lives only under `plugins/` directory structure
Learnt from: CR
Repo: wshobson/agents
Timestamp: 2026-05-27T15:47:48.243Z
Learning: This repository should maintain a short, map-style README/AGENTS.md file (max ~150 lines) per OpenAI harness-engineering practices, with detail delegated to `docs/` and skills
🪛 checkmake (0.3.2)
Makefile
[warning] 21-21: Target body for "help" exceeds allowed length of 5 lines (11).
(maxbodylength)
[warning] 20-20: Required target "all" is missing from the Makefile.
(minphony)
🔇 Additional comments (3)
tools/adapters/base.py (1)
289-296: LGTM!tools/generate.py (1)
37-45: LGTM!Also applies to: 68-71, 76-78, 178-187, 220-220
Makefile (1)
19-19: LGTM!Also applies to: 25-25, 34-35, 167-167, 237-243
- Add TestAntigravitySmoke in test_cli_smoke.py using agy plugin import - Isolate HOME to temp dir to avoid polluting real config - Update docs/round-trip-results.md: real CLI version, updated recipe - Add agy install step to CI workflow via antigravity.google/cli/install.sh
…igravity adapter The agy CLI reads from the Gemini-format (root skills/agents/commands + gemini-extension.json), not from .antigravity/, .agent/, or .agents/. These extra-write paths were duplicates/subsets meant for IDE/2.0 discovery only. Removed: - tools/generate.py: simplify _HARNESS_TARGETS to 3 paths - tools/adapters/antigravity.py: drop extra-write loops - tools/doc_gardener.py: drop stale detection for extra paths - tools/adapters/capabilities.py: update notes
- ARCHITECTURE.md: fix output path (.antigravity/workflows/, not /commands/) - ARCHITECTURE.md: update CI job description (include Antigravity) - AGENTS.md: add missing GitHub Copilot to harness list; update CI description - CONTRIBUTING.md: include Antigravity in smoke-test comment - Makefile: include agy in smoke-test CLI list; update CI description - docs/authoring.md: fix Antigravity slash command output path
|
Thanks — the adapter integration is solid and agy demonstrably runs in CI. To get this moving again:
Happy to re-review after a rebase. |
Summary
Add Antigravity CLI as a sixth harness in the multi-harness adapter framework. Introduces a new adapter (
tools/adapters/antigravity.py) that transpiles the canonicalplugins/<name>/source-of-truth into Antigravity-native formats, plus supporting infrastructure: install/uninstall workflow, drift detection, validation, and tests.Impact: 15 files changed (+937/−37), 2 commits
Risk: 🟢 Low — isolated to new adapter + harness plumbing
Review: ~15 min
What Changed
Source — New Adapter
tools/adapters/antigravity.pyagent.jsonper subagent,SKILL.mdper skill. Maps Claude model aliases to Gemini model IDstools/adapters/capabilities.pytools/adapters/base.pyAgentSource.modelpropertytools/generate.pytools/validate_generated.pyvalidate_antigravity()— schema checks for agent.json, skill frontmattertools/doc_gardener.pyInstall/Uninstall
tools/install_antigravity.pyMakefileTests
tools/tests/test_adapters.pytools/tests/test_round_trip.pytools/tests/test_validate_generated.pytools/tests/test_install_antigravity.pyDocs
docs/harnesses.mdAGENTS.md.gitignoreDesign
Follows the Copilot adapter pattern:
plugins/<p>/agents/<a>.md->.antigravity/agents/<p>__<a>/agent.jsonwith Gemini model IDs, tool allowlists, customAgentSpecplugins/<p>/skills/<s>/SKILL.md->.antigravity/skills/<p>__<s>/SKILL.mdplugins/<p>/commands/<c>.md->.antigravity/skills/<p>-<c>/SKILL.md(hyphen naming)Checklist
Test Plan
Risk Assessment
Overall: Low
Related issue(s)
Closes #560