Files
gravity_control/docs/devlog/entries/20260308-018.md

5.2 KiB

승인 감지 최적화 + GB Observer 동작 확인

  • 시간: 2026-03-08 19:53~20:15
  • Commit: 810fbcc
  • Vikunja: #262 → done, #263 → 신규 생성

접근 과정과 실패 사례 (오늘 하루 전체 여정)

시도 1: 외부 <script src> 참조 → 실패

  • 접근: SDK patcher가 workbench.html<script src="./ag-sdk-variet-gravity-bridge.js"> 삽입
  • 실패: vscode-file:// 프로토콜이 원본 번들에 없는 커스텀 .js 파일을 서빙하지 않음 (silent 404)
  • 교훈: Electron의 vscode-file://product.json checksums에 등록된 파일만 서빙하며, 새 파일 추가는 불가

시도 2: 인라인 <script> + product.json 체크섬 업데이트 → 부분 실패

  • 접근: HTML에 직접 <script>코드</script> 삽입 + SHA256 체크섬 갱신
  • 실패: Reload Window 후에도 원본 HTML이 서빙됨
  • 원인: Electron 메인 프로세스가 시작 시 product.json 체크섬을 메모리에 캐시. Reload Window는 렌더러만 재시작하므로 캐시된 구 체크섬 사용
  • 교훈: 체크섬 변경 시 반드시 Antigravity 완전 종료 → 재시작 필요

시도 3: Antigravity 풀 재시작 → 성공

  • 발견: GB Observer 로그 정상 출력 (Bridge connected on port 34332)
  • 발견: Allow Once / Allow This Conversation 버튼 즉시 감지 + pending 생성 정상

시도 4: Run 버튼 감지 확인 → 실패 → 원인 발견

  • 접근: 렌더러 스크립트 패턴 {re:/^Run$/i} 가 Match할 것으로 기대
  • 실패: Run 버튼이 전혀 감지되지 않음
  • 원인 분석:
    • Allow/Trust 버튼 → 워크벤치 외부 DOM에 렌더링 → document.querySelector()로 접근 가능
    • Run/Accept 버튼 → Antigravity 채팅 webview iframe 내부에 별도 DOM으로 렌더링 → 외부 document에서 접근 불가
    • findPanel() 셀렉터 (.antigravity-agent-side-panel 등)가 매치하는 것은 iframe 컨테이너이지, 내부 DOM이 아님
  • 교훈: Electron webview iframe은 별도 browsing context. DOM Observer는 외부 DOM 전용

시도 5: webview iframe 스크립트 주입 검토 → ⏸️ 보류

  • 접근: webview.executeJavaScript() 또는 Electron preload 스크립트로 iframe 내부에 Observer 주입
  • 결정: 복잡도 높고, Extension Host에서 webview 참조를 얻는 공식 API 없음
  • 대안: RPC 기반 접근이 훨씬 안정적 → 시도 6으로 전환

시도 6: latestToolCallStep RPC 기반 즉시 감지 → 구현

  • 발견: GetAllCascadeTrajectories 응답에 latestToolCallStep 필드가 이미 존재하나 전혀 활용되지 않고 있었음
  • 발견: SDK에 StepStatus.WaitingForUser = "waiting_for_user" enum이 존재
  • 구현: poll loop에서 latestToolCallStep.step의 status 필드 확인 → WAITING 시 즉시 pending 생성
  • 개선: 30초 stall detection → 5초 poll 1회 즉시 감지

시도 7: Accept all/Reject all 리뷰 바 → 구현

  • 발견: 유저가 "대화창 바로 위의 Accept all 리뷰 바"를 지적
  • 원인: scan() 함수가 findPanel() 반환값 내부만 검색 → 리뷰 바는 에디터/notification 영역에 렌더링되어 패널 밖
  • 구현: scan() 검색 범위를 panel → document.body 전체로 확장, Accept all/Reject all 패턴 추가

핵심 아키텍처 발견

Antigravity Workbench DOM (우리 스크립트가 실행되는 곳)
├── .antigravity-agent-side-panel (findPanel이 찾는 컨테이너)
│   └── <webview> iframe ← Run/Accept 버튼 (접근 불가)
├── Trust/Permission 다이얼로그 ← Allow Once 등 (접근 가능 ✅)
└── Diff Review 바 ← Accept all/Reject all (body 스캔으로 접근 가능 ✅)

Extension Host (Node.js)
└── RPC: GetAllCascadeTrajectories
    ├── latestNotifyUserStep (기존 활용 중)
    ├── latestTaskBoundaryStep (기존 활용 중)
    └── latestToolCallStep ← status=WAITING 즉시 감지 (NEW ✅)

Extension 재설치 안전성

setupApprovalObserver() 함수가 자동 수행하는 항목:

  1. workbench.html + workbench-jetski-agent.html → 인라인 <script> 삽입
  2. product.json → SHA256 체크섬 자동 갱신
  3. HTTP bridge 서버 → 결정론적 포트로 시작

결론: Extension VSIX만 설치하면 수동 패치 불필요. 단, 패치 적용을 위해 AG 풀 재시작 필수.

코드 변경

  • extension.ts: latestToolCallStep 즉시 감지, DOM scan 범위 확장, stall→100초 fallback
  • .agents/workflows/start.md: services.md 로딩 + Python 전체 경로
  • .agents/workflows/services.md: Python 전체 경로
  • .agents/references/known-issues.md: 5건 신규 추가

미완료 (#263)

  • latestToolCallStep protobuf 구조 확정 — 첫 실행 시 [TOOL-STEP] 덤프 로그로 status 필드 위치 확인 필요
  • Accept all 리뷰 바 실제 감지 테스트 — body 스캔 후 올바르게 잡히는지 검증
  • 다음 세션: AG 재시작 → tool call 발생 → DevTools 콘솔에서 [TOOL-STEP] 로그 확인 → 필요 시 필드 매핑 수정