feat(#2096): migrate Antigravity onto EoS declarative adapter + permission-writer + MCP companion (ADR-1239)

Fold all antigravity literal branches into descriptor-driven reads:
getConfigDirFromHome (→ configHome.kind 'dot-home-nested'), projectLocalHookPrefix
(→ hostBehaviors.hookPathStyle 'raw'), applyAgentPathRewrites (→ noPathRewrite),
getProjectInstructionFile (→ projectInstructionFile 'GEMINI.md'); removed the dead
inline convertClaudeAgentToAntigravityAgent branch + dead isAntigravity
destructures (antigravity is already on the descriptor-agents path). subagentToolkit
flipped undocumented→full (Context7: antigravity.google/docs/cli/features);
namedDispatch/nested/maxDepth/backgroundDispatch stay undocumented. Byte-identical
golden parity for all 16 runtimes.

UPGRADE 1 (permission-writer): permissionWriter 'antigravity' + configureAntigravityPermissions
merges a scoped permissions.allow block (GSD's own tree + hooks) into Antigravity's
settings.json — non-destructive, idempotent, symmetric uninstall. Added to
VALID_PERMISSION_WRITERS + the FinishPermissionWriter union.
UPGRADE 2 (MCP companion): configureAntigravityMcpConfig writes mcp_config.json
registering the gsd-core companion MCP server (Gemini-successor mcpServers schema,
best-effort — raw schema unpublished). Both writers dispatch from finishInstall.
settings.json is golden-excluded (HOOK_CONFIG_FILES); mcp_config.json (portable,
no absolute paths) is golden-tracked → only antigravity.json changes.

Tests: declarative-reference-antigravity extended (source-grep guard across 4
modules, fail-closed for the 4 undocumented sub-axes, validator acceptance) +
antigravity-upgrades (permission-writer + mcp_config live-install, idempotency,
user-preservation). Matrix + ADR-1016 + capability-manifest + CONTEXT.md +
connect-gsd-mcp-server docs updated; changeset (Changed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-11 02:27:57 -04:00
parent e3a8c063b8
commit 5695522d5f
19 changed files with 800 additions and 48 deletions

View File

@@ -343,9 +343,14 @@ describe('bug #1906: local hook commands use $CLAUDE_PROJECT_DIR', () => {
* dir as cwd. Claude Code and others still use "$CLAUDE_PROJECT_DIR"/ (#1906).
*
* #1928: Google sunset Gemini CLI (2026-06-18) and the `gemini` runtime was
* removed from GSD entirely. `projectLocalHookPrefix` now special-cases only
* `antigravity` — an unrecognized runtime string like the former `'gemini'`
* falls through to the default $CLAUDE_PROJECT_DIR-anchored prefix.
* removed from GSD entirely.
*
* #2096: `projectLocalHookPrefix` no longer special-cases `antigravity` by
* name — it branches on the caller-supplied `hookPathStyle` (sourced from
* the runtime's `hostBehaviors.hookPathStyle` descriptor field). An
* unrecognized runtime string like the former `'gemini'`, or any runtime
* that doesn't declare `hookPathStyle: 'raw'`, falls through to the default
* $CLAUDE_PROJECT_DIR-anchored prefix.
*/
const { describe, test } = require('node:test');
@@ -357,7 +362,13 @@ const { projectLocalHookPrefix, projectShellCommandText } = projection;
describe('bug #2557: Antigravity local hooks use relative paths (not $CLAUDE_PROJECT_DIR); gemini runtime removed (#1928)', () => {
test('Antigravity local prefix is bare dirName', () => {
assert.equal(projectLocalHookPrefix({ runtime: 'antigravity', dirName: '.agents' }), '.agents');
// #2096: hookPathStyle is now the caller-supplied descriptor value
// (bin/install.js resolves it from hostBehaviors.hookPathStyle); the
// function itself no longer knows the runtime name 'antigravity'.
assert.equal(
projectLocalHookPrefix({ runtime: 'antigravity', dirName: '.agents', hookPathStyle: 'raw' }),
'.agents',
);
});
test('non-Antigravity local prefix remains $CLAUDE_PROJECT_DIR anchored', () => {
@@ -512,7 +523,13 @@ describe('bug #3439: shell projection module owns managed-hook policy and legacy
});
test('projectLocalHookPrefix centralizes runtime-specific project-dir interpolation policy', () => {
assert.equal(projectLocalHookPrefix({ runtime: 'antigravity', dirName: '.agents' }), '.agents');
// #2096: 'raw' hookPathStyle (descriptor-driven) is what produces the
// bare-dirName behavior now — the function no longer branches on the
// 'antigravity' runtime name itself.
assert.equal(
projectLocalHookPrefix({ runtime: 'antigravity', dirName: '.agents', hookPathStyle: 'raw' }),
'.agents',
);
assert.equal(
projectLocalHookPrefix({ runtime: 'claude', dirName: '.claude' }),
'"$CLAUDE_PROJECT_DIR"/.claude',