* fix(#503): detect local Antigravity (.agent) installs in /gsd:update The installer places local Antigravity installs in ./.agent/ (bin/install.js getDirName('antigravity') === '.agent'), but the /gsd:update detection cascade in update.md only knew the global Antigravity layout (.gemini/antigravity{,-ide,-cli}). A local .agent install fell through to the `Otherwise -> claude` default, so the update refreshed Claude artifacts instead of the Antigravity install. Add `.agent` -> antigravity to all four runtime-dir surfaces in update.md: the execution_context path classifier, the RUNTIME_DIRS candidate array, the local-scope discovery loop, and the post-update cache-clear loop (the last otherwise left a stale update indicator on local Antigravity installs). Note: the issue also cited update-context.cjs, which does not exist on `next` (it is introduced by the still-open PR #499). The same .agent fix should be carried into update-context.cjs when #499 lands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#503): add changeset for Antigravity .agent detection fix Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
5
.changeset/503-antigravity-agent-local-detection.md
Normal file
5
.changeset/503-antigravity-agent-local-detection.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 512
|
||||
---
|
||||
**`/gsd:update` now detects local Antigravity (`.agent`) installs** — local Antigravity installs live in `./.agent/`, but the update detection cascade in `update.md` only knew the global `.gemini/antigravity{,-ide,-cli}` layout, so a local install was misclassified as `claude` and refreshed Claude artifacts instead. `.agent` → antigravity is now mapped across all four runtime-dir surfaces (path classifier, `RUNTIME_DIRS`, local-scope discovery loop, and the post-update cache-clear loop). (#503)
|
||||
@@ -17,6 +17,7 @@ First, derive `PREFERRED_CONFIG_DIR` and `PREFERRED_RUNTIME` from the invoking p
|
||||
- Path contains `/.gemini/antigravity-ide/` -> `antigravity`
|
||||
- Path contains `/.gemini/antigravity-cli/` -> `antigravity`
|
||||
- Path contains `/.gemini/antigravity/` -> `antigravity`
|
||||
- Path contains `/.agent/` -> `antigravity` (local Antigravity install dir; see bin/install.js getDirName('antigravity'))
|
||||
- Path contains `/.gemini/` -> `gemini`
|
||||
- Path contains `/.config/kilo/` or `/.kilo/`, or `PREFERRED_CONFIG_DIR` contains `kilo.json` / `kilo.jsonc` -> `kilo`
|
||||
- Path contains `/.config/opencode/` or `/.opencode/`, or `PREFERRED_CONFIG_DIR` contains `opencode.json` / `opencode.jsonc` -> `opencode`
|
||||
@@ -39,7 +40,7 @@ expand_home() {
|
||||
# Using an array instead of a space-separated string ensures correct
|
||||
# iteration in both bash and zsh (zsh does not word-split unquoted
|
||||
# variables by default). Fixes #1173.
|
||||
RUNTIME_DIRS=( "claude:.claude" "opencode:.config/opencode" "opencode:.opencode" "antigravity:.gemini/antigravity-ide" "antigravity:.gemini/antigravity-cli" "antigravity:.gemini/antigravity" "gemini:.gemini" "kilo:.config/kilo" "kilo:.kilo" "codex:.codex" )
|
||||
RUNTIME_DIRS=( "claude:.claude" "opencode:.config/opencode" "opencode:.opencode" "antigravity:.gemini/antigravity-ide" "antigravity:.gemini/antigravity-cli" "antigravity:.gemini/antigravity" "antigravity:.agent" "gemini:.gemini" "kilo:.config/kilo" "kilo:.kilo" "codex:.codex" )
|
||||
ENV_RUNTIME_DIRS=()
|
||||
|
||||
# PREFERRED_CONFIG_DIR / PREFERRED_RUNTIME should be set from execution_context
|
||||
@@ -100,7 +101,7 @@ if [ -n "$PREFERRED_CONFIG_DIR" ] && { [ -f "$PREFERRED_CONFIG_DIR/get-shit-done
|
||||
printf '%s' "$p"
|
||||
}
|
||||
normalized_preferred="$(normalize_path "$PREFERRED_CONFIG_DIR")"
|
||||
for dir in .claude .config/opencode .opencode .gemini/antigravity-ide .gemini/antigravity-cli .gemini/antigravity .gemini .config/kilo .kilo .codex; do
|
||||
for dir in .claude .config/opencode .opencode .gemini/antigravity-ide .gemini/antigravity-cli .gemini/antigravity .agent .gemini .config/kilo .kilo .codex; do
|
||||
resolved_local="$(cd "./$dir" 2>/dev/null && pwd)"
|
||||
normalized_local="$(normalize_path "$resolved_local")"
|
||||
if [ -n "$normalized_local" ] && [ "$normalized_local" = "$normalized_preferred" ]; then
|
||||
@@ -606,7 +607,7 @@ for dir in "${CACHE_DIRS[@]}"; do
|
||||
fi
|
||||
done
|
||||
|
||||
for dir in .claude .config/opencode .opencode .gemini/antigravity-ide .gemini/antigravity-cli .gemini/antigravity .gemini .config/kilo .kilo .codex; do
|
||||
for dir in .claude .config/opencode .opencode .gemini/antigravity-ide .gemini/antigravity-cli .gemini/antigravity .agent .gemini .config/kilo .kilo .codex; do
|
||||
rm -f "./$dir/cache/gsd-update-check.json"
|
||||
rm -f "$HOME/$dir/cache/gsd-update-check.json"
|
||||
done
|
||||
|
||||
75
tests/bug-503-update-agent-antigravity-detection.test.cjs
Normal file
75
tests/bug-503-update-agent-antigravity-detection.test.cjs
Normal file
@@ -0,0 +1,75 @@
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// update.md is a workflow file whose text IS the contract the runtime loads
|
||||
// and executes (the embedded bash detection cascade). Asserting on its text
|
||||
// tests the deployed behavior. Per CONTRIBUTING.md exception matrix.
|
||||
|
||||
/**
|
||||
* Bug #503: /gsd:update misclassifies local Antigravity (.agent) installs as claude
|
||||
*
|
||||
* The installer places a LOCAL Antigravity install in ./.agent/
|
||||
* (bin/install.js: getDirName('antigravity') === '.agent'). But the
|
||||
* /gsd:update detection cascade in get-shit-done/workflows/update.md only
|
||||
* knew the GLOBAL Antigravity layout (.gemini/antigravity{,-ide,-cli}), so a
|
||||
* local .agent install fell through to the `Otherwise -> claude` default and
|
||||
* the update refreshed Claude artifacts instead of the Antigravity install.
|
||||
*
|
||||
* The cascade has three coupled detection surfaces; .agent must be mapped to
|
||||
* antigravity in all three:
|
||||
* 1. the execution_context path classifier,
|
||||
* 2. the RUNTIME_DIRS candidate array,
|
||||
* 3. the LOCAL-scope discovery `for dir in ...` loop.
|
||||
*/
|
||||
|
||||
const { describe, test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const UPDATE_MD = fs.readFileSync(
|
||||
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'update.md'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('/gsd:update detects local Antigravity (.agent) installs (#503)', () => {
|
||||
test('execution_context classifier maps a /.agent/ path to antigravity', () => {
|
||||
// A rule line of the form: Path contains `/.agent/` -> `antigravity`
|
||||
const hasAgentClassifierRule =
|
||||
/\/\.agent\/[^\n]*->[^\n]*antigravity/.test(UPDATE_MD);
|
||||
assert.ok(
|
||||
hasAgentClassifierRule,
|
||||
'update.md classifier must map a `/.agent/` path to the `antigravity` runtime'
|
||||
);
|
||||
});
|
||||
|
||||
test('RUNTIME_DIRS candidate array includes antigravity:.agent', () => {
|
||||
const runtimeDirsLine = UPDATE_MD
|
||||
.split('\n')
|
||||
.find((l) => l.includes('RUNTIME_DIRS=('));
|
||||
assert.ok(runtimeDirsLine, 'RUNTIME_DIRS array must exist in update.md');
|
||||
assert.ok(
|
||||
runtimeDirsLine.includes('antigravity:.agent'),
|
||||
`RUNTIME_DIRS must contain "antigravity:.agent", got: ${runtimeDirsLine}`
|
||||
);
|
||||
});
|
||||
|
||||
test('every runtime-dir `for dir in` loop includes .agent', () => {
|
||||
// Both the LOCAL-scope discovery loop AND the post-update cache-clear loop
|
||||
// enumerate the runtime config dirs as a literal `.claude ... .codex` list.
|
||||
// The same root cause (.agent missing from the runtime-dir list) breaks
|
||||
// detection in the first and leaves a stale update indicator in the second,
|
||||
// so ALL such loops must include .agent.
|
||||
const runtimeDirLoops = UPDATE_MD
|
||||
.split('\n')
|
||||
.filter((l) => /for dir in .*\.claude.*\.codex/.test(l));
|
||||
assert.ok(
|
||||
runtimeDirLoops.length >= 2,
|
||||
`expected at least 2 runtime-dir loops in update.md, found ${runtimeDirLoops.length}`
|
||||
);
|
||||
for (const loop of runtimeDirLoops) {
|
||||
assert.ok(
|
||||
/(^|\s)\.agent(\s|$)/.test(loop),
|
||||
`every runtime-dir loop must include .agent, got: ${loop.trim()}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user