From ede090b23fb0ca25cd8d35b7d9879c649642e759 Mon Sep 17 00:00:00 2001 From: Thierry Kwiatkowski Date: Mon, 5 Oct 2026 17:52:41 +0200 Subject: [PATCH 1/2] feat(cli): add Antigravity CLI as a flat host for skills Teams moved from Gemini CLI to Antigravity CLI (agy) have no AIDD install. This adds an isolated `antigravity` flat profile that writes AIDD skills under `.agents/skills/`, from setup and from `translate --to antigravity --as flat`. agy 1.2.14 discovers a skill only directly under `.agents/skills/`: a probe at `.agents/skills///SKILL.md` logs no expansion, one at `.agents/skills//SKILL.md` logs `expanded slash command`. A flat profile can therefore declare a `single-level` skill layout, `skills/-/`, which the flat install now recognises; every other tool keeps the `nested` default. Hooks and agents stay unsupported until their own phases. The golden snapshot gains only the `antigravity:flat` cell. Refs #511 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 3 +- .../backlog-link.json | 5 + .../phase-2.md | 117 +++++++++++ .../phase-3.md | 90 +++++++++ .../phase-4.md | 82 ++++++++ .../phase-5.md | 79 ++++++++ .../2026_10_02_antigravity-flat-host/plan.md | 45 +++++ cli/aidd_docs/memory/codebase-map.md | 1 + cli/mutation-scopes.json | 5 + cli/package.json | 1 + cli/scripts/smoke-tools.sh | 2 +- .../built-tree-materialization-translator.ts | 15 +- .../domain/capabilities/plugins-capability.ts | 8 + .../profiles/antigravity/antigravity-paths.ts | 5 + .../domain/profiles/antigravity/build.ts | 33 ++++ .../domain/profiles/antigravity/profile.ts | 57 ++++++ .../translate/domain/content-translator.ts | 9 +- cli/src/kernel/tool.ts | 10 +- cli/src/presentation/commands/translate.ts | 2 +- cli/src/presentation/prompts/menu-use-case.ts | 6 +- cli/src/runtime/assets/asset-loader.ts | 1 + cli/src/runtime/wiring/framework.ts | 1 + cli/src/runtime/wiring/tools.ts | 1 + cli/src/runtime/wiring/translate.ts | 1 + .../tool-addition-cost.arch.test.ts | 12 +- .../clean-native-cache.integration.test.ts | 1 + ...list-installed-rules-use-case.unit.test.ts | 1 + .../uninstall-use-case.unit.test.ts | 2 +- .../plugin-asset-translation.unit.test.ts | 1 + .../diagnose-telemetry-use-case.unit.test.ts | 2 + .../read-local-cost-sweep.unit.test.ts | 13 ++ .../read-local-cost-use-case.unit.test.ts | 1 + .../report-cost-use-case.unit.test.ts | 12 ++ .../application/tool-attribution.unit.test.ts | 1 + .../domain/cost-report-envelope.unit.test.ts | 1 + .../domain/metrics-contract.unit.test.ts | 1 + ...metry-evidence-adapter.integration.test.ts | 1 + ...ild-hooks-support-declaration.unit.test.ts | 3 + ...plugin-root-token-declaration.unit.test.ts | 1 + .../profiles/antigravity/build.unit.test.ts | 33 ++++ .../profiles/antigravity/profile.unit.test.ts | 41 ++++ .../domain/registry-conformance.unit.test.ts | 8 +- .../telemetry-route-supply.unit.test.ts | 1 + .../tools/domain/tool-config.unit.test.ts | 4 +- ...egistry-reader-adapter.integration.test.ts | 1 + .../plugin-content-translator.unit.test.ts | 7 + ...clean-antigravity-foreign-file.e2e.test.ts | 48 +++++ .../cli-owns-read/expected-envelope.json | 14 ++ .../golden/framework-build-golden.e2e.test.ts | 14 +- .../snapshots/framework-build/golden.json | 184 ++++++++++++++++++ cli/tests/golden/snapshots/help/surface.json | 2 +- .../golden/snapshots/phase0/snapshot.json | 2 +- cli/tests/helpers/ports/build-unit-deps.ts | 1 + .../translate-wiring.integration.test.ts | 3 +- .../interactive-menu-use-case.unit.test.ts | 4 +- docs/MAINTAINERS.md | 2 +- ...e-real-user-scope-tool-list-parity.test.js | 2 +- 57 files changed, 970 insertions(+), 33 deletions(-) create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/backlog-link.json create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-2.md create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-3.md create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-4.md create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md create mode 100644 aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md create mode 100644 cli/src/contexts/tools/domain/profiles/antigravity/antigravity-paths.ts create mode 100644 cli/src/contexts/tools/domain/profiles/antigravity/build.ts create mode 100644 cli/src/contexts/tools/domain/profiles/antigravity/profile.ts create mode 100644 cli/tests/contexts/tools/domain/profiles/antigravity/build.unit.test.ts create mode 100644 cli/tests/contexts/tools/domain/profiles/antigravity/profile.unit.test.ts create mode 100644 cli/tests/e2e/clean-antigravity-foreign-file.e2e.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ee0bfacd..a47d29d32 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: contents: write strategy: fail-fast: false - # Four marketplace plus six flat — opencode and kilo are flat-only. Mirrors the CLI golden + # Four marketplace plus seven flat — opencode, kilo and antigravity are flat-only. Mirrors the CLI golden # snapshot matrix. matrix: include: @@ -168,6 +168,7 @@ jobs: - { tool: codex, mode: flat } - { tool: opencode, mode: flat } - { tool: kilo, mode: flat } + - { tool: antigravity, mode: flat } steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/backlog-link.json b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/backlog-link.json new file mode 100644 index 000000000..6f955dffc --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/backlog-link.json @@ -0,0 +1,5 @@ +{ + "backlog": "ai-driven-dev/framework#511", + "written_at": "2026-10-02T16:30:00Z", + "written_by": "aidd-dev:01-plan" +} diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-2.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-2.md new file mode 100644 index 000000000..3739aca29 --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-2.md @@ -0,0 +1,117 @@ +--- +status: done +--- + + + +# Instruction: `antigravity` profile with skills, registered everywhere, golden cell + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +cli/ +├── src/kernel/tool.ts ✏️ AiToolId union and AI_TOOL_IDS +├── src/contexts/framework/application/framework/translator/built-tree-materialization-translator.ts ✏️ recognise a skill at the profile's declared flat layout, not only `skills//…` +├── src/contexts/tools/domain/profiles/antigravity/ +│ ├── antigravity-paths.ts ✅ `.agents/` directory and skills dir constants +│ ├── profile.ts ✅ AiTool, flat plugins, no hooks yet, registerTool +│ └── build.ts ✅ flat contract: skills only, agents/hooks/mcp/rules/commands unsupported +├── src/runtime/wiring/{tools,framework,translate}.ts ✏️ side-effect profile import +├── src/runtime/assets/asset-loader.ts ✏️ CONFIG_ASSETS entry (Record) +├── src/presentation/commands/translate.ts ✏️ `--to` help string +├── src/presentation/prompts/menu-use-case.ts ✏️ example strings +├── scripts/smoke-tools.sh ✏️ AI_TOOLS +├── scripts/check-bundle-size.mjs ✏️ only if the budget breaks, with a registry line +├── mutation-scopes.json, package.json ✏️ `tools-antigravity` scope and script +├── tests/architecture/tool-addition-cost.arch.test.ts ✏️ BASELINE counts +1 for the files above +├── tests/contexts/tools/domain/profiles/antigravity/ +│ ├── profile.unit.test.ts ✅ paths, capabilities, telemetry reason +│ └── build.unit.test.ts ✅ skill paths, link rewriting +├── tests/golden/framework-build-golden.e2e.test.ts ✏️ FLAT_TARGETS + cell count +├── tests/golden/snapshots/framework-build/golden.json ✏️ new `antigravity:flat` cell only +├── tests/golden/snapshots/{help/surface,phase0/snapshot}.json, tests/fixtures/cli-owns-read/expected-envelope.json ✏️ regenerated +└── tests/** enumerating tool ids (tool-config, registry-conformance, build-hooks-support-declaration, asset-loader, interactive-menu, translate-wiring, uninstall-use-case, build-unit-deps, telemetry-route-supply, plugin-root-token-declaration, metrics-contract, cost-report-envelope, tool-attribution, host-marketplace-registry-reader-adapter) ✏️ +.github/workflows/ci.yml ✏️ `{ tool: antigravity, mode: flat }` row, comment count +scripts/__tests__/smoke-real-user-scope-tool-list-parity.test.js ✏️ flat-only list +docs/MAINTAINERS.md ✏️ archive count +``` + +## User Journey + +```mermaid +flowchart TD + A[aidd setup --ai antigravity] --> B[skills written to .agents/skills/aidd-*/SKILL.md] + B --> C[manifest records them under antigravity] + D[aidd translate src --to antigravity --as flat] --> E[same .agents/skills tree in --out] + C --> F[aidd clean antigravity removes only its recorded files] +``` + +## Test Scope + +```mermaid +--- +title: Test scope +--- +journey + section Setup + fixture framework source with one plugin skill => source ready: 5: system + section Happy path + aidd translate fixture --to antigravity --as flat => .agents/skills/-/SKILL.md written: 5: cli + aidd setup --ai antigravity => skills under .agents/skills recorded in manifest: 5: cli + golden e2e => antigravity:flat cell matches, other cells unchanged: 5: cli + section Edge case - foreign file + user file .agents/skills/mine/SKILL.md => clean antigravity => file untouched: 5: cli + section Teardown + remove temp project => baseline restored: 5: system +``` + +## Tasks to do + +### `1)` Profile, paths and flat contract + +> Skills only; every other artifact `supported: false` until its phase. + +1. `antigravity-paths.ts`: `ANTIGRAVITY_DIRECTORY = ".agents/"`, skills dir. +2. `build.ts`: skills `fullTree`, `rewriteSkillName: true`, path `.agents/skills/-/`, one directory level (same shape as Codex flat). Measured 2026-10-05 on `agy` 1.2.14: `.agents/skills/flat-probe/SKILL.md` logs `expanded slash command "flat-probe" (skill)`; `.agents/skills/aidd-probe/nested-probe/SKILL.md` logs no expansion. Never `//`. +3. Install side: setup reads the built flat tree back through `belongsToPlugin` in `built-tree-materialization-translator.ts`, which accepts only `skills//…` and so installs 0 files from the one-level layout. Let the profile declare its flat skill layout and have the materializer recognise it; test first (red: setup installs 0 skills), keep every existing tool's behaviour unchanged. +4. `profile.ts`: `SkillsCapability` on `.agents/skills/`, `PluginsCapability` `mode: "flat"`, `acceptsHooks: false` with a reason pointing to phase 3; `telemetryLocalRead` unsupported with the canonical reason string `registry-conformance` expects; no `distributionProbes.marketplace`. +5. Unit tests first: profile and build, red then green. + +### `2)` Register the id everywhere the arch test demands + +> Kilo review lesson: a static id is not a runtime registration. + +1. `tool.ts`, three wiring files, asset loader, translate help, menu strings. +2. Raise each `tool-addition-cost` BASELINE count by one; nothing else in that file. +3. Update every test enumeration listed in the projection; regenerate help and phase0 snapshots and the cli-owns-read envelope. + +### `3)` Golden cell and CI matrix + +> Only the new cell may move. + +1. Add `antigravity` to `FLAT_TARGETS`, update the cell-count title, run with `UPDATE_FRAMEWORK_GOLDEN=1`. +2. `git diff` the golden file: every changed key is `antigravity:flat`. +3. `ci.yml` matrix row, `MAINTAINERS.md` archive count, root parity test list, `smoke-tools.sh`, mutation scope and script. + +### `4)` Ownership under a shared `.agents/` + +> The Codex-shared case is a known bug outside #511; prove only that AIDD never touches a foreign file. + +1. Integration test: setup antigravity, add a user file under `.agents/skills/`, clean antigravity, user file intact. + +### `5)` Full suite and size + +1. `cd cli && pnpm test`, `pnpm exec lefthook run pre-commit`, bundle size check; raise the budget only with a registry line. +2. Diff size: if over 600 lines, move task 4 or the test-enumeration edits that are pure lists into a follow-up commit, never the golden cell. + +## Test acceptance criteria + +| Task | Acceptance criteria | +| ---- | ------------------- | +| 1 | `translate --to antigravity --as flat` writes `.agents/skills/-/SKILL.md`, one level deep, and no other artifact; `aidd setup --ai antigravity` installs the same skills; no other tool's setup output changes | +| 2 | `aidd setup --ai antigravity` succeeds, `aidd --help` and the menu list it, the arch tests pass | +| 3 | `golden.json` gains exactly one key, `antigravity:flat`; no existing cell changes; `ci.yml` builds the new archive | +| 4 | Cleaning Antigravity leaves a user file under `.agents/` in place | +| 5 | The full CLI suite and pre-commit pass on the branch | diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-3.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-3.md new file mode 100644 index 000000000..ddaf5696f --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-3.md @@ -0,0 +1,90 @@ +--- +status: pending +--- + + + +# Instruction: Memory hook in `.agents/hooks.json` + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +cli/ +├── src/contexts/tools/domain/profiles/antigravity/ +│ ├── antigravity-hooks.ts ✅ named-hook shape: merge AIDD's `aidd-memory` key into `.agents/hooks.json`, strip it on uninstall, convert Claude-shaped flat hooks +│ ├── profile.ts ✏️ HooksCapability on `.agents/hooks.json` +│ └── build.ts ✏️ hooks artifact: scripts under `.agents/hooks//`, hooksMerge into `.agents/hooks.json` +├── tests/contexts/tools/domain/profiles/antigravity/ +│ └── antigravity-hooks.unit.test.ts ✅ merge, idempotence, foreign keys kept, invalid JSON, strip +├── tests/contexts/tools/domain/build-hooks-support-declaration.unit.test.ts ✏️ antigravity now supports hooks +└── tests/golden/snapshots/framework-build/golden.json ✏️ `antigravity:flat` cell only +``` + +## User Journey + +```mermaid +flowchart TD + A[aidd setup --ai antigravity] --> B[.agents/hooks.json gains key aidd-memory with SessionStart command] + B --> C[agy new session in trusted folder] + C --> D[log: loaded N named hooks; memory refresh runs at repo root] + E[aidd clean antigravity] --> F[aidd-memory key removed, other named hooks kept, file deleted only if empty] +``` + +## Test Scope + +```mermaid +--- +title: Test scope +--- +journey + section Setup + agy 1.2.14 logged in, probe hook printing cwd and workspacePaths => measured cwd recorded: 5: system + section Happy path + aidd setup --ai antigravity on empty project => .agents/hooks.json has aidd-memory SessionStart entry: 5: cli + second setup => file byte-identical: 5: cli + translate --to antigravity --as flat => same hooks.json shape and scripts under .agents/hooks/: 5: cli + section Edge case - user hooks present + .agents/hooks.json with user key lint => setup then clean => lint key unchanged: 5: cli + section Edge case - invalid JSON + unparsable .agents/hooks.json => setup => error names the file, file untouched: 1: cli + section Teardown + remove temp project => baseline restored: 5: system +``` + +## Tasks to do + +### `1)` Measure the hook `cwd` on 1.2.14 + +> #890 measured `cwd = /.agents` on 1.2.5; `update_memory.js` silently no-ops when `aidd_docs/` is not in `cwd`. + +1. Local probe: a `SessionStart` hook writing `pwd` and its stdin payload to a marker; read the marker, not the turn. +2. Pick the command from the result: if `cwd` is `.agents`, the command must reach the repo root (e.g. `node ../.aidd/scripts/update_memory.cjs`, or a root resolved from `workspacePaths[0]`); record the evidence in the PR. + +### `2)` Named-hook merge, test first + +> Shape `{ "": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "…", "timeout": 30 } ] } ] } }`, no wrapper. + +1. Tests: empty file, existing foreign keys, re-run idempotent, invalid JSON fails loud (Codex's silent `catch { parsed = {} }` is not copied), strip leaves foreign keys. +2. Implement in `antigravity-hooks.ts`; mutate the foreign-key preservation and watch its test fail. + +### `3)` Wire setup and translate + +1. `profile.ts`: `HooksCapability` targeting `.agents/hooks.json` with the merge and strip; `acceptsHooks` stays false for plugin flat install so the hook is not written twice. +2. `build.ts`: hooks `hooksBundle`, scripts to `.agents/hooks//`, `hooksMerge` + `hooksMergeDest` converting the rewritten Claude-shaped JSON to one named key per plugin. +3. Confirm the flat-rewritten script path resolves from the measured `cwd`. + +### `4)` Golden and suite + +1. Regenerate golden; only `antigravity:flat` moves. +2. `cd cli && pnpm test`, pre-commit. + +## Test acceptance criteria + +| Task | Acceptance criteria | +| ---- | ------------------- | +| 1 | The PR quotes the measured `cwd` and the marker line from a real `agy` session | +| 2 | Foreign named hooks survive setup and clean; a second setup changes nothing; invalid JSON stops with the file named | +| 3 | After setup, a new `agy` session logs `loaded … named hooks` and the memory refresh marker appears at repo root | +| 4 | Only the `antigravity:flat` golden cell changes; full suite passes | diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-4.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-4.md new file mode 100644 index 000000000..62fa96668 --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-4.md @@ -0,0 +1,82 @@ +--- +status: pending +--- + + + +# Instruction: Portable agents under `.agents/agents//agent.md` + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +cli/ +├── src/contexts/tools/domain/formats/ +│ └── portable-agent.ts ✅ rebuild frontmatter: name, description, model: inherit, tools as YAML list; drop everything else +├── src/contexts/tools/domain/profiles/antigravity/ +│ ├── antigravity-paths.ts ✏️ agents dir +│ ├── profile.ts ✏️ AgentsCapability, nested `/agent.md` +│ └── build.ts ✏️ agents artifact, link rewriting relative to the nested path +├── tests/contexts/tools/domain/formats/ +│ └── portable-agent.unit.test.ts ✅ model mapping, tools string → list, Claude-only keys dropped, empty description rejected +├── tests/contexts/tools/domain/profiles/antigravity/build.unit.test.ts ✏️ agent path and body +└── tests/golden/snapshots/framework-build/golden.json ✏️ `antigravity:flat` cell only +``` + +## User Journey + +```mermaid +flowchart TD + A[source agent plugins/aidd-dev/agents/executor.md, model: opus, tools: a, b] --> B[aidd setup / translate antigravity] + B --> C[.agents/agents/aidd-dev-executor/agent.md] + C --> D[frontmatter: name, description, model: inherit, tools list] + D --> E[agy /agents lists aidd-dev-executor] +``` + +## Test Scope + +```mermaid +--- +title: Test scope +--- +journey + section Setup + fixture agent with model opus, comma tools and a Claude-only key => source ready: 5: system + section Happy path + translate --to antigravity --as flat => .agents/agents/-/agent.md written: 5: cli + read frontmatter => name, description, model inherit, tools YAML list, nothing else: 5: cli + aidd setup --ai antigravity => same file recorded in manifest: 5: cli + section Edge case - no tools + source agent without tools => translate => no tools key emitted: 5: cli + section Edge case - empty description + source agent with blank description => translate => build fails naming the agent: 1: cli + section Edge case - flat shape + any build => no .agents/agents/.md file exists: 5: cli +``` + +## Tasks to do + +### `1)` Portable frontmatter, test first + +> One builder #916 can reuse for Codex flat and Kimi. + +1. Tests for the four rules in #916, then implement `portable-agent.ts`. +2. Mutate `model: inherit` back to the source value; watch the model test fail. + +### `2)` Antigravity agents in setup and translate + +1. `AgentsCapability` and flat `agents` artifact writing `.agents/agents/-/agent.md`, body links rewritten from that nested path. +2. Unit test the path and body; regenerate golden, only `antigravity:flat` moves. + +### `3)` Live check + +1. Local `agy --add-dir --output-format json -p "/agents"` lists a generated agent; quote the line in the PR, with an invented-name negative control. + +## Test acceptance criteria + +| Task | Acceptance criteria | +| ---- | ------------------- | +| 1 | A source agent with `model: opus` and `tools: "a, b"` yields `model: inherit` and `tools: [a, b]`, and no Claude-only key | +| 2 | Agents land only at `.agents/agents//agent.md`; only the `antigravity:flat` golden cell changes; full suite passes | +| 3 | `agy /agents` lists the generated agent and not the invented one | diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md new file mode 100644 index 000000000..c6448f792 --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md @@ -0,0 +1,79 @@ +--- +status: pending +--- + + + +# Instruction: Docs, AIDD skill references and local runtime evidence + +## Architecture projection + +> Tree of the final files. ✅ create · ✏️ modify · ❌ delete + +```txt +README.md ✏️ compatibility line, tool table, install section +cli/README.md ✏️ tool and config-path rows +docs/FAQ.md ✏️ tool lists +cli/aidd_docs/memory/codebase-map.md ✏️ profiles/antigravity entry +plugins/aidd-context/hooks/update_memory.js ✏️ TOOL_FILES antigravity → AGENTS.md +plugins/aidd-context/skills/02-project-memory/references/tools.md ✏️ mirror of TOOL_FILES +plugins/aidd-context/skills/{04..08}-*/references/tool-paths.md, tool-detect.md ✏️ `.agents/` paths, detection +plugins/aidd-context/skills/11-explore/…/ai-mapping.md, 00-onboard/…/detection.md ✏️ antigravity row +cli/scripts/smoke-antigravity.sh ✅ local only: setup, then assert `expanded slash command`, `loaded … named hooks`, `/agents` line from logs and markers, never the turn's end +``` + +## User Journey + +```mermaid +flowchart TD + A[developer reads README] --> B[aidd setup --ai antigravity] + B --> C[agy in the project] + C --> D[/aidd skill expands, memory refreshes, agents listed] + E[maintainer runs smoke-antigravity.sh locally] --> F[three log assertions pass or name the missing line] +``` + +## Test Scope + +```mermaid +--- +title: Test scope +--- +journey + section Setup + agy 1.2.14 logged in, empty temp project with aidd_docs => ready: 5: system + section Happy path + smoke-antigravity.sh => expanded slash command line found for one AIDD skill: 5: cli + smoke-antigravity.sh => loaded named hooks line and memory marker found: 5: cli + smoke-antigravity.sh => /agents lists a generated agent: 5: cli + section Edge case - agy missing + no agy on PATH => smoke-antigravity.sh => exits non-zero naming agy: 1: cli + section Teardown + kill hung agy turn, remove temp project => baseline restored: 5: system +``` + +## Tasks to do + +### `1)` Docs and references + +1. README tables, FAQ, CLI README, codebase map. +2. `TOOL_FILES` and its mirror `tools.md`; the generate skills' path and detection references. +3. `pnpm exec lefthook run pre-commit` (doc duplication, links, paths named in prose). + +### `2)` Local runtime smoke + +> Print mode hangs after answering: bound each turn with a timeout and read the log, as the spike did. + +1. Script asserting the three log lines; documented as local-only with why (login required) in `docs/MAINTAINERS.md`. +2. Run it; paste the three shortest lines, date and `agy --version` into the PR. + +### `3)` Close the loop on #511 + +1. Tick #511's criteria with links to each phase's PR; file follow-ups named in the plan's decisions if not already filed (native plugin mode, telemetry host, migration guide). + +## Test acceptance criteria + +| Task | Acceptance criteria | +| ---- | ------------------- | +| 1 | README and FAQ list Antigravity; `update_memory.js` refreshes `AGENTS.md` for `antigravity`; pre-commit passes | +| 2 | On a logged-in machine the script reports all three lines; without `agy` it fails naming it | +| 3 | Every #511 criterion points to the PR that proves it | diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md new file mode 100644 index 000000000..066fde357 --- /dev/null +++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md @@ -0,0 +1,45 @@ +--- +objective: "`aidd setup --ai antigravity` and `aidd translate --to antigravity --as flat` write AIDD skills, the memory hook and agents under `.agents/`, which `agy` loads, without touching files AIDD did not write." +status: in-progress +--- + + + +# Plan: Antigravity CLI as a flat host + +## Overview + +| Field | Value | +| ---------- | ----- | +| **Goal** | An isolated `antigravity` flat profile, modelled on Kilo, in project scope, shipped as four PRs under 600 lines each | +| **Source** | ai-driven-dev/framework#511, spike `aidd_docs/backlog/spikes/antigravity-supported-surfaces.md`, Kilo PR #745 and its review | + +## Phases + +| # | Phase | File | +| --- | ----- | ---- | +| 2 | `antigravity` profile with skills, registered everywhere, golden cell | [`phase-2.md`](./phase-2.md) | +| 3 | Memory hook in `.agents/hooks.json` | [`phase-3.md`](./phase-3.md) | +| 4 | Portable agents under `.agents/agents//agent.md` | [`phase-4.md`](./phase-4.md) | +| 5 | Docs, AIDD skill references and local runtime evidence | [`phase-5.md`](./phase-5.md) | + +## Resources + +| Source | Verified | +| ------ | -------- | +| https://antigravity.google/docs/hooks | `hooks.json` is keyed by hook name, no `hooks` wrapper; events `PreToolUse`, `PostToolUse`, `PreInvocation`, `PostInvocation`, `Stop`; `SessionStart` works though undocumented (spike, #890) | +| https://antigravity.google/docs/subagents?tab=cli | agents at `.agents/agents/.md` or `/agent.md`; `name`, `description` required; `model` in `inherit`/`flash`/`pro`; `tools` a YAML list | +| Issue #890 | hooks only from `hooks.json`; hook process `cwd` is `/.agents` on 1.2.5 | +| Issue #916 comments | `agy` silently drops an agent with `model: sonnet`/`opus` or a comma-separated `tools`, while `plugin validate` passes | +| Spike, 2026-10-02 | print-mode turns hang after answering: runtime evidence reads `cli-*.log` lines and markers, never the turn's end; a turn needs a login, so no CI runtime smoke | + +## Decisions + +| Decision | Why | +| -------- | --- | +| The shared plugin-path uninstall bug stays out of #511; phases are numbered 2 to 5 | Codex and Antigravity both write `.agents/skills/`, and uninstalling one deletes plugin files the other still records (probe `uninstall-tools-shared-plugin-path.probe.unit.test.ts` fails). Product owner's call on 2026-10-05: track it separately, ship #511 with it as a known limitation | +| Setup writes the memory hook through a `HooksCapability` on `.agents/hooks.json`, like Codex, not through a JS bridge like Kilo | `agy` reads a JSON file natively; a bridge only exists where the host has no hooks file | +| The hook command is chosen from a measured `cwd` on `agy` 1.2.14, not assumed | `update_memory.js` exits 0 in silence when `aidd_docs/` is absent from `cwd`, so a wrong `cwd` looks like success | +| The portable agent frontmatter builder lives in `tools/domain/formats/`, not in the profile | it is a cross-host shape (#916 reuses it for Codex flat and Kimi); only the Antigravity paths stay in `profiles/antigravity/` | +| No CI runtime smoke; CI gets the golden cell and the `build-per-tool` matrix row only | a turn needs a Google login and print mode hangs; the Kilo review's "real binary in the gate" lesson cannot hold here, so the PR says so instead of shipping a skipped test | +| Native plugin mode, telemetry host, duplicate-agent-name rejection stay out | #511 out of scope; duplicate `name` rejection belongs to #916 | diff --git a/cli/aidd_docs/memory/codebase-map.md b/cli/aidd_docs/memory/codebase-map.md index cffa92725..d6acacd29 100644 --- a/cli/aidd_docs/memory/codebase-map.md +++ b/cli/aidd_docs/memory/codebase-map.md @@ -48,6 +48,7 @@ src/ │ │ │ ├── models/ │ │ │ ├── ports/ │ │ │ └── profiles/ # one directory per tool +│ │ │ ├── antigravity/ │ │ │ ├── claude/ │ │ │ ├── codex/ │ │ │ ├── copilot/ diff --git a/cli/mutation-scopes.json b/cli/mutation-scopes.json index ccef764bf..a854e976d 100644 --- a/cli/mutation-scopes.json +++ b/cli/mutation-scopes.json @@ -8,6 +8,7 @@ "tools": { "mutate": [ "src/contexts/tools/**/*.ts", + "!src/contexts/tools/domain/profiles/antigravity/**/*.ts", "!src/contexts/tools/domain/profiles/claude/**/*.ts", "!src/contexts/tools/domain/profiles/codex/**/*.ts", "!src/contexts/tools/domain/profiles/copilot/**/*.ts", @@ -61,6 +62,10 @@ "mutate": "src/contexts/tools/domain/profiles/opencode/**/*.ts", "break": 94 }, + "tools-antigravity": { + "mutate": "src/contexts/tools/domain/profiles/antigravity/**/*.ts", + "break": 82 + }, "tools-kilo": { "mutate": "src/contexts/tools/domain/profiles/kilo/**/*.ts", "break": 64 diff --git a/cli/package.json b/cli/package.json index d88fbca50..e83ebb756 100644 --- a/cli/package.json +++ b/cli/package.json @@ -63,6 +63,7 @@ "test:mutation": "node scripts/run-mutation.mjs", "test:mutation:kernel": "node scripts/run-mutation.mjs kernel", "test:mutation:tools": "node scripts/run-mutation.mjs tools", + "test:mutation:tools-antigravity": "node scripts/run-mutation.mjs tools-antigravity", "test:mutation:tools-claude": "node scripts/run-mutation.mjs tools-claude", "test:mutation:tools-codex": "node scripts/run-mutation.mjs tools-codex", "test:mutation:tools-copilot": "node scripts/run-mutation.mjs tools-copilot", diff --git a/cli/scripts/smoke-tools.sh b/cli/scripts/smoke-tools.sh index 57dd7971a..cd84a7e1c 100755 --- a/cli/scripts/smoke-tools.sh +++ b/cli/scripts/smoke-tools.sh @@ -17,7 +17,7 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd)" CLI="$ROOT/dist/cli.js" FRAMEWORK_FIXTURE="$ROOT/tests/fixtures/framework" -AI_TOOLS=(claude cursor copilot codex opencode kilo) +AI_TOOLS=(claude cursor copilot codex opencode kilo antigravity) IDE_TOOLS=(vscode) # Canonical leaf-command surface. Coverage = exercised / total. diff --git a/cli/src/contexts/framework/application/framework/translator/built-tree-materialization-translator.ts b/cli/src/contexts/framework/application/framework/translator/built-tree-materialization-translator.ts index 94a5eec9c..673366f9f 100644 --- a/cli/src/contexts/framework/application/framework/translator/built-tree-materialization-translator.ts +++ b/cli/src/contexts/framework/application/framework/translator/built-tree-materialization-translator.ts @@ -151,11 +151,10 @@ export class BuiltTreeMaterializationTranslator implements PluginTranslator { } // Flat build emits the whole marketplace into one workspace. Agents are namespaced by - // `-`; skills instead nest the whole subtree under `skills//`, since a - // skill's own script can `require()` a sibling by relative path, which only keeps resolving while - // nothing under that subtree is renamed. Hooks land under `flatHooksDir//`, except the - // one script that is the loader's own runtime module, renamed to the plugin's name in the - // loader's directory — so hook paths are matched by path, never by naming convention. + // `-`; skills keep their subtree intact, since a skill's script can `require()` a + // sibling by relative path, under `skills//` or, `single-level`, `skills/-/`. + // Hooks land under `flatHooksDir//`, except the loader's own runtime module, renamed to + // the plugin's name in the loader's directory — so hook paths are matched by path, not by name. private async readFlatFiles( builtDir: string, dist: PluginDistribution, @@ -182,7 +181,11 @@ export class BuiltTreeMaterializationTranslator implements PluginTranslator { if (segments[0] !== toolDirectory || segments.length < 3) return false; // `skills/` nests the whole plugin under one exactly-named segment; every other flat section // hyphen-prefixes the leaf segment. - if (segments[1] === "skills") return segments[2] === name; + if (segments[1] === "skills") { + return resolvePluginsCapability(toolId)?.flatSkillLayout === "single-level" + ? segments[2].startsWith(`${name}-`) + : segments[2] === name; + } return segments[2].startsWith(`${name}-`); } diff --git a/cli/src/contexts/tools/domain/capabilities/plugins-capability.ts b/cli/src/contexts/tools/domain/capabilities/plugins-capability.ts index dbc9c403b..2c66b53b0 100644 --- a/cli/src/contexts/tools/domain/capabilities/plugins-capability.ts +++ b/cli/src/contexts/tools/domain/capabilities/plugins-capability.ts @@ -127,9 +127,13 @@ export type FlatHooksSupport = } | { acceptsHooks: false; hooksUnsupportedReason: string }; +/** Flat skills go under `skills//`, or `skills/-/` for a shallow-scan tool. */ +export type FlatSkillLayout = "nested" | "single-level"; + export type FlatPluginsParams = { mode: "flat"; flatNamespacePrefix: string; + flatSkillLayout?: FlatSkillLayout; } & FlatHooksSupport; export interface UnsupportedPluginsParams { @@ -180,6 +184,7 @@ export class PluginsCapability { readonly flatHooksLoaderEntry: FlatHooksLoaderEntry | null; /** See {@link FlatHooksBridge}, or `null` when this capability declares none. */ readonly flatHooksBridge: FlatHooksBridge | null; + readonly flatSkillLayout: FlatSkillLayout; readonly marketplaceSettings: MarketplaceSettings | null; readonly nativeActivation: NativeActivation | null; readonly translationMode: PluginTranslationMode | null; @@ -209,6 +214,7 @@ export class PluginsCapability { this.flatHooksDir = null; this.flatHooksLoaderEntry = null; this.flatHooksBridge = null; + this.flatSkillLayout = "nested"; this.marketplaceSettings = params.marketplaceSettings ?? null; this.nativeActivation = params.nativeActivation ?? null; this._userPluginsDir = params.userPluginsDir; @@ -223,6 +229,7 @@ export class PluginsCapability { ? (params.flatHooksLoaderEntry ?? null) : null; this.flatHooksBridge = params.acceptsHooks ? (params.flatHooksBridge ?? null) : null; + this.flatSkillLayout = params.flatSkillLayout ?? "nested"; this.hooksTrustNotice = null; this.pluginRootToken = null; this.acceptsMcp = false; @@ -243,6 +250,7 @@ export class PluginsCapability { this.flatHooksDir = null; this.flatHooksLoaderEntry = null; this.flatHooksBridge = null; + this.flatSkillLayout = "nested"; this.hooksTrustNotice = null; this.pluginRootToken = null; this.acceptsMcp = false; diff --git a/cli/src/contexts/tools/domain/profiles/antigravity/antigravity-paths.ts b/cli/src/contexts/tools/domain/profiles/antigravity/antigravity-paths.ts new file mode 100644 index 000000000..e2d651fdc --- /dev/null +++ b/cli/src/contexts/tools/domain/profiles/antigravity/antigravity-paths.ts @@ -0,0 +1,5 @@ +/** Paths Antigravity CLI scans in a project. Kept apart from the profile so the build contract + * and the setup capability share one declaration. */ + +export const ANTIGRAVITY_DIRECTORY = ".agents/"; +export const ANTIGRAVITY_SKILLS_DIR = `${ANTIGRAVITY_DIRECTORY}skills/`; diff --git a/cli/src/contexts/tools/domain/profiles/antigravity/build.ts b/cli/src/contexts/tools/domain/profiles/antigravity/build.ts new file mode 100644 index 000000000..8dabe531e --- /dev/null +++ b/cli/src/contexts/tools/domain/profiles/antigravity/build.ts @@ -0,0 +1,33 @@ +/** Antigravity's project distribution is flat and carries skills only. A skill sits one level + * under `.agents/skills/`, since `agy` expands none nested deeper. */ + +import { genericFlatSkillPath } from "../../../../../kernel/materialization/flat-paths.js"; +import type { ToolBuildContract } from "../../build-contract.js"; +import { ANTIGRAVITY_SKILLS_DIR } from "./antigravity-paths.js"; + +function antigravityFlatSkillPath(plugin: string, rel: string): string { + return genericFlatSkillPath(ANTIGRAVITY_SKILLS_DIR, plugin, rel.replace(/^skills\//, "")); +} + +export function buildAntigravityFlatContract(): ToolBuildContract { + return { + manifestFileRelative: null, + synthesizeManifest: null, + manifestSchemaName: null, + artifacts: { + skills: { + supported: true, + source: { kind: "fullTree", srcDir: "skills" }, + path: antigravityFlatSkillPath, + rewriteSkillName: true, + }, + agents: { supported: false }, + mcp: { supported: false }, + hooks: { supported: false }, + rules: { supported: false }, + commands: { supported: false }, + }, + buildMarketplaceCatalog: null, + buildMarketplaceEntry: null, + }; +} diff --git a/cli/src/contexts/tools/domain/profiles/antigravity/profile.ts b/cli/src/contexts/tools/domain/profiles/antigravity/profile.ts new file mode 100644 index 000000000..858c6055d --- /dev/null +++ b/cli/src/contexts/tools/domain/profiles/antigravity/profile.ts @@ -0,0 +1,57 @@ +import { PluginsCapability } from "../../capabilities/plugins-capability.js"; +import { SkillsCapability } from "../../capabilities/skills-capability.js"; +import type { AiTool, HasPlugins, HasSkills } from "../../contracts.js"; +import { registerTool } from "../../registry.js"; +import { ANTIGRAVITY_DIRECTORY } from "./antigravity-paths.js"; +import { buildAntigravityFlatContract } from "./build.js"; + +const TOOL_SUFFIX = ".antigravity.md"; +const SKILLS_PREFIX = "aidd-"; + +function skillName(fileName: string): string { + const parts = fileName.split("/"); + if (parts.length > 1) return parts[0] as string; + const base = parts[0] as string; + return base.endsWith(TOOL_SUFFIX) + ? base.slice(0, -TOOL_SUFFIX.length) + : base.replace(/\.md$/, ""); +} + +export const antigravity: AiTool = { + kind: "ai", + toolId: "antigravity", + directory: ANTIGRAVITY_DIRECTORY, + toolSuffix: TOOL_SUFFIX, + displayName: "Antigravity CLI", + telemetryLocalRead: { + kind: "unsupported", + reason: "Antigravity CLI telemetry is not yet supported by AIDD.", + }, + telemetryTaskAttributable: false, + signalDir: null, + buildContracts: { flat: buildAntigravityFlatContract }, + + capabilities: { + skills: new SkillsCapability({ + toolSuffix: TOOL_SUFFIX, + prefix: SKILLS_PREFIX, + buildInstallPath: (fileName) => + `${ANTIGRAVITY_DIRECTORY}skills/${SKILLS_PREFIX}${skillName(fileName)}/SKILL.md`, + convertFrontmatter: (fm) => fm, + }), + plugins: new PluginsCapability({ + mode: "flat", + flatNamespacePrefix: "aidd-", + flatSkillLayout: "single-level", + acceptsHooks: false, + hooksUnsupportedReason: + "Antigravity CLI hooks are not wired yet (follow-up phase 3 of #511: .agents/hooks.json).", + }), + }, + + rewriteContent(content: string): string { + return content; + }, +}; + +registerTool(antigravity); diff --git a/cli/src/contexts/translate/domain/content-translator.ts b/cli/src/contexts/translate/domain/content-translator.ts index bcd8b9c9f..9b3b9a3e0 100644 --- a/cli/src/contexts/translate/domain/content-translator.ts +++ b/cli/src/contexts/translate/domain/content-translator.ts @@ -254,7 +254,7 @@ export class PluginContentTranslator { const { flatNamespacePrefix } = tool.capabilities.plugins; if (flatNamespacePrefix === null) return { files: [], skipped: [] }; const result: InstallationFile[] = []; - for (const file of dist.components.commands) { + for (const file of hasCommands(tool) ? dist.components.commands : []) { result.push(this.flatCommandFile(file, dist.manifest.name, tool, flatNamespacePrefix)); } for (const section of ["agents", "rules", "skills"] as const) { @@ -349,7 +349,12 @@ export class PluginContentTranslator { // Same rule as the native path: prose is rewritten, an artefact is carried. Rewriting every // flat file left a script intact only where a tool's own rewrite happened to spare it. const content = isProse(file.relativePath) ? tool.rewriteContent(file.content) : file.content; - return this.makeFile(`${tool.directory}${section}/${pluginName}/${fileName}`, content); + const singleLevel = + section === "skills" && tool.capabilities.plugins.flatSkillLayout === "single-level"; + const path = singleLevel + ? `${tool.directory}skills/${pluginName}-${fileName}` + : `${tool.directory}${section}/${pluginName}/${fileName}`; + return this.makeFile(path, content); } private makeFile(relativePath: string, content: string): InstallationFile { diff --git a/cli/src/kernel/tool.ts b/cli/src/kernel/tool.ts index 6f8b968f5..ed8f3d32c 100644 --- a/cli/src/kernel/tool.ts +++ b/cli/src/kernel/tool.ts @@ -1,6 +1,13 @@ import { UnknownAiToolIdError } from "./errors.js"; -export type AiToolId = "claude" | "cursor" | "copilot" | "opencode" | "kilo" | "codex"; +export type AiToolId = + | "claude" + | "cursor" + | "copilot" + | "opencode" + | "kilo" + | "codex" + | "antigravity"; export type IdeToolId = "vscode"; export type ToolId = AiToolId | IdeToolId; export type ToolCategory = "ai" | "ide"; @@ -12,6 +19,7 @@ export const AI_TOOL_IDS: readonly AiToolId[] = [ "opencode", "kilo", "codex", + "antigravity", ]; export const IDE_TOOL_IDS: readonly IdeToolId[] = ["vscode"]; export const VALID_TOOL_IDS: readonly ToolId[] = [...AI_TOOL_IDS, ...IDE_TOOL_IDS]; diff --git a/cli/src/presentation/commands/translate.ts b/cli/src/presentation/commands/translate.ts index 79830cce0..960a08d4d 100644 --- a/cli/src/presentation/commands/translate.ts +++ b/cli/src/presentation/commands/translate.ts @@ -72,7 +72,7 @@ export function registerTranslateCommand(program: Command): void { .argument("", "Path to the source framework directory") .requiredOption( "--to ", - "Conversion target (claude, cursor, copilot, codex, opencode, kilo)" + "Conversion target (claude, cursor, copilot, codex, opencode, kilo, antigravity)" ) .requiredOption("--out ", "Output directory (marketplace dist or project root)") .option("--as ", "Output layout", "marketplace") diff --git a/cli/src/presentation/prompts/menu-use-case.ts b/cli/src/presentation/prompts/menu-use-case.ts index b58ae19d3..f758c48e5 100644 --- a/cli/src/presentation/prompts/menu-use-case.ts +++ b/cli/src/presentation/prompts/menu-use-case.ts @@ -44,7 +44,8 @@ const INSTALLED_NODES: MenuNode[] = [ value: "doctor-tool", description: "Scope the report to a single AI or IDE tool", command: ["doctor", "--tool"], - inputPrompt: "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, vscode)", + inputPrompt: + "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, antigravity, vscode)", }, { name: "Plugins", @@ -64,7 +65,8 @@ const INSTALLED_NODES: MenuNode[] = [ value: "framework-install", description: "Add a tool to this project", command: ["framework", "install", "--tool"], - inputPrompt: "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, vscode)", + inputPrompt: + "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, antigravity, vscode)", }, { name: "Remove", diff --git a/cli/src/runtime/assets/asset-loader.ts b/cli/src/runtime/assets/asset-loader.ts index 2377e545a..f4a10e318 100644 --- a/cli/src/runtime/assets/asset-loader.ts +++ b/cli/src/runtime/assets/asset-loader.ts @@ -28,6 +28,7 @@ const CONFIG_ASSETS: Readonly { }) ).rejects.toThrow( new InputRequiredError( - "At least one tool ID is required. Valid tools: claude, cursor, copilot, opencode, kilo, codex, vscode" + "At least one tool ID is required. Valid tools: claude, cursor, copilot, opencode, kilo, codex, antigravity, vscode" ) ); }); diff --git a/cli/tests/contexts/framework/domain/plugin-asset-translation.unit.test.ts b/cli/tests/contexts/framework/domain/plugin-asset-translation.unit.test.ts index a49f34034..6b1aa11a3 100644 --- a/cli/tests/contexts/framework/domain/plugin-asset-translation.unit.test.ts +++ b/cli/tests/contexts/framework/domain/plugin-asset-translation.unit.test.ts @@ -6,6 +6,7 @@ import "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import { claude } from "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; diff --git a/cli/tests/contexts/telemetry/application/diagnose-telemetry-use-case.unit.test.ts b/cli/tests/contexts/telemetry/application/diagnose-telemetry-use-case.unit.test.ts index 0b19c9176..b725d886f 100644 --- a/cli/tests/contexts/telemetry/application/diagnose-telemetry-use-case.unit.test.ts +++ b/cli/tests/contexts/telemetry/application/diagnose-telemetry-use-case.unit.test.ts @@ -4,6 +4,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { Manifest } from "../../../../src/contexts/framework/domain/manifest.js"; import { InstalledPlugin } from "../../../../src/contexts/framework/domain/plugins/installed-plugin.js"; @@ -763,6 +764,7 @@ describe("DiagnoseTelemetryUseCase — the setup it prints", () => { tool: "kilo", reason: "Kilo OpenTelemetry is experimental and not yet supported by AIDD.", }, + { tool: "antigravity", reason: "Antigravity CLI telemetry is not yet supported by AIDD." }, ]); }); }); diff --git a/cli/tests/contexts/telemetry/application/read-local-cost-sweep.unit.test.ts b/cli/tests/contexts/telemetry/application/read-local-cost-sweep.unit.test.ts index 680b67ca4..3bdba2006 100644 --- a/cli/tests/contexts/telemetry/application/read-local-cost-sweep.unit.test.ts +++ b/cli/tests/contexts/telemetry/application/read-local-cost-sweep.unit.test.ts @@ -4,6 +4,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { type LocalCostToolReport, @@ -81,6 +82,15 @@ const KILO_NOT_COVERED: LocalCostToolReport = { reason: "Kilo OpenTelemetry is experimental and not yet supported by AIDD.", }; +const ANTIGRAVITY_NOT_COVERED: LocalCostToolReport = { + tool: "antigravity", + status: "not-covered", + recordsFound: 0, + recordsStored: 0, + sessionsFailed: 0, + reason: "Antigravity CLI telemetry is not yet supported by AIDD.", +}; + function sessionJournal(vendorId: string, host = "claude-code"): RunJournal { return { boundaries: [], @@ -179,6 +189,7 @@ describe("which sessions a sweep reads", () => { notAsked("opencode"), notAsked("kilo"), notAsked("codex"), + notAsked("antigravity"), ], }); }); @@ -205,6 +216,7 @@ describe("which sessions a sweep reads", () => { notAsked("opencode"), notAsked("kilo"), notAsked("codex"), + notAsked("antigravity"), ], refusedReason: "measurement is refused — AIDD_TELEMETRY=0 or the project switch is off; nothing read, " + @@ -230,6 +242,7 @@ describe("one session's answers, tool by tool", () => { notAsked("opencode"), KILO_NOT_COVERED, notAsked("codex"), + ANTIGRAVITY_NOT_COVERED, ], }, ]); diff --git a/cli/tests/contexts/telemetry/application/read-local-cost-use-case.unit.test.ts b/cli/tests/contexts/telemetry/application/read-local-cost-use-case.unit.test.ts index dea20b167..1730bd15a 100644 --- a/cli/tests/contexts/telemetry/application/read-local-cost-use-case.unit.test.ts +++ b/cli/tests/contexts/telemetry/application/read-local-cost-use-case.unit.test.ts @@ -8,6 +8,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { ReadLocalCostUseCase } from "../../../../src/contexts/telemetry/application/read-local-cost-use-case.js"; import { mapCodexRolloutToSinkRecords } from "../../../../src/contexts/telemetry/domain/formats/codex-rollout.js"; diff --git a/cli/tests/contexts/telemetry/application/report-cost-use-case.unit.test.ts b/cli/tests/contexts/telemetry/application/report-cost-use-case.unit.test.ts index 9204a849e..6909a4d04 100644 --- a/cli/tests/contexts/telemetry/application/report-cost-use-case.unit.test.ts +++ b/cli/tests/contexts/telemetry/application/report-cost-use-case.unit.test.ts @@ -6,6 +6,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { ReadLocalCostUseCase } from "../../../../src/contexts/telemetry/application/read-local-cost-use-case.js"; import { ReportCostUseCase } from "../../../../src/contexts/telemetry/application/report-cost-use-case.js"; @@ -1023,6 +1024,17 @@ describe("ReportCostUseCase — what it assembles for the report", () => { taskAttributable: true, }, }, + { + tool: "antigravity", + coverage: "not-covered", + reason: "Antigravity CLI telemetry is not yet supported by AIDD.", + capability: { + localRead: null, + export: null, + journalAttributable: false, + taskAttributable: false, + }, + }, ]); }); diff --git a/cli/tests/contexts/telemetry/application/tool-attribution.unit.test.ts b/cli/tests/contexts/telemetry/application/tool-attribution.unit.test.ts index 81c5a609b..5a3efae72 100644 --- a/cli/tests/contexts/telemetry/application/tool-attribution.unit.test.ts +++ b/cli/tests/contexts/telemetry/application/tool-attribution.unit.test.ts @@ -8,6 +8,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { ReadLocalCostUseCase } from "../../../../src/contexts/telemetry/application/read-local-cost-use-case.js"; import { mapClaudeCodeTranscriptToSinkRecords } from "../../../../src/contexts/telemetry/domain/formats/claude-code-transcript.js"; diff --git a/cli/tests/contexts/telemetry/domain/cost-report-envelope.unit.test.ts b/cli/tests/contexts/telemetry/domain/cost-report-envelope.unit.test.ts index 10031afc9..85c8a54ef 100644 --- a/cli/tests/contexts/telemetry/domain/cost-report-envelope.unit.test.ts +++ b/cli/tests/contexts/telemetry/domain/cost-report-envelope.unit.test.ts @@ -8,6 +8,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { buildCostReport, diff --git a/cli/tests/contexts/telemetry/domain/metrics-contract.unit.test.ts b/cli/tests/contexts/telemetry/domain/metrics-contract.unit.test.ts index 259256c5e..0f826d029 100644 --- a/cli/tests/contexts/telemetry/domain/metrics-contract.unit.test.ts +++ b/cli/tests/contexts/telemetry/domain/metrics-contract.unit.test.ts @@ -10,6 +10,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { ReadLocalCostUseCase } from "../../../../src/contexts/telemetry/application/read-local-cost-use-case.js"; import type { LocalCostCandidateRecord } from "../../../../src/contexts/telemetry/domain/ports/session-cost-reader.js"; diff --git a/cli/tests/contexts/telemetry/infrastructure/telemetry-evidence-adapter.integration.test.ts b/cli/tests/contexts/telemetry/infrastructure/telemetry-evidence-adapter.integration.test.ts index 2a94dbdd0..ea05d54b9 100644 --- a/cli/tests/contexts/telemetry/infrastructure/telemetry-evidence-adapter.integration.test.ts +++ b/cli/tests/contexts/telemetry/infrastructure/telemetry-evidence-adapter.integration.test.ts @@ -9,6 +9,7 @@ import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import { TelemetryEvidenceAdapter } from "../../../../src/contexts/telemetry/infrastructure/telemetry-evidence-adapter.js"; diff --git a/cli/tests/contexts/tools/domain/build-hooks-support-declaration.unit.test.ts b/cli/tests/contexts/tools/domain/build-hooks-support-declaration.unit.test.ts index 73557fb4a..a89e2807e 100644 --- a/cli/tests/contexts/tools/domain/build-hooks-support-declaration.unit.test.ts +++ b/cli/tests/contexts/tools/domain/build-hooks-support-declaration.unit.test.ts @@ -3,6 +3,8 @@ import type { ArtifactContract, ToolBuildContract, } from "../../../../src/contexts/tools/domain/build-contract.js"; +import { buildAntigravityFlatContract } from "../../../../src/contexts/tools/domain/profiles/antigravity/build.js"; +import { antigravity } from "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import { buildClaudeFlatContract } from "../../../../src/contexts/tools/domain/profiles/claude/build.js"; import { claude } from "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import { buildCodexFlatContract } from "../../../../src/contexts/tools/domain/profiles/codex/build.js"; @@ -31,6 +33,7 @@ const FLAT_CONTRACTS: ReadonlyArray<[HooksDeclaringTool, () => ToolBuildContract [copilot, buildCopilotFlatContract], [codex, buildCodexFlatContract], [kilo, buildKiloFlatContract], + [antigravity, buildAntigravityFlatContract], [opencode, buildOpencodeFlatContract], ]; diff --git a/cli/tests/contexts/tools/domain/plugin-root-token-declaration.unit.test.ts b/cli/tests/contexts/tools/domain/plugin-root-token-declaration.unit.test.ts index 468a9a00d..5cb74aa3a 100644 --- a/cli/tests/contexts/tools/domain/plugin-root-token-declaration.unit.test.ts +++ b/cli/tests/contexts/tools/domain/plugin-root-token-declaration.unit.test.ts @@ -9,6 +9,7 @@ import "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import type { PluginsCapability } from "../../../../src/contexts/tools/domain/capabilities/plugins-capability.js"; diff --git a/cli/tests/contexts/tools/domain/profiles/antigravity/build.unit.test.ts b/cli/tests/contexts/tools/domain/profiles/antigravity/build.unit.test.ts new file mode 100644 index 000000000..a62d41abc --- /dev/null +++ b/cli/tests/contexts/tools/domain/profiles/antigravity/build.unit.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; +import type { ArtifactContract } from "../../../../../../src/contexts/tools/domain/build-contract.js"; +import { buildAntigravityFlatContract } from "../../../../../../src/contexts/tools/domain/profiles/antigravity/build.js"; + +function supported(artifact: ArtifactContract): Extract { + if (!artifact.supported) throw new Error("artifact is declared unsupported"); + return artifact; +} + +describe("buildAntigravityFlatContract", () => { + it("sits a skill one level under .agents/skills, the plugin hyphenated onto its name", () => { + const skills = supported(buildAntigravityFlatContract().artifacts.skills); + expect(skills.path("aidd-dev", "skills/01-plan/SKILL.md")).toBe( + ".agents/skills/aidd-dev-01-plan/SKILL.md" + ); + expect(skills.rewriteSkillName).toBe(true); + expect(skills.source).toEqual({ kind: "fullTree", srcDir: "skills" }); + }); + + it.each(["agents", "hooks", "mcp", "rules", "commands"] as const)( + "declares %s unsupported", + (kind) => { + expect(buildAntigravityFlatContract().artifacts[kind].supported).toBe(false); + } + ); + + it("writes no manifest, catalog or config artifact", () => { + const contract = buildAntigravityFlatContract(); + expect(contract.manifestFileRelative).toBeNull(); + expect(contract.buildMarketplaceCatalog).toBeNull(); + expect(contract.emitConfigArtifact).toBeUndefined(); + }); +}); diff --git a/cli/tests/contexts/tools/domain/profiles/antigravity/profile.unit.test.ts b/cli/tests/contexts/tools/domain/profiles/antigravity/profile.unit.test.ts new file mode 100644 index 000000000..15ffb415d --- /dev/null +++ b/cli/tests/contexts/tools/domain/profiles/antigravity/profile.unit.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "vitest"; +import { antigravity } from "../../../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; + +describe("antigravity", () => { + it("is named for the person reading it and declares a flat build only", () => { + expect(antigravity.displayName).toBe("Antigravity CLI"); + expect(antigravity.directory).toBe(".agents/"); + expect(antigravity.buildContracts?.flat).toBeDefined(); + expect(antigravity.buildContracts?.marketplace).toBeUndefined(); + expect(antigravity.distributionProbes).toBeUndefined(); + }); + + it("installs skills under .agents/skills with the aidd- namespace", () => { + expect(antigravity.capabilities.skills.buildInstallPath("01-plan/SKILL.antigravity.md")).toBe( + ".agents/skills/aidd-01-plan/SKILL.md" + ); + expect(antigravity.capabilities.skills.accepts(".agents/skills/aidd-01-plan/SKILL.md")).toBe( + true + ); + expect(antigravity.capabilities.skills.accepts(".kilo/skills/x/SKILL.md")).toBe(false); + }); + + it("is a flat host that accepts no hooks until the hooks phase", () => { + expect(antigravity.capabilities.plugins).toMatchObject({ + mode: "flat", + flatNamespacePrefix: "aidd-", + flatSkillLayout: "single-level", + acceptsHooks: false, + }); + expect(antigravity.capabilities.plugins.hooksUnsupportedReason).toContain("phase 3"); + expect(Object.keys(antigravity.capabilities).sort()).toEqual(["plugins", "skills"]); + }); + + it("declares telemetry unsupported with a reason", () => { + expect(antigravity.telemetryLocalRead).toEqual({ + kind: "unsupported", + reason: "Antigravity CLI telemetry is not yet supported by AIDD.", + }); + expect(antigravity.telemetryTaskAttributable).toBe(false); + }); +}); diff --git a/cli/tests/contexts/tools/domain/registry-conformance.unit.test.ts b/cli/tests/contexts/tools/domain/registry-conformance.unit.test.ts index 86460f37c..9ac55f719 100644 --- a/cli/tests/contexts/tools/domain/registry-conformance.unit.test.ts +++ b/cli/tests/contexts/tools/domain/registry-conformance.unit.test.ts @@ -6,6 +6,7 @@ import "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import "../../../../src/contexts/tools/domain/profiles/vscode/profile.js"; @@ -91,9 +92,12 @@ describe("AiTool contract conformance", () => { ).toBe(true); }); + // A flat-only tool builds no marketplace catalog, so it has no catalog file to probe for. it("is ingestible when it declares a plugins capability", () => { const declaresPlugins = "plugins" in (tool.capabilities as object); if (!declaresPlugins) return; + if (tool.buildContracts?.marketplace === undefined && tool.distributionProbes === undefined) + return; expect( marketplaceProbes().some((probe) => probe.format === toolId), `${toolId} declares a plugins capability but its profile declares no marketplace probe — its native marketplace would never be detected` @@ -141,6 +145,7 @@ describe("telemetryLocalRead — exact declarations, phase 2 of local-cost-read" copilot: { kind: "declared" }, cursor: { kind: "unsupported", reason: "token count" }, kilo: { kind: "unsupported", reason: "OpenTelemetry is experimental" }, + antigravity: { kind: "unsupported", reason: "not yet supported by AIDD" }, }; it.each(Object.entries(EXPECTED))("%s", (toolId, expected) => { @@ -389,7 +394,8 @@ describe("projectHooksFileOf()", () => { /** Pinned as a table rather than described, so a tool whose install path moves — or a sixth * tool added with rules — fails here instead of drifting away from the installer quietly. */ describe("every tool says where its own installed rules live", () => { - const EXPECTED: Readonly> = { + const EXPECTED: Readonly> = { + antigravity: null, claude: { directory: ".claude/rules/", extension: ".md" }, codex: { directory: ".codex/rules/", extension: ".md" }, copilot: { directory: ".github/instructions/", extension: ".instructions.md" }, diff --git a/cli/tests/contexts/tools/domain/telemetry-route-supply.unit.test.ts b/cli/tests/contexts/tools/domain/telemetry-route-supply.unit.test.ts index e45b601e7..7a5e78c83 100644 --- a/cli/tests/contexts/tools/domain/telemetry-route-supply.unit.test.ts +++ b/cli/tests/contexts/tools/domain/telemetry-route-supply.unit.test.ts @@ -5,6 +5,7 @@ import "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import { mapClaudeCodeTranscriptToSinkRecords } from "../../../../src/contexts/telemetry/domain/formats/claude-code-transcript.js"; diff --git a/cli/tests/contexts/tools/domain/tool-config.unit.test.ts b/cli/tests/contexts/tools/domain/tool-config.unit.test.ts index ddb69df31..d80d13c44 100644 --- a/cli/tests/contexts/tools/domain/tool-config.unit.test.ts +++ b/cli/tests/contexts/tools/domain/tool-config.unit.test.ts @@ -25,7 +25,7 @@ const makeStubConfig = (toolId: AiToolId, toolSuffix: string): AiTool = }); describe("VALID_TOOL_IDS", () => { - it("contains exactly claude, cursor, copilot, opencode, kilo, codex, vscode", () => { + it("contains exactly claude, cursor, copilot, opencode, kilo, codex, antigravity, vscode", () => { expect(VALID_TOOL_IDS).toEqual([ "claude", "cursor", @@ -33,6 +33,7 @@ describe("VALID_TOOL_IDS", () => { "opencode", "kilo", "codex", + "antigravity", "vscode", ]); }); @@ -67,6 +68,7 @@ describe("toolIdsForCategory()", () => { "opencode", "kilo", "codex", + "antigravity", ]); }); diff --git a/cli/tests/contexts/tools/infrastructure/host-marketplace-registry-reader-adapter.integration.test.ts b/cli/tests/contexts/tools/infrastructure/host-marketplace-registry-reader-adapter.integration.test.ts index ceeaaa307..9f155bb1f 100644 --- a/cli/tests/contexts/tools/infrastructure/host-marketplace-registry-reader-adapter.integration.test.ts +++ b/cli/tests/contexts/tools/infrastructure/host-marketplace-registry-reader-adapter.integration.test.ts @@ -8,6 +8,7 @@ import "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import { nativeActivationOf } from "../../../../src/contexts/tools/domain/registry.js"; diff --git a/cli/tests/contexts/translate/domain/plugin-content-translator.unit.test.ts b/cli/tests/contexts/translate/domain/plugin-content-translator.unit.test.ts index d0913b772..4fd3e818b 100644 --- a/cli/tests/contexts/translate/domain/plugin-content-translator.unit.test.ts +++ b/cli/tests/contexts/translate/domain/plugin-content-translator.unit.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; import { PluginsCapability } from "../../../../src/contexts/tools/domain/capabilities/plugins-capability.js"; +import { antigravity } from "../../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import { claude } from "../../../../src/contexts/tools/domain/profiles/claude/profile.js"; import { codex } from "../../../../src/contexts/tools/domain/profiles/codex/profile.js"; import { copilot } from "../../../../src/contexts/tools/domain/profiles/copilot/profile.js"; @@ -251,6 +252,12 @@ describe("PluginContentTranslator.translate()", () => { }); }); + describe("antigravity target (flat mode, one-level skills)", () => { + it("emits a skill as .agents/skills/-/, never nested under the plugin", () => { + expect(pathsFor(antigravity)).toEqual([".agents/skills/sample-plugin-hello/SKILL.md"]); + }); + }); + describe("vscode (IDE tool)", () => { it("returns empty array", () => { expect(translator.translate(makeDist(), vscodeToolConfig)).toEqual([]); diff --git a/cli/tests/e2e/clean-antigravity-foreign-file.e2e.test.ts b/cli/tests/e2e/clean-antigravity-foreign-file.e2e.test.ts new file mode 100644 index 000000000..3f94b5576 --- /dev/null +++ b/cli/tests/e2e/clean-antigravity-foreign-file.e2e.test.ts @@ -0,0 +1,48 @@ +import { existsSync } from "node:fs"; +import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { describe, expect, it } from "vitest"; +import { createTestEnv, runCli } from "./helpers.js"; + +const FRAMEWORK_REAL_PATH = resolve(process.cwd(), "tests/fixtures/framework-real"); +const OWN_SKILL = "aidd-vcs-01-commit/SKILL.md"; +const FOREIGN_SKILL = "# mine\n"; + +describe("E2E: antigravity under a .agents/ it does not own", () => { + it("clean removes the skills it wrote and leaves a user skill beside them", async () => { + const test = await createTestEnv("clean-antigravity-foreign"); + try { + const skills = join(test.projectDir, ".agents", "skills"); + const foreign = join(skills, "mine", "SKILL.md"); + await mkdir(join(skills, "mine"), { recursive: true }); + await writeFile(foreign, FOREIGN_SKILL); + + const setup = await runCli( + [ + "setup", + "--source", + "local", + "--path", + FRAMEWORK_REAL_PATH, + "--ai", + "antigravity", + "--plugins", + "aidd-vcs", + "--yes", + ], + test.projectDir, + test.fakeHome + ); + expect(setup.exitCode).toBe(0); + expect(existsSync(join(skills, OWN_SKILL))).toBe(true); + + const clean = await runCli(["clean", "--force"], test.projectDir, test.fakeHome); + + expect(clean.exitCode).toBe(0); + expect(existsSync(join(skills, OWN_SKILL))).toBe(false); + expect(await readFile(foreign, "utf-8")).toBe(FOREIGN_SKILL); + } finally { + await test.cleanup(); + } + }); +}); diff --git a/cli/tests/fixtures/cli-owns-read/expected-envelope.json b/cli/tests/fixtures/cli-owns-read/expected-envelope.json index 00d396af9..5bdfffe1b 100644 --- a/cli/tests/fixtures/cli-owns-read/expected-envelope.json +++ b/cli/tests/fixtures/cli-owns-read/expected-envelope.json @@ -242,6 +242,20 @@ "cache_read_tokens": 2000, "cache_creation_tokens": 0 } + }, + { + "tool": "antigravity", + "coverage": "not-covered", + "reason": "Antigravity CLI telemetry is not yet supported by AIDD.", + "capability": { + "local_read": null, + "export": null, + "journal_attributable": false, + "task_attributable": false + }, + "totals": { + "requests": 0 + } } ], "by_project": [ diff --git a/cli/tests/golden/framework-build-golden.e2e.test.ts b/cli/tests/golden/framework-build-golden.e2e.test.ts index 9d6686ec8..597a7b814 100644 --- a/cli/tests/golden/framework-build-golden.e2e.test.ts +++ b/cli/tests/golden/framework-build-golden.e2e.test.ts @@ -20,7 +20,15 @@ type TargetSnapshot = Record; // rel-path → sha256 type GoldenSnapshot = Record; // key → files const MARKETPLACE_TARGETS = ["copilot", "codex", "claude", "cursor"] as const; -const FLAT_TARGETS = ["claude", "cursor", "copilot", "codex", "opencode", "kilo"] as const; +const FLAT_TARGETS = [ + "claude", + "cursor", + "copilot", + "codex", + "opencode", + "kilo", + "antigravity", +] as const; const FROZEN_CELLS = new Set([ ...MARKETPLACE_TARGETS, @@ -107,7 +115,7 @@ async function captureAllCells( return captured; } -describe.concurrent("Framework build golden — 10-cell matrix", () => { +describe.concurrent("Framework build golden — 11-cell matrix", () => { // Two full 9-cell builds measured just past the 60s default on a Windows runner, not a // hang. Raised per test so no other e2e file's budget moves. it("snapshot is deterministic (two captures of each target are byte-identical)", async () => { @@ -154,7 +162,7 @@ describe.concurrent("Framework build golden — 10-cell matrix", () => { } }, 120_000); - it("every one of the 10 cells is byte-identical to its stored baseline", async () => { + it("every one of the 11 cells is byte-identical to its stored baseline", async () => { const { tempDir, projectDir, fakeHome, cleanup } = await createTestEnv("fb-golden-baseline"); try { const captured = await captureAllCells(projectDir, fakeHome, tempDir); diff --git a/cli/tests/golden/snapshots/framework-build/golden.json b/cli/tests/golden/snapshots/framework-build/golden.json index bd0495052..9888b25a7 100644 --- a/cli/tests/golden/snapshots/framework-build/golden.json +++ b/cli/tests/golden/snapshots/framework-build/golden.json @@ -1945,5 +1945,189 @@ ".kilo/agents/aidd-dev-implementer.md": "4b4fe709e0ed56b097b697a49f6adfc200cccaad36a0e978a12e4f062a3a5e38", ".kilo/agents/aidd-dev-planner.md": "c83648c34068b6fa762fdc6b073e31cb3e9dfe5bd5bf2fd7e2cb4ad3e865feee", ".kilo/agents/aidd-dev-reviewer.md": "30e2dbb93309d23fc99cbce36a4fcfd0b6d76e49c3425979827727327ba697a6" + }, + "antigravity:flat": { + ".agents/skills/aidd-vcs-04-issue-create/SKILL.md": "3983ed1c71124786fdf737ec5447637a31b1cc146eff43003978cec50c2ddc67", + ".agents/skills/aidd-vcs-04-issue-create/evals/scenarios.json": "d113c62aae4867e425737948c39c9f687f56c3d37234eca345a2f65f1a234c30", + ".agents/skills/aidd-vcs-04-issue-create/assets/CONTRIBUTING.md": "1372c7512c02c26e21643ae523a98d7c90ff92c03633532a8c417b4ca8d9e75f", + ".agents/skills/aidd-vcs-04-issue-create/assets/issue-template.md": "66b4ef6090208512205fce0bb16edbbcf0ffb19009eae76dc317d738c7a10cdc", + ".agents/skills/aidd-vcs-04-issue-create/actions/01-issue-create.md": "e3f60414fa3ce2d78583e5cb118dad8df956927aa86e2f6e802031a7d742d7ed", + ".agents/skills/aidd-vcs-03-release-tag/SKILL.md": "0052405cdf2deeb07b123e8f94ee47a2b4ecea6031641315ce71fc6cff3faabb", + ".agents/skills/aidd-vcs-03-release-tag/evals/scenarios.json": "fdba5d61f815b956512f84baf712cde92be651593282b43ac173b2459ee9eca3", + ".agents/skills/aidd-vcs-03-release-tag/assets/release-template.md": "bce05178ae5ea7da6c356849ba69eebd249ba344c94a3c571d7d40be9d4e9e27", + ".agents/skills/aidd-vcs-03-release-tag/actions/01-release-tag.md": "b2f6c6cce5f7c83f83e4b2fd84c7aae3888bdfcd29f1be3d3e2bc362b18eae6b", + ".agents/skills/aidd-vcs-02-pull-request/SKILL.md": "80c8d4f2dc28e4d1b67d418c12a865ba74ffc8b57720eb05bdf1e1fca3b82a6a", + ".agents/skills/aidd-vcs-02-pull-request/evals/scenarios.json": "63f63e6b13038672fbe325509deb32a9b25a50a996b687c001dfc74815a0dccd", + ".agents/skills/aidd-vcs-02-pull-request/assets/CONTRIBUTING.md": "1372c7512c02c26e21643ae523a98d7c90ff92c03633532a8c417b4ca8d9e75f", + ".agents/skills/aidd-vcs-02-pull-request/assets/README.md": "fb774bb7e5a19a39b21619879ee5045d7b3a0952be3f4b61aea524b93e9c9086", + ".agents/skills/aidd-vcs-02-pull-request/assets/branch.md": "92880244478c3e48c4f105e3ab2f9c09850778f84f1e44108ff8e912ccb0bea3", + ".agents/skills/aidd-vcs-02-pull-request/assets/pull_request.md": "66939eaae42c729f3b05f8dcc2546a1e4227441d9d156d692fc7ced89d07a11f", + ".agents/skills/aidd-vcs-02-pull-request/actions/01-pull-request.md": "3c3753569b5f336e6c53ac8312ba6f9538ccc711e16fb7847ca1ebf04250a790", + ".agents/skills/aidd-vcs-01-commit/SKILL.md": "1825b3994a89c0394271c3437a772e74892e4bfb5fac9c2dbc90739544404585", + ".agents/skills/aidd-vcs-01-commit/evals/scenarios.json": "bdefba21f63f7ef737ff3431077278cc45b722e85ba4b66e3a4adf4d34e0b2ff", + ".agents/skills/aidd-vcs-01-commit/assets/commit-template.md": "b3c392c5c3faecc903bf80eb2bd287d2a02e42d4c3896490a5745d66fca60bf2", + ".agents/skills/aidd-vcs-01-commit/actions/01-commit.md": "06ded7f8c23e950b3b1a76b0bb89c219d1ca161cb8f9a02e04e8083ad7061dc0", + ".agents/skills/aidd-refine-03-condense/SKILL.md": "2d6db1071f826db1cf030fb8a34aeaf0adc79884a29750efa9fe378ab12d8593", + ".agents/skills/aidd-refine-03-condense/references/intensity-levels.md": "8e6aa26fc675a2d30dbb4df13e68d0ce6d2844c88bafd39e0ea3f2945e3276f1", + ".agents/skills/aidd-refine-03-condense/evals/scenarios.json": "c03016b5e98c5a9a8b6680035bf8ee0f2a75edc5ce33e33cf1e1430cd91f55ec", + ".agents/skills/aidd-refine-03-condense/actions/01-condense.md": "bffb26d5a306bc90f40614b29ca21e9a2151dc5ba82880c857e29c39486a16fd", + ".agents/skills/aidd-refine-02-challenge/SKILL.md": "0e05299821bb3e41834cd8ff97ffa23f48342974b4e20c1e9ea59ce83255eed8", + ".agents/skills/aidd-refine-02-challenge/references/confidence-rubric.md": "714f1bfd0c33f2adf911c93e9bb2f113be9fd29bad07d83e54be293fc44de823", + ".agents/skills/aidd-refine-02-challenge/evals/scenarios.json": "332403843b5b5d99a9dcb3464f298ca3b7274edbd1b5c337407a4dd977bc19a5", + ".agents/skills/aidd-refine-02-challenge/actions/01-challenge.md": "6f47920ccec8682708789e07583e32698695f1274bf883757ab13fca6f3e76c0", + ".agents/skills/aidd-refine-01-brainstorm/SKILL.md": "e29675b330838d6bd843f40c227fd64ae46e9162c3c3b5db4d8695d9f6b38f17", + ".agents/skills/aidd-refine-01-brainstorm/references/ambiguity-detection.md": "c869338af0d8e0bdde5915000ce44980fef750cc40d070d4055bcba4c1334e0f", + ".agents/skills/aidd-refine-01-brainstorm/evals/scenarios.json": "c6858f3b6b8efa666e2c7f21f4325f5e57297e3fdfc475b836f3ce5de9d635bf", + ".agents/skills/aidd-refine-01-brainstorm/assets/question-templates.md": "bd744429e69f26caf37359e2b1d1c38dc4faba1a2c54dfaa99bfde48da0dc3c8", + ".agents/skills/aidd-refine-01-brainstorm/actions/01-capture-request.md": "bc133963be4eeb68d6653a65f88f2e1820d711d6d7bf74b79a6225fff7b8e6c8", + ".agents/skills/aidd-refine-01-brainstorm/actions/02-ask-probing-questions.md": "d8a25b7e2c0861bc4bce878e7d10dcda279855fa0db06d1997ad84f3e5682d54", + ".agents/skills/aidd-refine-01-brainstorm/actions/03-integrate-answers.md": "b6f2c34f4f03cca48e83ed6fff5936e8ddbecae5fef1f597e99fd764e13f32cd", + ".agents/skills/aidd-refine-01-brainstorm/actions/04-refine-and-validate.md": "4a6368a3e189c3022f133050f996eda3d9195281a3e4bbabdd120f5b8b414c3c", + ".agents/skills/aidd-refine-01-brainstorm/actions/05-confirm-approval.md": "3c6c8184910a210bb6698c2c010aebec88a28313b31bbed0ef9c1189530cd6fe", + ".agents/skills/aidd-pm-05-spec/SKILL.md": "32a14c6e9b275630363a0cca29ebd3c6c35271fa38be9eb79cc0e41e8e6e478b", + ".agents/skills/aidd-pm-05-spec/assets/spec-template.md": "2f7e446c4ec58d05a471212e9ab3ba64395bdd059943620d02bf1bf5c98777c2", + ".agents/skills/aidd-pm-05-spec/assets/spec-validator.yml": "2358c6f0baa5656ddcff9410149cf8261d54199d8722f77769f76ca0d7c8cf18", + ".agents/skills/aidd-pm-04-clarity/SKILL.md": "5f50dcfdf1c96f1ce71eed10dd791e1a2945eb9e761e8d42beca3519370ba55b", + ".agents/skills/aidd-pm-03-prd/SKILL.md": "b3ac6ea89c9642651135cb9f7dea8bdf47fb3bc4ea777216d2f65b5459dd0c6b", + ".agents/skills/aidd-pm-03-prd/assets/prd-template.md": "af01423720e8c9527ff12a2e9ad1de39c6e63c6569359be08defd0a059aabea9", + ".agents/skills/aidd-pm-03-prd/assets/task-template.md": "c0069ed2ecce4742629dccd6be709d4e5a71f3db3821310c381c054aeb479289", + ".agents/skills/aidd-pm-03-prd/actions/01-prd.md": "c0da6597f8c465ad50a17a07543152f53de1fbccc28cd906763d439004084a22", + ".agents/skills/aidd-pm-02-user-stories-create/SKILL.md": "d95bad3cfd000c1e8dba905a152384320a177f5891bdaa218819ffe55f6ad710", + ".agents/skills/aidd-pm-02-user-stories-create/assets/user-story-template.md": "59ecd98d00057313414a74a94c19c0f2d167957e1080b880ee68a69a31948320", + ".agents/skills/aidd-pm-02-user-stories-create/actions/01-create-user-stories.md": "6fad8968a1e787c197764c4a8c09b17c521ae5ea2286a5082addc717bd72b1e6", + ".agents/skills/aidd-pm-01-ticket-info/SKILL.md": "26e0491f8527a073f6685ffe7c3e15a22f230a22837aea92694d34a7a2f2f29d", + ".agents/skills/aidd-pm-01-ticket-info/actions/01-ticket-info.md": "f075ea6ff626534dbe0826d06b67fae93b6488ec4c5c7a3d857f1d05f73d0630", + ".agents/skills/aidd-dev-08-for-sure/SKILL.md": "07a94d0a975a8b6f4e2be89b3fd9d68b9b71bd9843836c76e1aa074685cc4376", + ".agents/skills/aidd-dev-08-for-sure/actions/01-init-tracking.md": "3ce6bb19135e5d31c4d2ad1c2151c1563886a611f2399b47624368268a79dcdf", + ".agents/skills/aidd-dev-08-for-sure/actions/02-auto-accept.md": "235818118c772c0f499ea0668bfbc7bd00c2aae34e6bbd8b13b912fddfa79705", + ".agents/skills/aidd-dev-08-for-sure/actions/03-autonomous-loop.md": "b19d4520ad716def3c2a4611c37725cba9af713cd4bcb668c237e874e1e43843", + ".agents/skills/aidd-dev-07-debug/SKILL.md": "860f4137ca48a43470d52f76ae8e631204e5fd7dd82a661905d40bd583bf56fc", + ".agents/skills/aidd-dev-07-debug/references/mermaid-conventions.md": "85826285744909dd4c4706b82f0dbeff4f88a8f191cb22d538aa12c3c96365eb", + ".agents/skills/aidd-dev-07-debug/assets/task-template.md": "c0069ed2ecce4742629dccd6be709d4e5a71f3db3821310c381c054aeb479289", + ".agents/skills/aidd-dev-07-debug/actions/01-reproduce.md": "7e902e5aadc9162b444b341deb33f2a683000c1cc4722ad856496f9d740ec17d", + ".agents/skills/aidd-dev-07-debug/actions/02-debug.md": "dc3900ce6fb76074b88034d7b7316f4051d78a1828caa3acef9786e8ea582b18", + ".agents/skills/aidd-dev-07-debug/actions/03-reflect-issue.md": "3d5f18634618737870da4c783c7525cee25e09d942faee80125dd7536978ce12", + ".agents/skills/aidd-dev-06-refactor/SKILL.md": "6fbf8c363728a11288c58f6967d36845aa4709a9a69a62bd6c6d9ca6d39135ba", + ".agents/skills/aidd-dev-06-refactor/actions/01-performance.md": "1f7d500967de58875aeb14b732a1af377b17edff8654f4365b3f29743debb3c7", + ".agents/skills/aidd-dev-06-refactor/actions/02-security.md": "db55b81ab824d81b765189296deb1ce31fdb134edac186baf22a2c3bb1cde938", + ".agents/skills/aidd-dev-05-test/SKILL.md": "131c810499c0673ace51a2385640dc533203ca89560f72a381bef4a2abf9d388", + ".agents/skills/aidd-dev-05-test/actions/01-test.md": "f6db9653cd29729c51653df7afe473fae4ae45bb126a694a367bfd84fa1785a4", + ".agents/skills/aidd-dev-05-test/actions/02-test-journey.md": "1eeb85da69abc3f1fc3e5671e83962f44fcb5686d9ca5972eeb2ba4cab31306d", + ".agents/skills/aidd-dev-04-review/SKILL.md": "87b2de872bd37fa19b12f458f6c30d60ca65de8ce2988dc63d0811cdec4720cc", + ".agents/skills/aidd-dev-04-review/assets/code-review-template.md": "e270c4b6b8c69e4fbbbcc08c2f91cc9a09fc8ad155b6f52cec3e3d34a262324d", + ".agents/skills/aidd-dev-04-review/assets/review-functional-template.md": "a84b48347caf4d09d84994b07329e4d05c8053d45630b37d47ca3ccb386e3146", + ".agents/skills/aidd-dev-04-review/assets/review-template.md": "b0ad0ab703e4d9ed960bd324bc37efe5f682cbcd40ed6293791d9074f174201c", + ".agents/skills/aidd-dev-04-review/actions/01-review-code.md": "8d5e4fc6c9243a83025961ae40146f1d96f321d9ff4d93ab74c370bbc53c18ed", + ".agents/skills/aidd-dev-04-review/actions/02-review-functional.md": "9e5d837715f5610a42f1c294b0fa71277538e2629dc47cf09675487dcfa98324", + ".agents/skills/aidd-dev-03-audit/SKILL.md": "da84a82a3446283034f26ad5a335d7f8a48ecd501c254af2f4ddaccd09cd4e0f", + ".agents/skills/aidd-dev-03-audit/actions/01-audit.md": "0371ae3d0c9a383f8b90657f3381717f323742bad922df2c1c508f6db013267e", + ".agents/skills/aidd-dev-02-assert/SKILL.md": "a75c5fe87f257fe476129d8eb5b89267df6563924e5c84bb4ea6c1d7215b14ad", + ".agents/skills/aidd-dev-02-assert/assets/task-template.md": "c0069ed2ecce4742629dccd6be709d4e5a71f3db3821310c381c054aeb479289", + ".agents/skills/aidd-dev-02-assert/actions/01-assert.md": "b8a9680e7cf956f2e1ff7720f755586e2523d6951c35ec686ded659f7fa3a4b1", + ".agents/skills/aidd-dev-02-assert/actions/02-assert-architecture.md": "e5d7effa39f33c045e4d605ed909d46ddf7562e2a0199eb2e39fcc8f3fc92620", + ".agents/skills/aidd-dev-02-assert/actions/03-assert-frontend.md": "ed9751b32580c7fd3fbe02a8205cbb5d85a8e7bc38f982b5130b810950bbd091", + ".agents/skills/aidd-dev-01-plan/SKILL.md": "272aaa80349b438a1536c78e91d5c55c1ef26b65f942caa1c47edc062e0591c9", + ".agents/skills/aidd-dev-01-plan/references/mermaid-conventions.md": "85826285744909dd4c4706b82f0dbeff4f88a8f191cb22d538aa12c3c96365eb", + ".agents/skills/aidd-dev-01-plan/assets/master-plan-template.md": "f793f2bc8fad34f056e824def49527552f50cf12e43f0929731d64278376b822", + ".agents/skills/aidd-dev-01-plan/assets/plan-template.md": "cf462e831d994230c811c71eaa72a8f9880536ba3b657b70342083dee00ab254", + ".agents/skills/aidd-dev-01-plan/assets/tech-choice-template.md": "c9f16f9b598aded5953127b4bf2768b95d7abda0b75d937e0b31dfee9317c40a", + ".agents/skills/aidd-dev-01-plan/actions/01-plan.md": "c480fc1cffe39f117003b5aeea23e10f808952a0eeea067dbc0ab44c0af992ff", + ".agents/skills/aidd-dev-01-plan/actions/02-components-behavior.md": "cacb673334d8947c3c252feaaf0ef50c269c06c5cf8f51b45663cbd42402e094", + ".agents/skills/aidd-dev-01-plan/actions/03-image-extract-details.md": "6f6cddd0893888c71b0aed5ecfe48217afe0eef10feec6415db433bfcc69f8e3", + ".agents/skills/aidd-dev-00-sdlc/SKILL.md": "34964c02e338adbf393c25abc4f5862e28452f874c7640f85c950e170130c17c", + ".agents/skills/aidd-context-06-discovery/SKILL.md": "45cf7373cddfe1614b6edba32b36a9411d9136b8eab29a3ae9b43dab7ee4e912", + ".agents/skills/aidd-context-06-discovery/actions/01-find-skill.md": "600caf7822017bfe75d40773e1673ada784227b98f5b88d4ba98a57822fa0dcf", + ".agents/skills/aidd-context-05-learn/SKILL.md": "9ca8b41c8a8fac66d943ad1658ae7a2f374373d13a8a2edd66e1f7fd058694de", + ".agents/skills/aidd-context-05-learn/assets/adr-template.md": "1f9feb18109b178226885ab7edabc3d1c4dd2a77dd1fa7345be856643107ac16", + ".agents/skills/aidd-context-05-learn/assets/decision-template.md": "1e6229157fd0a07c090ce0bd159336a13554975e146966b306bf25665a179938", + ".agents/skills/aidd-context-05-learn/actions/01-learn.md": "92400bfcc2cdfe9f0bad8f2feadd7d28dce882240fe58971d25dfa880521d8bb", + ".agents/skills/aidd-context-04-mermaid/SKILL.md": "d25ac37dc7e065a1bf6eafc5a49dfaef14af85cb947e26095d6b376a32c3b416", + ".agents/skills/aidd-context-04-mermaid/references/mermaid-conventions.md": "85826285744909dd4c4706b82f0dbeff4f88a8f191cb22d538aa12c3c96365eb", + ".agents/skills/aidd-context-04-mermaid/actions/01-mermaid.md": "f70b18f429701d0c3b46a4c6e75153c732ee9e06a16aa01efec05e810ac7a6dd", + ".agents/skills/aidd-context-03-context-generate/SKILL.md": "e0f9b6c4a2eadc331c5611e1cc18c74d10633e94180bf56a6fee5aed6f984f07", + ".agents/skills/aidd-context-03-context-generate/references/agents-coordination.md": "eaaa31ed554a53f7870151307853e1add7e3ddd1de8e442b8d5e7c5698ab0098", + ".agents/skills/aidd-context-03-context-generate/references/ai-mapping.md": "4ad192b5ae53c7ceadff165a1cef8c3f24949498375bedc0cc359194dea3117e", + ".agents/skills/aidd-context-03-context-generate/references/naming-conventions.md": "fd39d00b1449f0770ee89aad9f6e84d21e1fee2efc0ff547a240b0e18f648cd8", + ".agents/skills/aidd-context-03-context-generate/references/rule-structure.md": "c8ce6eea6dbaae5309a77237d702db193a7748db5c581d0918f17db3989e414f", + ".agents/skills/aidd-context-03-context-generate/references/rule-writing.md": "e4cddd88dca3162d576a1b616c419f5ff2f3b7681a09a569da68358f3713c9e6", + ".agents/skills/aidd-context-03-context-generate/references/skill-structure.md": "2b6114ff8aa30f1a5d7bfd3bf0d7d87e429cb8d65ba13b369e6cdc9c8bec501c", + ".agents/skills/aidd-context-03-context-generate/evals/scenarios.json": "db355f13f2ca3499f912f39ada136472f9bc993846564aeaeb6eab371d485520", + ".agents/skills/aidd-context-03-context-generate/assets/skills/action-template.md": "8bd80e05dcbb10e24adb668778fd9dfb058c92193c52c6012e9f5cc11305103c", + ".agents/skills/aidd-context-03-context-generate/assets/skills/evals-template.md": "c0468fe9869895b42f7a59b48f7613ca4ef3b1af93acb7c41dc063559964ff27", + ".agents/skills/aidd-context-03-context-generate/assets/skills/skill-template.md": "f30bc5a47574cc85dc0daddfa1abd0d7f8bd8a39e201fbb3df5784506a61b13a", + ".agents/skills/aidd-context-03-context-generate/assets/rules/rule-template.md": "200ec56d8ed43acd51b94df783f7de9236b00a6e5398a98a30640d02edb76ba1", + ".agents/skills/aidd-context-03-context-generate/assets/agents/agent-template.md": "476802721ac4947d741b4bd17626860c4914037992a2ebf0ef282553f819aa25", + ".agents/skills/aidd-context-03-context-generate/actions/skills/01-capture-intent.md": "850c9b7dab101eba66284950eb3b8b612aca3ad40a1b13fcdc5ac181d1f72069", + ".agents/skills/aidd-context-03-context-generate/actions/skills/02-design-evals.md": "fc51fb2c85a7462fe27586ddc3cc5c2699214dcd059c28f7ab8daf26a6479ced", + ".agents/skills/aidd-context-03-context-generate/actions/skills/03-decompose-actions.md": "8bf7ff1ac05d968fc7a3e9b6aa5de3df3be04b07e96517cbe06268baec4151fc", + ".agents/skills/aidd-context-03-context-generate/actions/skills/04-draft-skill.md": "08946a56b720408bee9c63cd7141e6c869e6818610546f8a42628fe6d2e12514", + ".agents/skills/aidd-context-03-context-generate/actions/skills/05-write-actions.md": "948ac436af5e9c9e897b8c4e44b12a278943bff2b93afc10b4ddaee587d58cc5", + ".agents/skills/aidd-context-03-context-generate/actions/skills/06-validate.md": "658c1077b03c461bb0c3fa17db047e4d2fbc3874f4d4fbd2e3dc5df606aa03ee", + ".agents/skills/aidd-context-03-context-generate/actions/rules/01-generate-rules.md": "855b9adf65b0b0cc31ca15c68b8ac37da6a816c9a6416fbc3aea424cffa238c3", + ".agents/skills/aidd-context-03-context-generate/actions/agents/01-generate-agent.md": "3dce30335eba1d60c5a62d43184d133eed621bbc344e9277ab0f05ead443e0ba", + ".agents/skills/aidd-context-02-project-init/SKILL.md": "4bd40beb8290018b6fa58b651d3681e13465b39b84c3e4c0c39964aefcc52002", + ".agents/skills/aidd-context-02-project-init/references/mapping-ai-context-file.md": "cf251454634037d4affd1d27cee2593c555dfe29305b521d3bed4564f4cad273", + ".agents/skills/aidd-context-02-project-init/assets/AGENTS.md": "8b3d349220e9f96b45dedf316eeb2b3418666d96d0a4f64d315cadfc9ef337ae", + ".agents/skills/aidd-context-02-project-init/assets/GUIDELINES.md": "bf41995402b46268ba53ceec41be00c455004603f69035349b6ff3bef14cc18a", + ".agents/skills/aidd-context-02-project-init/assets/README.md": "575086cda27a386806a28c1bb4865cb5f974dc3fe6e39ca8bdd2c19764cf2059", + ".agents/skills/aidd-context-02-project-init/assets/golden-principles.md": "e83c582a9e1477a42531734deed90061f4e004ea28e1b1616bf714070856c888", + ".agents/skills/aidd-context-02-project-init/assets/templates/workflows/README.md": "33d50760dfde22feb8878cf3e24d399a748eef8ed2df630f465d673d9f125a53", + ".agents/skills/aidd-context-02-project-init/assets/templates/stack/README.md": "8dbccfc7d47424411b7725374247b50973a962fff777b272a23109b7e0f2a099", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/README.md": "66e6275cd7e7187ca520ad8f2f3c57ebecf967742901e00085c139fd9eea5892", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/architecture.md": "f00c02db4135a43e99f5bdd7888f40f290e39dd4a65bb1539eca9a06c9873427", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/codebase-map.md": "5d1d184bc70c93e0073cb64312f4fa8d50fcf465b0da982f37bde25d624a5386", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/coding-assertions.md": "2e3d7b16f85e8af3cf9971c3b0c23409653e8d693c969ff11892c5a4f10bea90", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/deployment.md": "361e80ebbddda1f0497856530e7a5a35cd2c8ae56df2a6ef64268657de333d28", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/project-brief.md": "0240ee41e05c6091bd136b7c3b18f603731128941c987449917886b191e38e90", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/testing.md": "760e58855270ee9210b20987b3f01b537b25f6108f8d164e2a88000f4cb278b7", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/vcs.md": "3eccc51898b8c0c17245a737c9fa540f30706676ea01ff771d6898f3861060f1", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/frontend/browsing.md": "f8ab234ba45571979a5dbc2181859a8f6859cd56c9d86371560516b3323dd8a1", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/frontend/design.md": "edcaa8ab125acd64d330a32abac102fa3d0b37b45ef03a9552c71c885c1ea847", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/frontend/forms.md": "662dd1b62a9d3fef587cf38f1c2f6fe3de2d0cb226a9ec50dd7b576bf824115b", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/backend/api-docs.md": "09b9633c1d8c3b5a11bf0d171abf148bf159836ae96223a78a52b9e56ffb52e8", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/backend/backend-communication.md": "87d548e12bed0fa2a2d7601fe1c36d810f40051abd713cc3d4462582319babde", + ".agents/skills/aidd-context-02-project-init/assets/templates/memory/backend/database.md": "899ceb107598c8b9a1adc3ff7cf8b6217e4582553f5c27f3e22b9e7fb0f555b9", + ".agents/skills/aidd-context-02-project-init/actions/01-init-context-file.md": "33c907084418ec22f8c22381fbefecfbf3d88c250781c852059bf611be0f2ae2", + ".agents/skills/aidd-context-02-project-init/actions/02-scaffold-docs.md": "c07f175692241d477b029441a2a984c2fff6de0041ff6f47a6851d73900a1ac3", + ".agents/skills/aidd-context-02-project-init/actions/03-generate-memory.md": "f7cde767985a1d7ca8c2d74c1ffcc11eac2232a97e26b46573533eefcdd5ac96", + ".agents/skills/aidd-context-02-project-init/actions/04-review-memory.md": "211ad0ad0d7c4925acbd8a41f775a16b09de51b85d9f3fc6f972170ac63fd353", + ".agents/skills/aidd-context-02-project-init/actions/05-init-rules-skeleton.md": "12924f4535c083e114a5a4a4ef148e4aa2c8c4c436d23c8f50e152f869e3be2c", + ".agents/skills/aidd-context-02-project-init/actions/06-sync-memory.md": "3f6825c8d230cea72f729aee15cf6136b613b7a9b07ddec237b91fe5ad3be59b", + ".agents/skills/aidd-context-01-bootstrap/SKILL.md": "be11990b997d32ff2acb7c49eba7d63899ffbe161827e4c25d330debace71805", + ".agents/skills/aidd-context-01-bootstrap/references/stack-heuristics.md": "17f7c0df7b19090f42c26ddf70df1049897b3973d9c1bf8df358b87a1cc9985a", + ".agents/skills/aidd-context-01-bootstrap/evals/scenarios.json": "c5998a91c584d561618dbabe66f21bd8f446260731778de4f467a70a6da21784", + ".agents/skills/aidd-context-01-bootstrap/assets/checklist.md": "64b84a7712ca78bc1901d2c78c183310336a4abe1b5890a689c3cf166b026d21", + ".agents/skills/aidd-context-01-bootstrap/assets/install-template.md": "cd67115a7b11fddea0258810b9cee1d35c3e12840f515c5364fa769cad9d6a60", + ".agents/skills/aidd-context-01-bootstrap/actions/01-gather-needs.md": "b3251034285434b06775ab4a59ffe27259bb23cb97ac65927c946a4846ea946d", + ".agents/skills/aidd-context-01-bootstrap/actions/02-propose-candidates.md": "57376071d9d0b011c5f19ba218a3ef28c3bf1fba1220a87260806a2d79e341d6", + ".agents/skills/aidd-context-01-bootstrap/actions/03-audit-candidates.md": "def30caedeca0babb4500b2081fe46bdcaf72ee911e4ad94ae860b068c2ee0e0", + ".agents/skills/aidd-context-01-bootstrap/actions/04-pick-and-design.md": "1444ede4a16e6df368792d7f214e0bb61912621a9c266205e031ec73151606e7", + ".agents/skills/aidd-context-01-bootstrap/actions/05-write-install-md.md": "c94afb152683cc29f10d2d4451632265b7fdc763a8a41b69f8ddc2c00b81dfd0", + ".agents/skills/aidd-async-dev-03-review/SKILL.md": "12577d34b7e03ac89407075bbeb998925e9d1043620913767d390d1153151e39", + ".agents/skills/aidd-async-dev-03-review/references/stop-conditions.md": "47280ec7ebb0bd2d25bb7bf7dd716f5ef41a0ad8163653fa139981b5283e7ba0", + ".agents/skills/aidd-async-dev-03-review/evals/scenarios.json": "562d462eedcb589487585a6840d3077a8cce760ea4ecd5e416a8a01b8472d995", + ".agents/skills/aidd-async-dev-03-review/actions/skills/01-collect-comments.md": "a7494fcd9ec705cf76d36ed9b7ce59b2d9ed6e82ce64084e2ed935d52ab57527", + ".agents/skills/aidd-async-dev-03-review/actions/skills/02-detect-stop.md": "b5d40992028d2e0a1d59f31dd699237005ebb51d9c70a648aca7f757f7449659", + ".agents/skills/aidd-async-dev-03-review/actions/skills/03-fix-iteration.md": "a3133409542ed6fc8e9b814658be68504e646cc44ed58ca749251c6b6dd45f25", + ".agents/skills/aidd-async-dev-03-review/actions/skills/04-finalize.md": "bf01c103e3940fda6fd07092bd35f44993f24cdd25ec7ff5c52004b20a37cb17", + ".agents/skills/aidd-async-dev-02-run/SKILL.md": "63fa98e5a2e3baaa8a4b1e55fa894f4d98fe47e4dbdc0ae5be2c6c5d7f894e01", + ".agents/skills/aidd-async-dev-02-run/evals/scenarios.json": "cf78e4c46ac988912a7de98b1a1143c439d3c744bef234d7294f17b4836a84d0", + ".agents/skills/aidd-async-dev-02-run/actions/skills/01-poll-ready.md": "38b0767d080c60149fc4dd1b04395c72b6cda204bd2152d2f9be54db814626fd", + ".agents/skills/aidd-async-dev-02-run/actions/skills/02-resolve-deps.md": "9ede89ff3396287bde2ed9fed6e8068a8411b9190dc446ec392badaf31a52a5f", + ".agents/skills/aidd-async-dev-02-run/actions/skills/03-acquire-lock.md": "0a9b54f4bc9ebdb653932b57bd9d61e9ee7248d86104bc95841617beb4eeeee5", + ".agents/skills/aidd-async-dev-02-run/actions/skills/04-check-sdlc.md": "1934b9f0fb5824736349070ceca67105892ef7e4f319ca95ae955f564e821633", + ".agents/skills/aidd-async-dev-02-run/actions/skills/05-delegate-sdlc.md": "3142a7d2ee15d1871fecc1b4977ff3fb43b9a343f25913a54cc943d9fab31a7c", + ".agents/skills/aidd-async-dev-02-run/actions/skills/06-write-audit.md": "3cfbabf8f6c6e267994afcf189d17234eac4c3bb35ab68408776f1acb644b6ba", + ".agents/skills/aidd-async-dev-02-run/actions/skills/07-emit-webhook.md": "4c8fe76bdf265386247a636dafc9365946114afa54c479ef13abfd929d7af3db", + ".agents/skills/aidd-async-dev-01-setup/SKILL.md": "ce55273c1d1109267f8725edfeb654df9ad4c84e9055998b0e29f9817c6befa3", + ".agents/skills/aidd-async-dev-01-setup/references/auth-modes.md": "4122f895e4b210fce0e8f4cac81a79f6711eca56edac02ac43235359a77c2f62", + ".agents/skills/aidd-async-dev-01-setup/evals/scenarios.json": "79b49984a0999a3f34348bedbf8e7fe815ebdddf825701fabfedbe39f7a1ede2", + ".agents/skills/aidd-async-dev-01-setup/assets/config-template.json": "d47d1d93014157d525f48f3c96626472d940fafffc0deb106af2371db97b4e83", + ".agents/skills/aidd-async-dev-01-setup/assets/workflow-template.yml": "63be55459862cf9c1f9943ac48dde6f1304a0fd3c3231b608e2217f8ee785d3f", + ".agents/skills/aidd-async-dev-01-setup/actions/skills/01-detect-context.md": "83f3ba3022dd75fa2597a872a55e8f75173762f932ed39ae73d8181c0b1b4536", + ".agents/skills/aidd-async-dev-01-setup/actions/skills/02-ask-config.md": "986335d1e86a633d0083fe4488aae58266a82ec35d0cdb0b74f0bbcea70e6f4e", + ".agents/skills/aidd-async-dev-01-setup/actions/skills/03-generate-workflow.md": "11f7ec6c03284d0524179f71337691301a6362cf77bf3aa666fe41686b4df40b", + ".agents/skills/aidd-async-dev-01-setup/actions/skills/04-write-config.md": "eb7ecb812e8bdaaeba2e56c71c77bf8c14fce0a2c44311ff7985444617635dd5", + ".agents/skills/aidd-async-dev-01-setup/actions/skills/05-bootstrap-labels.md": "f53177ce1c58767f1bdfcfa3e72f7d4cc5e3d4fd782c35c3998815317be108b1" } } diff --git a/cli/tests/golden/snapshots/help/surface.json b/cli/tests/golden/snapshots/help/surface.json index c69798490..a46175224 100644 --- a/cli/tests/golden/snapshots/help/surface.json +++ b/cli/tests/golden/snapshots/help/surface.json @@ -192,7 +192,7 @@ { "invocation": "aidd translate", "exitCode": 0, - "help": "Usage: aidd translate [options] \n\nConvert an arbitrary source into a target-native plugin tree — records nothing\n(see `sync` for the manifest-driven, tracked version)\n\nArguments:\n source Path to the source framework directory\n\nOptions:\n --to Conversion target (claude, cursor, copilot, codex,\n opencode, kilo)\n --out Output directory (marketplace dist or project root)\n --as Output layout (default: \"marketplace\")\n --force Overwrite existing files at canonical paths under\n --out\n -h, --help display help for command" + "help": "Usage: aidd translate [options] \n\nConvert an arbitrary source into a target-native plugin tree — records nothing\n(see `sync` for the manifest-driven, tracked version)\n\nArguments:\n source Path to the source framework directory\n\nOptions:\n --to Conversion target (claude, cursor, copilot, codex,\n opencode, kilo, antigravity)\n --out Output directory (marketplace dist or project root)\n --as Output layout (default: \"marketplace\")\n --force Overwrite existing files at canonical paths under\n --out\n -h, --help display help for command" }, { "invocation": "aidd update", diff --git a/cli/tests/golden/snapshots/phase0/snapshot.json b/cli/tests/golden/snapshots/phase0/snapshot.json index 93c16f4cf..eced22c81 100644 --- a/cli/tests/golden/snapshots/phase0/snapshot.json +++ b/cli/tests/golden/snapshots/phase0/snapshot.json @@ -800,7 +800,7 @@ "command": "[errors] framework install --tool not-a-tool", "exitCode": 1, "stdout": "", - "stderr": "Error: Unknown tool: not-a-tool. Valid tools: claude, cursor, copilot, opencode, kilo, codex, vscode\n", + "stderr": "Error: Unknown tool: not-a-tool. Valid tools: claude, cursor, copilot, opencode, kilo, codex, antigravity, vscode\n", "filesWritten": [], "manifest": null }, diff --git a/cli/tests/helpers/ports/build-unit-deps.ts b/cli/tests/helpers/ports/build-unit-deps.ts index 266d86bf3..5e0ad8e4b 100644 --- a/cli/tests/helpers/ports/build-unit-deps.ts +++ b/cli/tests/helpers/ports/build-unit-deps.ts @@ -4,6 +4,7 @@ import "../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import "../../../src/contexts/tools/domain/profiles/vscode/profile.js"; diff --git a/cli/tests/presentation/commands/translate-wiring.integration.test.ts b/cli/tests/presentation/commands/translate-wiring.integration.test.ts index 5fb23b017..8d593c36e 100644 --- a/cli/tests/presentation/commands/translate-wiring.integration.test.ts +++ b/cli/tests/presentation/commands/translate-wiring.integration.test.ts @@ -5,6 +5,7 @@ import "../../../src/contexts/tools/domain/profiles/claude/profile.js"; import "../../../src/contexts/tools/domain/profiles/codex/profile.js"; import "../../../src/contexts/tools/domain/profiles/copilot/profile.js"; import "../../../src/contexts/tools/domain/profiles/cursor/profile.js"; +import "../../../src/contexts/tools/domain/profiles/antigravity/profile.js"; import "../../../src/contexts/tools/domain/profiles/kilo/profile.js"; import "../../../src/contexts/tools/domain/profiles/opencode/profile.js"; import "../../../src/contexts/tools/domain/profiles/vscode/profile.js"; @@ -211,7 +212,7 @@ describe("aidd translate — the help surface", () => { ).toEqual([ [ "--to ", - "Conversion target (claude, cursor, copilot, codex, opencode, kilo)", + "Conversion target (claude, cursor, copilot, codex, opencode, kilo, antigravity)", undefined, ], ["--out ", "Output directory (marketplace dist or project root)", undefined], diff --git a/cli/tests/presentation/prompts/interactive-menu-use-case.unit.test.ts b/cli/tests/presentation/prompts/interactive-menu-use-case.unit.test.ts index fa4015ae1..96e5fd9ad 100644 --- a/cli/tests/presentation/prompts/interactive-menu-use-case.unit.test.ts +++ b/cli/tests/presentation/prompts/interactive-menu-use-case.unit.test.ts @@ -524,11 +524,11 @@ describe("interactive menu — the command each pick hands over", () => { it.each([ [ ["inspect", "doctor-tool"], - "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, vscode)", + "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, antigravity, vscode)", ], [ ["manage-tools", "framework-install"], - "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, vscode)", + "Tool (e.g. claude, cursor, copilot, codex, opencode, kilo, antigravity, vscode)", ], [["manage-tools", "framework-remove"], "Tool to remove"], [["manage-tools", "framework-update-one"], "Tool to update"], diff --git a/docs/MAINTAINERS.md b/docs/MAINTAINERS.md index 982af57d2..6ae24b5c2 100644 --- a/docs/MAINTAINERS.md +++ b/docs/MAINTAINERS.md @@ -68,7 +68,7 @@ release-please opens/updates a `chore: release main` PR on each push to `main`. 3. CI tags each bumped package, creates the GitHub Releases, and attaches the bundles: - `aidd-framework-marketplace-X.Y.Z.zip` (`.claude-plugin/` + `plugins/`) - `-vX.Y.Z.zip` - - `aidd-framework---X.Y.Z.zip` - per-tool distributions (10 archives: 4 marketplace claude/cursor/copilot/codex + 6 flat incl. opencode and kilo), produced by the `build-per-tool` matrix job in `ci.yml`. It builds the CLI from this run's own checkout and runs `translate --to --out --as ` — no published-version pin to bump. + - `aidd-framework---X.Y.Z.zip` - per-tool distributions (11 archives: 4 marketplace claude/cursor/copilot/codex + 7 flat incl. opencode, kilo and antigravity), produced by the `build-per-tool` matrix job in `ci.yml`. It builds the CLI from this run's own checkout and runs `translate --to --out --as ` — no published-version pin to bump. Versions live in `.release-please-manifest.json`. Forcing a version / pre-release: `release-as` in `release-please-config.json` (remove it after the release ships). diff --git a/scripts/__tests__/smoke-real-user-scope-tool-list-parity.test.js b/scripts/__tests__/smoke-real-user-scope-tool-list-parity.test.js index 93ffd51bb..2b88d1147 100644 --- a/scripts/__tests__/smoke-real-user-scope-tool-list-parity.test.js +++ b/scripts/__tests__/smoke-real-user-scope-tool-list-parity.test.js @@ -47,7 +47,7 @@ describe("smoke-real.sh drives --scope user with the tools the profiles support" it("leaves out AI tools that declare neither, which setup --scope user refuses", () => { const unsupported = aiToolIds().filter((id) => !declaresUserScopeActivation(id)); - assert.deepEqual([...unsupported].sort(), ["kilo", "opencode"]); + assert.deepEqual([...unsupported].sort(), ["antigravity", "kilo", "opencode"]); for (const toolId of unsupported) { assert.ok( !scriptUserAiList().includes(toolId), From 6b213e8263db7e354f7e567dbfc312a2b694a095 Mon Sep 17 00:00:00 2001 From: Thierry Kwiatkowski Date: Mon, 5 Oct 2026 18:12:05 +0200 Subject: [PATCH 2/2] test(cli): check antigravity's .agents/ in the setup smoke The setup smoke asserts a `./` directory per AI tool, but Antigravity writes under the shared `.agents/` root, so `pnpm smoke` failed with "antigravity dir missing after --ai all". Refs #511 Co-Authored-By: Claude Opus 5.5 --- cli/scripts/smoke-tools.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/scripts/smoke-tools.sh b/cli/scripts/smoke-tools.sh index cd84a7e1c..79a20e869 100755 --- a/cli/scripts/smoke-tools.sh +++ b/cli/scripts/smoke-tools.sh @@ -306,6 +306,9 @@ if true; then [[ ! -d "$BASE/.github" ]] \ && ok "copilot declarative settings absent without native source proof" \ || bad "copilot declarative settings written without native source proof" + elif [[ "$t" == antigravity ]]; then + # Antigravity reads the shared `.agents/` root, not a directory named after itself. + [[ -d "$BASE/.agents/skills" ]] && ok "$t dir present" || bad "$t dir missing after --ai all" else [[ -d "$BASE/.${t}" ]] && ok "$t dir present" || bad "$t dir missing after --ai all" fi