--- title: "Spec E — Antigravity hook 포팅 (공유 스크립트 + --antigravity 어댑터)" source_type: llm-generated status: draft confidence: medium tags: [harness, antigravity, hooks, design, automation] last_reviewed: 2026-06-08 --- # Spec E — Antigravity hook 포팅 > Spec A/B/C 의 hook 강제를 Antigravity 로 확장. 핵심: **같은 `.claude/hooks/` 스크립트(SSOT) + 얇은 `--antigravity` I/O 어댑터.** Claude/Codex 와 *구조·로직 동일*, Antigravity 프로토콜이 강제하는 출력 봉투/필드명만 분기. ## 1. 검증된 사실 (외부 리뷰 정정) 로컬 README 의 "Antigravity 는 PreToolUse 에서만 강제 가능"은 **stale/불완전**이었다. 현행 공식 문서(geminicli.com/docs/hooks/reference) 확인: | 이벤트(Gemini명) | `decision: deny`? | 에이전트 출력 텍스트 검사? | 필드 | |---|---|---|---| | BeforeTool | ✅ | — | tool_name, tool_input | | AfterTool | ✅ | tool_response | tool_input, tool_response | | **AfterAgent** | ✅ | ✅ **`prompt_response` = 에이전트 최종 텍스트** | prompt, prompt_response | → verdict/stats SubagentStop 게이트도 **AfterAgent 로 hook 강제 가능**(deny → retry, reason 이 교정 프롬프트). Antigravity 는 네이티브 이벤트(PreToolUse/PostToolUse/Stop)와 Gemini CLI 이벤트(BeforeTool/AfterTool/AfterAgent)를 둘 다 지원. ## 2. 설계 ### DD1 — 공유 스크립트 + 출력 어댑터 검사 로직(`check_markdown_write`/`validate_verdict_block`/`validate_stats_block`/`check_c2`/…)은 **한 줄도 안 바꾼다.** `--antigravity` 플래그 시 출력 봉투만 분기: - `emit_allow` → `{"decision":"allow"}` (exit 0) - `emit_block(reason)` → `{"decision":"deny","reason":reason}` (exit 0, fail-open 철학) ### DD2 — 필드/이벤트 매핑 - 에이전트 출력: `last_assistant_message`(Claude) **또는** `prompt_response`(Gemini AfterAgent). - 이벤트명: `SubagentStop`(Claude) **또는** `AfterAgent`/`Stop`(Antigravity). - tool 경로: claim_gate `target_path` 이 이미 `TargetFile/file_path/...` fallback 보유(Antigravity 호환). ### DD3 — 배선 + repoint `.agents/hooks.json` 가 repo 의 `.claude/hooks/*.py` 를 **절대경로 + `--antigravity`** 로 호출. 스크립트가 ROOT 를 `__file__` 로 잡으므로 절대경로면 ROOT=이 repo 자동. Antigravity 작업 위치를 `Documents/LLM Wiki`(예전) → `dev/llm-wiki-private`(현재)로 이전. ## 3. 아키텍처 ``` .claude/hooks/wiki_claim_gate.py ← MOD. --antigravity 출력 모드 + prompt_response/AfterAgent 매핑 .claude/hooks/wiki_structure_lint.py ← MOD. --antigravity 출력 모드 (run_pre/run_hook → (code,msg) 반환) .agents/hooks.json ← MOD. BeforeTool/AfterTool/AfterAgent (+native) 배선, 절대경로+--antigravity (global) ~/.gemini/antigravity-cli/hooks/wiki_hard_gate.py ENFORCE_PREFIX → dev repo (repoint, 별도/보완) ``` 배선(`.agents/hooks.json`): | 이벤트 (네이티브 + Gemini 둘 다) | 스크립트 | |---|---| | PreToolUse / BeforeTool | claim_gate --antigravity + structure_lint --pre --antigravity | | PostToolUse / AfterTool | structure_lint --hook --antigravity | | Stop / AfterAgent | claim_gate --antigravity (verdict/stats, prompt_response 검사) | 기존 wiki_hard_gate(리포트 품질 G1-G4) 는 보완적이라 유지. ## 4. 수용 기준 (검증 가능) 1. `claim_gate.py --antigravity` + (branch-note DEM 누락) Write 이벤트 → stdout `{"decision":"deny",...}` + exit 0. (비-antigravity: stderr + exit 2.) 2. `claim_gate.py --antigravity` + 정상 → `{"decision":"allow"}` + exit 0. 3. `claim_gate.py --antigravity` + AfterAgent 이벤트(`prompt_response` 에 malformed verdict 블록) → `{"decision":"deny"}`. 4. `structure_lint.py --pre --antigravity` + ghost 링크 → `{"decision":"deny",...}` + exit 0. 5. `.agents/hooks.json` valid JSON + 3 이벤트 + 절대경로 + `--antigravity` 포함. 6. 기존 4 스위트 + 신규 antigravity 모드 테스트 green. (Claude/Codex exit-code 경로 회귀 없음.) ## 5. 실측 미지수 (Antigravity 세션에서 사용자 확인) - Antigravity 가 실제 fire 하는 이벤트 이름(네이티브 vs Gemini) — 그래서 **둘 다 배선**. - `AfterAgent` 가 **서브에이전트별** fire 하는가(judge 검증에 필요) vs 메인만 — 미확인. 안 되면 verdict/stats 는 in-prompt G3(이미 완료)가 대체. - `.gemini/settings.json`(nested 호환) 도 필요한지 — 우선 `.agents/hooks.json` 만, 필요시 추가. - Antigravity 작업 디렉터리 repoint 방법(사용자 환경 설정). ## 6. 구현 순서 1. claim_gate `--antigravity` 출력 모드 + prompt_response/AfterAgent 매핑 (TDD subprocess). 2. structure_lint `--antigravity` 출력 모드 (run_pre/run_hook → (code,msg)) (TDD). 3. `.agents/hooks.json` 배선. 4. (별도) wiki_hard_gate ENFORCE_PREFIX repoint. 5. 전체 스위트 + §4 스모크 + §5 미지수 사용자 인계 문서화. ## 7. 메모 - Codex 가 "공짜"였던 건 exit-code 규약이 Claude 와 같아서. Antigravity 는 `{decision}` JSON 이라 어댑터 한 겹 필요 — *다른 설계가 아니라 같은 SSOT + 최소 직렬화 분기*. - 이로써 hook 레벨 강제 + in-prompt G3 이중 안전망. wiki_hard_gate(1500줄 별도)와의 drift 도 점진 흡수 여지.