feat(core): Antigravity 등 .agents/skills 규약을 읽는 하네스를 지원한다
All checks were successful
ci / build (push) Successful in 25s
release / release (push) Successful in 40s

Antigravity 에서 스킬로 인식되지 않는다는 제보를 받고 확인했다.
설치 경로가 없었던 것이 원인이다.

공식 문서 기준 경로:
  워크스페이스  <root>/.agents/skills/<이름>/
  전역         ~/.gemini/config/skills/<이름>/

.agents/skills 는 특정 제품 경로가 아니라 중립 경로라, 같은 규약을 쓰는
다른 하네스도 함께 읽는다. SKILL.md 구조(프론트매터 + references/)가
Claude Code 와 같아서 변환 없이 그대로 복사하면 된다.

프론트매터 요구사항도 맞는 것을 확인했다 — description 필수, name 선택.
우리 SKILL.md 는 둘 다 갖고 있다.

- targets/antigravity.ts 추가, 설치 대상 5 → 6종
- 하위호환 경로(.agent/skills, 단수)는 감지에만 쓰고 설치는 복수형에만 한다.
  두 곳에 깔면 스킬이 두 번 잡힌다
- 테스트 2개 추가: 범위별 경로, 변환 없이 싣는지 (테스트 25 → 27개)
- 소개 페이지 설치 대상 목록에 반영
This commit is contained in:
Yun Chan 2026-08-21 03:16:53 +09:00
parent 4e1e5f0073
commit e4ac43f0b3
8 changed files with 96 additions and 6 deletions

View file

@ -161,3 +161,29 @@ test("windsurf: 12,000자 상한을 넘으면 설치를 막는다", async () =>
assert.ok(plan.blocked, "상한 초과인데 막지 않았다");
assert.match(plan.blocked, /상한/);
});
test("antigravity: 프로젝트는 .agents/skills, 전역은 ~/.gemini/config/skills", async () => {
// 두 경로가 다른 제품 규약이라 하나만 맞으면 다른 쪽에서 스킬이 안 잡힌다.
const proj = await planInstall("antigravity", "project", skill, env);
assert.equal(proj.root, path.join(cwd, ".agents", "skills", "designpaca"));
const user = await planInstall("antigravity", "user", skill, env);
assert.equal(user.root, path.join(home, ".gemini", "config", "skills", "designpaca"));
});
test("antigravity: SKILL.md 를 변환 없이 그대로 싣는다", async () => {
// Claude Code 와 같은 규약이라 프론트매터도 참조 경로도 손대지 않아야 한다.
// 여기서 경로를 재작성하면 references 가 존재하지 않는 곳을 가리킨다.
const plan = await planInstall("antigravity", "project", skill, env);
const res = await applyPlan(plan, skill.version, { env });
const md = await fs.readFile(path.join(plan.root, "SKILL.md"), "utf8");
assert.match(md, /^---\n/, "프론트매터가 있어야 한다");
assert.match(md, /description:/, "Antigravity 는 description 을 필수로 요구한다");
assert.match(md, /`references\/tokens\.md`/, "참조 경로를 재작성하면 안 된다");
const ref = await fs.readFile(path.join(plan.root, "references", "tokens.md"), "utf8");
assert.match(ref, /# 토큰/);
await removeInstall(res.record, { env });
});