Files
gravity_control/.agents/references/known-issues.md

53 KiB

Known Issues & Lessons Learned

이 파일은 SSOT(Single Source of Truth)입니다. 디버깅이나 구현 전에 반드시 이 파일을 확인하세요. 세션 종료 시 새로 발견된 이슈를 이 파일에 추가합니다.


포맷

각 항목은 아래 형식을 따릅니다:

### [날짜] [키워드] — 한줄 요약
- **증상**: 무엇이 잘못되었는가
- **원인**: 근본 원인
- **해결**: 올바른 해결 방법
- **주의**: 재발 방지를 위한 교훈

공통 이슈

[2026-03-08] PowerShell curl — Invoke-WebRequest 충돌

  • 증상: curl 명령이 예상과 다른 응답 형식을 반환
  • 원인: PowerShell에서 curlInvoke-WebRequest의 별칭
  • 해결: **curl.exe**를 명시적으로 사용
  • 주의: HTTP 관련 모든 명령에서 curl.exe 사용 필수

[2026-03-08] PowerShell npm — 실행 정책 오류

  • 증상: npm run 명령이 실행 정책 관련 오류로 실패
  • 원인: PowerShell 스크립트 실행 정책이 제한적으로 설정됨
  • 해결: cmd /c npm run dev 형식으로 cmd를 통해 실행
  • 주의: npm 관련 명령은 항상 cmd /c 접두어 사용 권장

프로젝트별 이슈

아래에 프로젝트 특화 이슈를 추가하세요.

[2026-03-08] Antigravity Renderer Injection — Electron 캐시 차단

  • 증상: workbench.html, workbench-jetski-agent.html에 <script> 태그 추가 후 리로드해도 실행되지 않음
  • 원인: Electron의 V8 코드 캐시가 수정된 HTML을 무시하고 캐시된 버전을 서빙
  • 해결: 렌더러 인젝션 방식 포기. Extension Host에서 RPC 폴링 방식으로 전환
  • 주의: Antigravity는 workbench-jetski-agent.html을 사용 (Jetski = 내부 코드네임)

[2026-03-08] Antigravity 승인 대기 = RUNNING (NOT IDLE)

  • 증상: IDLE 기반 승인 감지가 실제 승인 대기를 놓침
  • 원인: 승인 대기 시 세션 상태가 CASCADE_RUN_STATUS_RUNNING (IDLE 아님), IDLE은 대화 대기(notify_user 후)
  • 해결: RUNNING + delta=0 (stall) 기반 감지로 전환. 6 polls (30초) 이상 FROZEN 시 pending 생성
  • 주의: Thinking/생성 중에도 RUNNING + delta=0이 발생 → lastModifiedTime으로 구분 시도했으나 불완전

[2026-03-08] ResolveOutstandingSteps RPC — 승인이 아닌 취소!

  • 증상: Discord 승인 → ResolveOutstandingSteps 호출 → step이 취소됨
  • 원인: ResolveOutstandingSteps는 blocking steps를 "resolve" = REJECT/CANCEL, approve가 아님
  • 해결: ResolveOutstandingSteps 제거. HandleCascadeUserInteractionsocket hang up
  • 주의: KI에 "more reliable"로 기록되어 있으나 실제 동작은 cancel임. KI 업데이트 필요

[2026-03-08] VS Code Accept Commands — Silent Success 문제

  • 증상: 4개 accept command 모두 OK(undefined) 반환하나 실제 승인 안 됨
  • 원인: webview에 활성 포커스가 필요. panel.focus()로는 충분하지 않음
  • 해결: 미해결. Windows UI Automation 등 OS 레벨 접근 필요
  • 주의: reject commands는 동작함. accept만 focus 의존성 있음

[2026-03-08] Multi-Window 세션 등록 경쟁 조건

  • 증상: 이 창(gravity_control)의 대화가 #ag-variet_agent 채널로 메시지 전달
  • 원인: writeRegistration()이 폴링 루프에서 호출 → 먼저 폴링한 확장이 세션을 자기 프로젝트로 등록
  • 해결: writeRegistration을 폴링에서 제거, writeChatSnapshot/writePendingApproval에서만 지연 호출
  • 주의: GetAllCascadeTrajectories는 모든 창의 세션을 반환하므로 세션→창 매핑은 불가능. 활동 기반 등록만 신뢰 가능

[2026-03-08] 공유 렌더러 스크립트 파일 덮어쓰기 문제

  • 증상: DOM Observer 렌더러 스크립트가 잘못된 HTTP bridge 포트에 연결
  • 원인: 두 확장이 동일한 ag-sdk-variet-gravity-bridge.js 파일에 각자 포트를 씀 → 마지막 확장 것만 남음
  • 해결: ag-bridge-ports.json에 모든 확장의 port를 JSON으로 기록, 렌더러가 all ports를 순회하며 ping
  • 주의: 렌더러 스크립트 파일 경로는 SDK patcher namespace에 의해 고정 — 변경 불가

[2026-03-08] workbench.html vs workbench-jetski-agent.html

  • 증상: 렌더러에서 [GB Observer] 로그가 전혀 안 나옴
  • 원인: DevTools가 workbench.html을 로드 — 스크립트 태그는 workbench-jetski-agent.html에만 패치됨
  • 해결: workbench.html에도 스크립트 태그 필요. Antigravity 재설치 후 SDK patcher가 올바르게 패치하도록 함
  • 주의: SDK patcher는 both HTML 파일을 패치하지만, 수동 수정은 Antigravity integrity check에 의해 되돌려질 수 있음

[2026-03-08] product.json 체크섬 불일치 → 렌더러 스크립트 미로딩

  • 증상: <script> 태그가 HTML에 존재하고 .js 파일도 디스크에 있으나, 렌더러 콘솔에 스크립트 로그가 전혀 없음
  • 원인: Antigravity 재설치 시 product.json의 SHA256 체크섬이 원본으로 리셋됨. Extension이 HTML을 패치하지만 IntegrityManager.suppressCheck()를 호출하지 않아 체크섬 불일치. vscode-file:// 프로토콜이 체크섬 불일치 파일을 무시하고 원본 캐시 HTML을 서빙
  • 해결: product.jsonchecksums 항목에서 수정된 파일(workbench.html, workbench-jetski-agent.html)의 SHA256 해시를 실제 파일 기준으로 업데이트. SDK IntegrityManager.suppressCheck() 호출 또는 수동 스크립트로 해결
  • 주의: Extension setupApprovalObserver()suppressCheck() 호출을 영구 추가해야 재설치마다 반복 안 됨. 해시 = base64(sha256(file)).replace(/=+$/, '')

[2026-03-08] vscode-file:// 프로토콜 — 커스텀 .js 파일 서빙 불가

  • 증상: <script src="./ag-sdk-variet-gravity-bridge.js"> 태그가 HTML에 있으나 net::ERR_FILE_NOT_FOUND 발생, GB Observer 로그 전혀 없음
  • 원인: vscode-file:// 프로토콜은 원본 배포에 포함된 파일만 서빙. Extension이 디스크에 쓴 커스텀 .js 파일은 프로토콜 레벨에서 차단됨
  • 해결: 외부 <script src> 참조 대신 인라인 <script>...코드...</script> 방식으로 HTML에 직접 삽입
  • 주의: ag-bridge-ports.json도 같은 이유로 XHR 로딩 불가. 모든 렌더러 스크립트/데이터는 HTML 인라인으로 전달해야 함

[2026-03-08] Renderer 포트 디스커버리 — ag-bridge-ports.json XHR 실패

  • 증상: [GB Observer] Port discovery timeout after 2min — 렌더러가 bridge 포트를 찾지 못함
  • 원인: 렌더러 스크립트가 ./ag-bridge-ports.json을 동기 XHR로 읽으려 하나, vscode-file:// 프로토콜이 .json 파일 서빙 거부
  • 해결: (1) 프로젝트명 해시 기반 결정론적 포트 사용 (gravity_control→34332), (2) 스크립트 생성 시 포트를 HARDCODED_PORT=${port}로 직접 삽입
  • 주의: server.listen(0) 랜덤 포트 → 매 재시작마다 변경되어 렌더러와 불일치. 결정론적 포트는 EADDRINUSE 시 랜덤 폴백 필요

[2026-03-08] Extension 컴파일 경로 != 설치 경로

  • 증상: npm run compile 후 Extension 동작이 변하지 않음
  • 원인: npm run compileextension/out/extension.js에만 빌드. Antigravity는 ~/.antigravity/extensions/variet.gravity-bridge-X.X.X/out/extension.js에서 로드
  • 해결: 컴파일 후 반드시 설치 경로로 수동 복사하거나, vsce package → VSIX 재설치
  • 주의: extension/out/ ≠ 실행 경로. 항상 설치 경로 확인 필요

[2026-03-08] Electron 메인 프로세스 체크섬 캐시 — Reload Window 불충분

  • 증상: product.json 체크섬 업데이트 + HTML 패치 후 Reload Window → 패치 미적용
  • 원인: Electron 메인 프로세스가 시작 시 product.json 체크섬을 메모리에 캐시. Reload Window는 렌더러만 재시작하므로 캐시된 구 체크섬 사용
  • 해결: Antigravity를 완전 종료 후 재시작 필요 (File → Exit 후 재실행)
  • 주의: Reload Window ≠ 앱 재시작. 체크섬 변경 시 항상 풀 재시작 필요

[2026-03-08] Renderer 동기 XHR — Electron 보안 정책 차단

  • 증상: tryPing() 함수가 동기 XMLHttpRequest로 HTTP bridge에 연결 시도 → 타임아웃
  • 원인: Electron 렌더러 프로세스에서 동기 XHR이 보안 정책에 의해 차단됨
  • 해결: fetch() + AbortSignal.timeout(2000) 비동기 방식으로 교체 (tryPingAsync)
  • 주의: async/await 사용 불가 (ES5 환경). .then() 체이닝으로 구현

[2026-03-08] DOM Observer — Run 버튼 감지 불가 (webview iframe 격리)

  • 증상: Allow Once/Allow This Conversation는 감지되나 Run/Accept 버튼은 감지 안 됨
  • 원인: Trust/permission 버튼은 워크벤치 외부 DOM에 렌더링, Run/Accept는 Antigravity 채팅 webview iframe 내부의 별도 DOM에 렌더링. 렌더러 스크립트의 document.querySelector()는 iframe 내부 접근 불가
  • 해결: Run 버튼은 DOM Observer가 아닌 latestToolCallStep RPC 기반 즉시 감지로 대체
  • 주의: webview iframe에 스크립트 주입은 Electron executeJavaScript()로 가능하나, 현재 RPC 방식이 더 안정적

[2026-03-08] Accept all/Reject all 리뷰 바 — agent 패널 밖 DOM

  • 증상: 코드 변경 리뷰 바(Accept all/Reject all)가 DOM Observer에 감지 안 됨
  • 원인: scan() 함수가 findPanel() (.antigravity-agent-side-panel 등) 내부만 검색. 리뷰 바는 에디터/notification 영역에 렌더링되어 패널 밖에 있음
  • 해결: scan() 검색 범위를 document.body 전체로 확장, Accept all / Reject all 패턴 추가
  • 주의: 패널+body 이중 검색 시 dedupe 필요 (같은 버튼이 두 번 잡힐 수 있음)

[2026-03-08] GetCascadeTrajectorySteps — cascadeId 파라미터 발견

  • 증상: GetCascadeTrajectoryStepstrajectoryId 파라미터 → 500 "trajectory not found"
  • 원인: 파라미터명이 trajectoryId가 아니라 cascadeId. 값은 GetAllCascadeTrajectories.trajectorySummaries의 맵 키(세션 ID)
  • 해결: { cascadeId: sessionId }로 호출 → 전체 step 배열 반환 성공
  • 주의: latestToolCallStep 필드는 GetAllCascadeTrajectories 응답에 존재하지 않음 (KI 오류)

[2026-03-08] Step 구조 — CORTEX_STEP_STATUS_WAITING 즉시 감지

  • 증상: stall-based 감지(100초)가 너무 느림
  • 원인: 이제 GetCascadeTrajectorySteps로 최신 step의 status를 직접 확인 가능
  • 해결: stall 5초 후 step probe → CORTEX_STEP_STATUS_WAITING 확인 → 즉시 pending 생성
  • Step 구조: {type: "CORTEX_STEP_TYPE_RUN_COMMAND", status: "CORTEX_STEP_STATUS_WAITING", metadata: {toolCall: {name, argumentsJson}}, runCommand, requestedInteraction}
  • 주의: 775-step 하드 리밋은 여전히 존재. 긴 세션에서는 fallback(40초) 사용

[2026-03-08] Extension 재설치 안전성 — 자동 패치 메커니즘

  • 증상: Antigravity 삭제 후 재설치 시 렌더러 스크립트가 동작 안 함
  • 원인: 재설치 시 HTML/product.json이 원본으로 리셋됨
  • 해결: Extension의 setupApprovalObserver()자동으로 모든 패치를 수행:
    1. workbench.html + workbench-jetski-agent.html 인라인 스크립트 삽입
    2. product.json SHA256 체크섬 자동 업데이트
    3. HTTP bridge 서버 시작 + 결정론적 포트
  • 주의: 패치 후 반드시 Antigravity 풀 재시작 필요 (Reload Window 불가). Extension VSIX만 설치하면 수동 패치 불필요

[2026-03-08] Response 파일 Race Condition — DOM Observer 승인 실패

  • 증상: Discord에서 승인 → [RESPONSE] renderer-handled approval 로그 출력 → 실제 버튼 클릭 안 됨
  • 원인: processResponseFile (파일 감시자)이 response 파일을 즉시 삭제 → renderer의 pollResponse가 HTTP GET /response/:rid로 조회 시 파일 이미 없음
  • 해결: DOM observer 소스일 때는 response 파일을 삭제하지 않도록 수정. HTTP endpoint가 renderer에게 서빙한 후 삭제
  • 주의: non-DOM (stall/step_probe relay)는 watcher에서 삭제해도 됨

[2026-03-08] Renderer 스크립트 소스 혼동 — 3곳의 코드

  • 증상: extension.ts에 BTN-DUMP 추가 → Reload 2번 → 콘솔에 안 나옴
  • 원인: renderer 코드가 3곳에 존재: (1) extension.tsgenerateApprovalObserverScript() (소스), (2) ag-sdk-variet-gravity-bridge.js (배포됨, Reload시 소스에서 재생성), (3) workbench-jetski-agent.html inline (HTML, JS파일과 중복로드 방지됨). 직접 JS파일 패치는 Reload시 소스에서 재생성되어 덮어씌워짐
  • 해결: 항상 extension.tsgenerateApprovalObserverScript() 함수를 수정 → 컴파일 → 배포 → Reload
  • 주의: HTML inline은 JS파일이 먼저 로드되어 window.__agSDK 가드에 의해 실행 안 됨. 실제 실행되는 것은 JS파일 경로의 스크립트

[2026-03-09] VS Code Accept — SDK 승인 명령이 AG에 미등록

  • 증상: Discord 승인 → antigravity.terminalCommand.run 등 7개 명령 → 모두 command not found
  • 원인: SDK(command-bridge.ts)에 정의된 7개 승인 명령이 현재 AG 빌드에 등록되어 있지 않음. 활성 시 72개, 세션 중 119개로 동적 등록되지만 승인 관련 명령은 없음
  • 검증:
    • HandleCascadeUserInteraction RPC 3 variants → 모두 socket hang up
    • ResolveOutstandingStepsrun state not found (500 에러, 실제로는 CANCEL 동작)
    • sendChatActionMessage, executeCascadeAction → 119개 명령 중 미등록
    • 존재하는 approval-like 명령: agentAcceptAllInFile (코드 diff), agentAcceptFocusedHunk (hunk), acceptCompletion (자동완성) — 터미널 승인과 무관
  • 해결: Renderer DOM Click 구현됨 (미검증)v1 검증 실패: webview iframe 격리 확인. v3 deepFindButtons()로 업그레이드 (iframe contentDocument + webview.executeJavaScript + shadow DOM). AG 완전 재시작 후 DOM-DUMP로 접근 가능 여부 확인 필요
  • 주의: agentPanel.focus도 미등록, agentSidePanel.focus만 존재

[2026-03-09] Renderer DOM — webview iframe 격리 확인 + v3 deep traversal

  • 증상: Renderer trigger-click이 document.querySelectorAll('button')으로 버튼 검색 → Run 버튼 미발견. 감지된 것은 외부 DOM의 trust-level 버튼(RunAlt+?)뿐
  • 원인: Run/Accept 버튼은 AG 채팅 webview iframe (vscode-webview:// origin) 안에 렌더링. 외부 workbench DOM (vscode-file:// origin)에서 cross-origin으로 접근 불가
  • 해결: Renderer v3 deepFindButtons() 구현:
    1. Main document 검색 (기존)
    2. iframe.contentDocument 접근 시도 (same-origin이면 성공)
    3. <webview>.executeJavaScript() 접근 시도 (Electron API)
    4. Shadow DOM 재귀 탐색 → 미검증 (AG 재시작 후 DOM-DUMP 결과 필요)
  • 주의: CDP(Chrome DevTools Protocol)는 사용자 결정에 의해 명시적으로 거부됨 (--remote-debugging-port 필요, 비표준 접근). 표준 DOM API/Electron API 범위 내에서만 해결할 것

[2026-03-09] Deep Inspect HTTP Endpoint — curl로 DOM 분석 트리거

  • 증상: AG DevTools 콘솔에 붙여넣기 불가 (Chromium 보안 정책)
  • 원인: Electron 렌더러 DevTools에서 allow pasting이 SyntaxError 발생 (Unexpected identifier 'pasting')
  • 해결: Extension HTTP bridge에 /deep-inspect 엔드포인트 추가. curl.exe http://127.0.0.1:34332/deep-inspect로 bridge→renderer→재귀 DOM 분석→결과 JSON 반환. 결과는 ~/.gemini/antigravity/bridge/deep-inspect-result.json에도 저장됨
  • 주의: 시작 3초 후 자동 실행 + curl로 재트리거 가능. renderer가 2초마다 /deep-inspect-trigger 폴링

[2026-03-09] workbench.html inline 스크립트 미삽입 — jetski만 패치한 버그

  • 증상: AG 재시작 후 /deep-inspect timeout — renderer v3 스크립트 미로딩
  • 원인: setupApprovalObserver()workbench-jetski-agent.html에만 inline 삽입하고, workbench.html에는 외부 <script src>만 추가. vscode-file:// 프로토콜은 커스텀 .js 파일을 서빙하지 않으므로 사실상 미로딩
  • 해결: HTML 패치 로직을 htmlFiles = ['workbench.html', 'workbench-jetski-agent.html'] 루프로 변경하여 양쪽 모두 inline 삽입. 수동 pre-patch 스크립트(/tmp/patch_workbench.py)로 즉시 적용 + product.json 체크섬 업데이트
  • 주의: 항상 양쪽 HTML을 동일하게 패치. AG가 어느 HTML을 로드할지 런타임까지 알 수 없음. pre-patch 후 1회 풀 재시작이면 충분 (체크섬 사전 업데이트 완료)

[2026-03-09] V8 CachedData — 체크섬 정상이어도 스크립트 미실행

  • 증상: HTML 패치 + product.json 체크섬 일치 + Bridge 서버 정상 → 그런데도 renderer 스크립트 미실행 (/deep-inspect timeout)
  • 원인: AG 프로세스 인자 --code-cache-schemes=vscode-webview,vscode-file에 의해 V8 바이트코드 캐시가 vscode-file:// 프로토콜에도 적용. product.json 체크섬 검증과 V8 코드 캐시는 별도 메커니즘 — 체크섬이 맞아도 V8은 %APPDATA%\Antigravity\CachedData의 이전 컴파일된 바이트코드를 재사용
  • 해결: %APPDATA%\Antigravity\CachedData\* 전체 삭제 후 AG 풀 재시작. AG 실행 중에도 삭제 가능 (파일 잠금 없음 확인됨)
  • 주의: CachedData 삭제 후 첫 시작이 약간 느릴 수 있음 (V8이 모든 JS를 재컴파일). HTML 패치 변경 시마다 CachedData 삭제 필수. product.json 체크섬 업데이트만으로는 불충분

승인 전략 결정 체인 (다음 세션 필독)

이 섹션은 2026-03-08~09 전체 세션의 시행착오를 요약합니다. 다음 세션은 이미 거부된 접근을 다시 시도하지 마세요.

시도 후 거부된 접근 (재시도 금지)

# 접근 결과 거부 사유
1 LS RPC HandleCascadeUserInteraction socket hang up AG 빌드에서 핸들러 미구현
2 LS RPC ResolveOutstandingSteps CANCEL 동작 (승인이 아님) 명칭과 달리 step을 취소함
3 VS Code 7개 승인 명령 (terminalCommand.run 등) command not found AG 런타임에 미등록
4 키보드 시뮬레이션 (type {Enter}) 빈 메시지 전송 Chat input에 캡처됨
5 sendChatActionMessage / executeCascadeAction 미등록 119개 명령에 없음
6 pywinauto (OS 레벨) 사용자 결정 폐기 크로스플랫폼 불가, 창 겹침 문제
7 CDP (Chrome DevTools Protocol) 사용자 명시적 거부 비표준, --remote-debugging-port 필요
8 Renderer v1 DOM Click (flat scan) Run 버튼 미발견 webview iframe 격리

현재 진행 중인 접근

# 접근 상태 다음 단계
1 Renderer v3 Deep DOM Traversal 패치+체크섬 OK, V8 CachedData 삭제 완료, AG 재시작 후 검증 AG 재시작 → curl.exe http://127.0.0.1:34332/deep-inspect
2 <webview>.executeJavaScript() v3에 포함, 미검증 위 결과에서 hasExecJS=true이면 유력
3 TerminalExecutionPolicy.EAGER (Turbo) 미시도, 최후 수단 통제권 포기이므로 사용자 승인 필요

🔑 핵심 전제

  • Run/Accept 버튼은 vscode-webview:// origin의 격리된 iframe 안에 있음
  • 외부 workbench DOM에서 querySelector로 접근 불가 (cross-origin)
  • <webview>.executeJavaScript()유일한 표준 관통 경로 (Electron API)
  • AG 패치 후 반드시 풀 프로세스 재시작 필요 (Reload Window 불충분)
  • 양쪽 HTML (workbench.html + workbench-jetski-agent.html) 모두 inline 패치 필수
  • HTML 패치 변경 시 %APPDATA%\Antigravity\CachedData 삭제 필수 (V8 바이트코드 캐시 무효화)
  • CSP script-src'unsafe-inline' 패치 필수 (없으면 인라인 스크립트 무조건 차단)

[2026-03-09] CSP script-src — 인라인 스크립트 무조건 차단

  • 증상: HTML 패치 , 체크섬 , CachedData 삭제 — 그런데도 renderer v3 스크립트 미실행 (/deep-inspect timeout)
  • 원인: workbench.html의 CSP <meta http-equiv="Content-Security-Policy">에서 script-src 'self' 'unsafe-eval' blob:'unsafe-inline' 없음. 브라우저가 인라인 <script> 태그를 무조건 차단
  • 해결: CSP의 script-src'unsafe-inline' 추가. Extension setupApprovalObserver()에 CSP 자동 패치 로직 영구 추가
  • 주의: style-src에는 'unsafe-inline'이 있어 스타일은 동작 → 스크립트만 차단되는 것이 함정. connect-srchttp://127.0.0.1:* 존재하여 HTTP fetch는 허용됨 (CSP 통과 시 통신은 문제없음). 이 CSP 이슈는 V8 CachedData 이슈와 동시에 존재하여 진단이 매우 어려웠음

[2026-03-09] 중복 승인 요청 — DOM scan + Step probe 동시 발동

  • 증상: Discord에 같은 명령에 대해 승인 요청이 2개 도착
  • 원인: DOM Observer가 RunAlt+↵ 버튼을 감지하여 pending 생성 + Step probe가 CORTEX_STEP_STATUS_WAITING 감지하여 pending 생성 → 동일 step에 대해 2개 파일
  • 해결: writePendingApproval()에 15초 dedup 윈도우 추가 — 최근 DOM observer pending이 있으면 step probe pending 스킵
  • 주의: DOM scan은 제거 불가 — Allow Once, Allow This Conversation 등 step probe가 감지 못하는 UI 버튼 존재. 버튼 텍스트도 (Alt|Ctrl|Shift|Meta)\+.* 정규식으로 키보드 단축키 정제

[2026-03-09] Step probe reject → ResolveOutstandingSteps가 AI 작업 취소

  • 증상: Discord에서 거부 클릭 → AI의 현재 step뿐 아니라 진행 중인 작업 전체가 중단
  • 원인: step probe 경로의 tryApprovalStrategies(approved=false)ResolveOutstandingSteps RPC 호출 → 이것은 step을 CANCEL하는 파괴적 동작
  • 해결: step probe 경로에서 reject 시 tryApprovalStrategies 호출 제거. reject은 로그만 남기고 파기적 동작 없음. DOM observer 경로만 실제 Reject 버튼 클릭 허용
  • 주의: ResolveOutstandingSteps는 이름과 달리 "해결"이 아닌 "취소". 승인에 절대 사용 금지 (이전 이슈 #55~59 참조)

[2026-03-09] Pending 파일 무한 누적 — write_response 후 미삭제

  • 증상: bridge/pending/ 디렉토리에 79개 이상의 .json 파일이 쌓여 봇 시작 시 폭주
  • 원인: write_response()가 pending 파일 status만 변경하고 삭제하지 않음. get_pending_requests()에 age filter 없음
  • 해결: (1) write_response()에서 pending 파일 삭제, (2) get_pending_requests()에 5분 age filter, (3) 시작 시 _cleanup_stale_pending() 호출
  • 주의: 봇 재시작 시 자동 정리. age filter는 expired 마킹 후 skip

[2026-03-09] Discord 승인 "Run" 표시 — DOM/step_probe 타이밍 불일치

  • 증상: Discord에 상세 명령어 대신 "Run"만 표시
  • 원인: DOM observer가 "Run" pending 생성(t=0) → 봇이 3초 후 전송 → step_probe MERGE가 10초 후 완료 → 이미 전송 후
  • 해결: (1) step_probe가 기존 DOM pending에 MERGE (skip 대신 update), (2) 봇에서 짧은 명령어(≤15자) 4 cycles(12s) 대기, 매 cycle re-read하여 merge 즉시 전송
  • 주의: MERGE 타이밍은 step_probe poll interval(5s) + stall detection 필요하므로 최소 10초. defer는 이보다 길어야 함

[2026-03-09] DOM observer false positive — Proceed/Continue/Open 버튼 오감지

  • 증상: 작업 전환 시(notify_user, task_boundary) 승인 요청 없는데도 Discord에 승인 요청 도착
  • 원인: DOM observer가 AG UI의 PathsToReview "Proceed"/"Open" 버튼, 파일 Open 버튼 등을 승인 버튼으로 오인
  • 해결: (1) HTTP POST /pending 핸들러에 false positive 필터 추가 (Proceed/Continue/Open/Close/OK 등), (2) "Run" 버튼은 sessionStalled=true일 때만 허용
  • 주의: renderer 인라인 스크립트(HTML)는 extension.js 배포로 안 바뀜 → 서버사이드 필터가 필수. PATS 패턴 수정은 HTML 재패치 시에만 적용

[2026-03-09] Discord ApprovalView timeout — 5분 후 버튼 무응답

  • 증상: 시간이 지난 후 Discord 승인 버튼 클릭해도 반응 없음
  • 원인: Discord.py View의 기본 timeout이 300초(5분)로 설정됨
  • 해결: timeout을 1800초(30분)로 증가
  • 주의: Discord View timeout은 서버 재시작 후만 적용. 기존 메시지의 View는 이미 만료됨

[2026-03-10] DOM Observer 승인 ENOENT — response 파일 Race Condition

  • 증상: Discord에서 승인 → extension.log에 ENOENT: response/xxx.json 에러 → AG에서 Run 미실행 (간헐적)
  • 원인: processResponseFile() (response watcher)이 response 파일을 읽고 즉시 fs.unlinkSync() → renderer pollResponse()GET /response/:rid로 조회할 때 파일 이미 없음
  • 해결: DOM observer 경로(isDomObserver)일 때 processResponseFile()에서 response 파일을 삭제하지 않고, HTTP handler(GET /response/:rid)가 renderer에 전달 후 삭제. step_probe 경로는 clickTrigger로 처리하므로 기존처럼 삭제 OK
  • 주의: DOM observer와 step_probe 두 경로가 독립적으로 pending을 생성할 수 있으므로, response 삭제 타이밍을 경로별로 구분해야 함

[2026-03-10] Allow Once + Allow This Conversation — 별개 pending으로 분리되는 문제

  • 증상: 파일 접근 시 Allow Once와 Allow This Conversation이 Discord에 2개 별도 메시지로 도착. Deny 선택지 없음
  • 원인: renderer scan()이 한 사이클에 한 버튼만 처리 후 return. 각 버튼이 별도 pending으로 전송. Deny는 PATS 패턴에 미등록
  • 해결: (1) scan()에서 findButtonContainer()+collectSiblingButtons()로 같은 컨테이너의 관련 버튼을 그룹화하여 buttons 배열로 전송, (2) bot.py ApprovalViewbuttons 배열이 있으면 clear_items() 후 동적 Discord 버튼 추가, (3) bridge.py UserResponsebutton_index 추가, (4) renderer pollResponseGroup()에서 button_index에 따라 DOM 버튼 클릭
  • 주의: buttons 배열이 없는 legacy pending은 기존 2버튼(승인/거부)으로 표시. Deny를 PATS에 추가함

[2026-03-10] step_probe verbosity — argumentsJson 미포함

  • 증상: Discord 승인 메시지에 list_dir: DirectoryPath (파라미터 이름만 표시, 값 없음)
  • 원인: GetCascadeTrajectorySteps 기본 verbosity에서 argumentsJson 필드가 빈 문자열
  • 해결: verbosity: 1 (DEBUG)을 모든 step_probe 호출에 추가 → argumentsJson 포함. 추출 로직에 DirectoryPath, SearchPath, AbsolutePath, Url, Query 등 값 우선 표시
  • 주의: verbosity 0=NORMAL (키만), 1=DEBUG (값 포함). Object.keys(args) fallback은 값 추출 실패 시에만

[2026-03-10] 파일 권한 응답 — "unexpected user interaction type: not file permission"

  • 증상: .agents 디렉토리 접근 시 "unexpected user interaction type: not file permission" 에러
  • 원인: 봇이 file_permission pending에 대해 runCommand.confirm RPC를 전송 (file_permission이 아닌 잘못된 interaction type). 또는 오래된 pending에 대해 봇이 자동 처리
  • 해결: (1) pending의 step_typefile_permission일 때 extension이 filePermission RPC 사용 (이미 구현됨), (2) DOM Observer의 file_permission 감지 → buttons 배열 + step_type: 'file_permission' 명시
  • 주의: 봇이 오래된 pending을 먼저 처리하면 타이밍 불일치 발생 가능. file_permission과 run_command가 동시에 대기 시 올바른 RPC 라우팅 필수

[2026-03-10] active_project.lock — 멀티 프로젝트 동시 사용 차단

  • 증상: 동일 PC에서 여러 AG 프로젝트 실행 시 첫 번째 프로젝트만 bridge 연결, 나머지는 경고 후 비활성화 시도
  • 원인: active_project.lock 파일이 단일 프로젝트만 bridge 사용을 허용하는 설계. 그런데 bridgeDisabled 플래그 설정 후 실제로 아무것도 차단하지 않아 → 모든 인스턴스가 같은 pending/response/commands 디렉토리를 동시에 읽고 씀
  • 해결: (1) active_project.lock 메커니즘 완전 제거, (2) step_probe auto-resolve scan에 project_name 필터 추가, (3) response watcher의 기존 project_name 필터 유지
  • 주의: bridge 격리는 project_name 필드 기반 filtering으로 충분. 파일시스템 레벨 분리(옵션 B)는 불필요하게 복잡

[2026-03-10] step_probe file_permission — 3-button 미주입

  • 증상: AG에서 파일 접근 권한 요청 시 Discord에 3개 선택지(Allow Once/Allow This Conversation/Deny) 대신 2개(승인/거부)만 표시
  • 원인: writePendingApproval()step_type: 'file_permission'을 설정하지만 buttons 배열을 주입하지 않음. DOM observer의 /pending 핸들러는 cmdLower.includes('allow') 조건에서만 buttons 주입 → step_probe의 view_file: /tmp/... 형태 command에서는 trigger 안 됨
  • 해결: writePendingApproval()에서 step_type === 'file_permission' && !buttons일 때 자동으로 3-button 배열 주입
  • 주의: DOM observer 경로는 기존 command 텍스트 기반 감지 유지. step_probe 경로만 수정

[2026-03-10] GetAllCascadeTrajectories — 크로스 윈도우 세션 가로채기

  • 증상: Deriva AG에서 대화 시작 → Discord에 신호 안 잡힘, gravity_control 채널에 Deriva 내용이 릴레이됨
  • 원인: GetAllCascadeTrajectories RPC가 모든 AG 인스턴스의 세션을 반환. 기존 register 파일 기반 필터링은 새 세션(아직 register 없음)에 대해 먼저 폴링한 인스턴스가 bestSession으로 가져감. gravity_control extension이 Deriva 세션을 자기 것으로 등록
  • 해결: trajectoryMetadata.workspaces[0].workspaceFolderAbsoluteUrivscode.workspace.workspaceFolders[0].uri.fsPath와 비교하여 자기 workspace 세션만 처리. register 파일은 metadata 없는 레거시 세션용 fallback으로 유지
  • 주의: workspace URI는 file:///c:/Users/... 형식이므로 normalize 필수 (protocol strip, %3A decode, 슬래시 통일, lowercase). 양쪽 AG 풀 재시작 필요

[2026-03-10] 크로스 프로젝트 Response Watcher 우회

  • 증상: Deriva 세션에 대한 승인 시도가 gravity_control에서 stepIndex:-1로 반복 실패
  • 원인: (1) pending 파일 삭제 후 response watcher가 project_name 체크 건너뜀, (2) processResponseFile이 전역 activeSessionId 사용
  • 해결: (1) response JSON의 project_name으로 fallback 필터, (2) 세션ID를 pending에서 우선 사용, (3) logToFile[projectName] 접두사, (4) UserResponseproject_name 추가
  • 주의: response 데이터 자체에 project_name 필수. auto_resolve로 pending 삭제 시 우회됨

[2026-03-10] file_permission — write 도구 3-button 미주입

  • 증상: replace_file_content 등 파일 수정 시 AG에선 3개 버튼(Deny/Allow Once/Allow This Conversation) 표시, Discord에선 2개(승인/거부)만 표시
  • 원인: step_probe의 file_permission 도구 리스트에 read 도구만 포함 (view_file, grep_search 등). replace_file_content, write_to_file, multi_replace_file_content 누락
  • 해결: 세 write 도구를 file_permission 리스트에 추가 (2곳: offset/normal scan)
  • 주의: AG가 파일 접근 권한을 요청하는 모든 도구는 이 리스트에 포함되어야 함

[2026-03-10] bestSession IDLE 고착 — RUNNING 세션 못 잡는 버그

  • 증상: Deriva AG에서 새 대화 시작 → bridge가 구 IDLE 세션만 추적, 새 RUNNING 세션 무시
  • 원인: bestSession 선택이 lastModifiedTime만 비교. 구 IDLE 세션의 modTime이 더 최신이면 새 RUNNING 세션보다 우선 선택됨
  • 해결: 2단계 비교 — (1) RUNNING 세션이 IDLE보다 항상 우선, (2) 동일 상태 내에서 lastModifiedTime 최신 순
  • 주의: Reload Window로도 해결되지만 근본적으로는 RUNNING 우선 로직이 필요. [SESSION-FILTER] 진단 로그도 추가됨

[2026-03-10] Bot IDLE 채널 자동 생성 — 불필요한 Discord 채널 증식

  • 증상: 봇 시작 시 IDLE 프로젝트까지 포함하여 모든 등록된 프로젝트의 채널을 자동 생성
  • 원인: pending_approval_scanner가 매 사이클마다 conv_to_project 전체를 순회하며 채널 생성
  • 해결: 자동 채널 생성 루프 제거. 채널은 실제 신호(snapshot/pending) 도착 시 _get_channel()로 on-demand 생성
  • 주의: _get_channel()은 snapshot scanner와 approval sender에서 이미 호출되므로 별도 사전 등록 불필요

[2026-03-10] Reload Window 후 세션 stale — GetAllCascadeTrajectories 미갱신

  • 증상: Reload Window 후 현재 대화의 세션이 GetAllCascadeTrajectories에 IDLE/구 stepCount로 고정. 새 메시지를 보내도 RUNNING으로 변경되지 않음
  • 원인: Reload Window 시 Extension은 리셋되지만 LS 프로세스는 유지됨. LS 내부 trajectory tracker가 Reload 이전 세션 상태를 캐시하고 갱신하지 않음
  • 해결: AG 완전 종료 → 재실행 (Full restart). Reload Window로는 해결 불가
  • 주의: Extension 코드 변경 후 배포 시 Reload Window 대신 Full restart 권장. 이건 AG LS 내부 동작이라 사용자 측에서 수정 불가

[2026-03-10] start_bot.bat — Windows Store Python 스텁 우선 실행

  • 증상: start_bot.bat 실행 시 '...' is not recognized 에러 후 Python만 출력되고 즉시 종료
  • 원인: where python이 Windows Store의 Python 스텁(AppAlias)을 먼저 찾음. 이 스텁은 실제 Python이 아니라 Store 페이지로 리다이렉트하는 더미
  • 해결: conda 경로(C:\ProgramData\miniforge3\envs\gravity_control\python.exe)를 where python보다 먼저 확인하도록 순서 변경
  • 주의: Windows 10/11에서 App Aliases의 python.exe가 PATH에 기본 포함됨. 항상 구체적 경로 우선 확인 필요

[2026-03-10] VSIX 빌드 — SDK JS 파일 미포함 (require 실패)

  • 증상: Extension 활성화 후 SDK not initialized, gravityBridge.connect 클릭 시 에러. extension.log에 SDK init 성공 로그 없음
  • 원인: src/sdk/index.js는 순수 JavaScript 파일. TypeScript 컴파일러(tsc)는 .ts만 변환하고 .js 파일을 out/에 복사하지 않음. require('./sdk/index')out/sdk/index.js를 찾지 못해 SDK 로드 실패
  • 해결: package.jsoncompile 스크립트에 tscnode -e "..." 복사 단계 추가 (src/sdk/out/sdk/)
  • 주의: VSIX 패키징은 .vscodeignore!out/** 규칙으로 out/sdk/를 포함함. 문제는 빌드 단계에서 복사 누락이므로 npm run compileout/sdk/ 존재 여부 반드시 확인

[2026-03-10] SDK _findLSProcess — 대소문자 구분 workspace hint 매칭 실패

  • 증상: variet-agent AG에서 활성 대화 진행 중인데 Discord에 신호 미도달. extension.log에 [SESSION-FILTER] NO session matched! total=11
  • 원인: SDK _findLSProcess()가 workspace hint(desktop_variet_agent, 소문자)를 LS 프로세스 command line의 Desktop_variet_agent(대문자 D)과 String.includes()(대소문자 구분)로 비교 → 매치 실패 → 첫 번째 LS(gravity_control)로 fallback → variet-agent 세션 없음. 각 AG 창은 별도의 LS 프로세스를 가지며(workspace_id로 구분), SDK가 잘못된 LS에 연결하면 해당 창의 세션을 볼 수 없음
  • 해결: extension.tsfixLSConnection() 함수 추가. SDK init 후 PowerShell로 모든 LS 프로세스를 조회, --workspace_id대소문자 무시 비교하여 올바른 LS 발견 → sdk.ls.setConnection(port, csrfToken)으로 재연결
  • 주의: 각 AG 창마다 별도 LS 프로세스 존재 확인됨 (workspace_id로 구분). SDK _getWorkspaceHint().toLowerCase() 적용하지만 검색 대상(LS command line)은 원본 대소문자를 유지하여 불일치 발생. 이 fix는 모든 multi-window AG 환경에서 필수

[2026-03-11] config.py BRAIN_PATH — .env 빈 문자열 → CWD 해석 버그

  • 증상: 봇이 Extension의 snapshot/pending을 전혀 읽지 못함. 로그에 Brain path: ., Bridge protocol initialized: bridge (상대경로)
  • 원인: .envBRAIN_PATH= (빈 값)이 있으면 os.getenv("BRAIN_PATH", default)가 빈 문자열 ""를 반환 (default 미사용). Path("")Path(".") → CWD로 해석. 봇의 bridge 디렉토리가 CWD/bridge/가 되어 Extension의 ~/.gemini/antigravity/bridge/다른 경로
  • 해결: os.getenv("BRAIN_PATH") or default 패턴으로 빈 문자열도 처리
  • 주의: os.getenv(key, default)는 key가 존재하면 (빈 값이라도) default를 사용하지 않음. 환경변수의 빈 값을 fallback 처리하려면 반드시 or 사용

[2026-03-11] Extension DEDUP MERGE — 크로스 프로젝트 pending 오염

  • 증상: #ag-lifetimepd 채널에 variet_agent의 write_to_file 승인 요청이 표시됨
  • 원인: writePendingApproval()의 DEDUP 로직이 project_name을 체크하지 않음. LifetimePD DOM observer가 "Deny" pending 생성 → 7초 후 variet_agent step_probe가 같은 pending에 MERGE → command가 덮어씌워짐. pending의 project_name: lifetimepd는 유지되어 잘못된 채널로 라우팅
  • 해결: 3곳 dedup 조건에 existing.project_name === projectName 가드 추가: (1) MERGE, (2) step_index 중복 스킵, (3) file_permission 중복 필터
  • 주의: 모든 Extension 인스턴스가 동일한 bridge/pending/ 디렉토리를 공유하므로, pending 파일 간 상호작용 시 반드시 project_name 일치 여부 확인 필수

[2026-03-11] Collector 동기 HTTP — aiohttp 전환

  • 증상: Collector가 Gateway에 동기 urllib 요청 시 이벤트 루프 전체 블로킹, 3초 폴링이 10초+로 늘어남
  • 원인: RemoteTransport._request()urllib.request.urlopen() 사용 (blocking I/O)
  • 해결: aiohttp.ClientSession 기반 비동기 전환 + 연결 모니터링 + 재시도 큐 (100건)
  • 주의: import aiohttp는 lazy (_get_session() 내부). 로컬 conda 환경에 aiohttp>=3.9.0 설치 필수

[2026-03-11] Extension fs.watch — Collector response 파일 감지 누락

  • 증상: Discord에서 거부 → Collector가 bridge/response/ 파일 정상 생성 → Extension processResponseFile 미호출 ([RESPONSE] 로그 0건)
  • 원인: setupResponseWatcher()event === 'rename'만 필터링. 파일 생성 방식에 따라 change 이벤트만 발생할 수 있음. Windows fs.watch는 빠른 write+delete 시 이벤트 누락 알려짐
  • 해결: 미해결event 필터 제거 또는 polling 전환 필요. 사이드이펙트 검증 필요하여 보류
  • 주의: 이 문제로 인해 Discord에서의 모든 거부/정지 명령이 Extension에 전달되지 않음

[2026-03-11] rejectAgentStep — AG 미등록 VS Code 커맨드

  • 증상: /stop 및 거부 시 antigravity.agent.rejectAgentStepcommand not found
  • 원인: AG IDE가 이 커맨드를 런타임에 등록하지 않음
  • 해결: 미해결 — AG가 실제 등록하는 커맨드 목록 조사 후 올바른 커맨드로 교체 필요
  • 주의: [2026-03-09] VS Code Accept Commands 이슈와 같은 근본 원인 (AG 커맨드 미등록)

[2026-03-12] RemoteTransport 429 무한 루프 — Extension 크래시 + AG 먹통

  • 증상: Collector→Gateway HTTP 요청 시 429 Rate limited 로그가 초당 수십 건 무한 반복. Extension 꺼지고 AG 재시작 시 화면 먹통
  • 원인: 3가지 복합: (1) RemoteTransport._arequest()가 429 수신 시 백오프 없이 즉시 리턴 → 3초 후 다시 전체 재시도, (2) _poll_responses_loop()가 모든 forwarded pending에 개별 HTTP 요청 → pending 쌓이면 1초에 10개 초과, (3) Gateway rate limit이 10 req/1초로 너무 공격적
  • 해결: (1) bridge.py — 지수 백오프 추가 (1s→2s→4s…60s) + Retry-After 헤더 지원 + is_rate_limited 프로퍼티, (2) gateway.py — rate limit 10→30으로 완화 + Retry-After 헤더 응답, (3) collector.py — 모든 루프에서 is_rate_limited 체크 + response 폴링에 0.2초 인터-리퀘스트 딜레이
  • 주의: AG 먹통은 봇 자체가 유발한 문제. Extension이나 AG 내부를 건드린 것이 아님. 봇을 끄고 AG를 재시작하면 정상 복구 가능

[2026-03-12] workbench.html 0-byte 파괴 — AG 새 창 먹통

  • 증상: AG 새 창 열면 화면 먹통 (빈 화면). 봇을 꺼도 복구 안 됨
  • 원인: 멀티 윈도우 환경(gravity_control + variet_agent + edf)에서 3개 Extension 인스턴스가 동시에 workbench.html을 읽고/패치/쓰기. 한 인스턴스가 writeFileSync 중에 다른 인스턴스가 readFileSync → 빈 문자열 반환 → 파이프라인 처리 후 0 bytes로 덮어쓰기
  • 해결: (1) pre-patch backup (.orig 파일) 생성, (2) 파일별 구조 검증 (requiredMarker), (3) 손상/잘못된 타입 감지 시 .orig에서 자동 복원
  • 주의: AG 풀 재시작 필수. 멀티 윈도우 환경에서 HTML 패치 race condition은 근본적으로 파일 잠금 없이는 완전 해결 불가 — 안전 가드로 피해 최소화

[2026-03-12] workbench.html 크로스 복원 — CSS 미로딩으로 레이아웃 깨짐

  • 증상: AG 재시작 후 아이콘/요소는 보이지만 전부 왼쪽으로 쏠려서 정렬 안 됨. 레이아웃 완전 깨짐
  • 원인: workbench.htmlworkbench-jetski-agent.html에서 복원할 때 JS만 교체 (jetskiAgent.jsworkbench.js)하고 CSS 참조를 교체하지 않음. 두 파일은 완전히 다른 CSS를 사용:
    • workbench.htmlworkbench.desktop.main.css (VS Code 기본 레이아웃)
    • workbench-jetski-agent.htmltw-base.tailwind.css + jetskiMain.tailwind.css (Jetski Agent 전용) 잘못된 CSS가 로드되면 JS는 정상 작동하나 레이아웃이 완전히 무너짐
  • 해결: (1) Extension에 파일별 requiredMarker 검증 추가 (workbench.html은 workbench.desktop.main.css, jetski는 jetskiMain.tailwind.css 필수), (2) 첫 패치 전 .orig 백업 자동 생성, (3) 손상 또는 잘못된 타입 감지 시 .orig에서 자동 복원. 두 HTML 파일은 절대 크로스 복원 불가
  • 주의: workbench.htmlworkbench-jetski-agent.html교환 불가능. CSS 경로, JS 엔트리 포인트, CSP 세부 설정이 모두 다름. 수동 복원 시도 금지 — Extension의 자동 복원 로직에 의존할 것

[2026-03-12] Collector 단일 프로젝트 폴링 — 멀티 프로젝트 command 전달 불가

  • 증상: Discord ag-deriva 채널에서 메시지 전송 → Deriva AG IDE에 전달되지 않음. Gateway에 command 정상 저장됨
  • 원인: collector.py _poll_commands_loop()self.project_name (= .envPROJECT_NAME, 기본 gravity_control)으로만 GET /api/commands/{project} 폴링. Gateway는 프로젝트별로 command를 저장(_commands["deriva"])하지만 Collector가 "gravity_control"만 요청 → 다른 프로젝트 명령이 30분 TTL 후 만료
  • 해결: _discover_local_projects()bridge/register/*.json에서 로컬 프로젝트 목록을 자동 발견, 모든 프로젝트에 대해 폴링. Extension은 L131에서 project_name 필터링이 있어 자기 프로젝트만 소비
  • 주의: 멀티 PC 환경에서 /api/commands/all 엔드포인트는 크로스 PC 명령 오염을 유발하므로 사용 금지. 각 Collector가 자기 PC의 register/ 기반으로 프로젝트를 발견하는 것이 올바른 설계

[2026-03-12] RemoteTransport backing off 무한 반복 — IDLE에서 더 심함

  • 증상: AG 미사용(IDLE) 시 backing off 1s 경고가 ~4초마다 영구 반복. 사용 중보다 IDLE 시 더 자주 발생
  • 원인: 3가지 구조적 결함의 복합:
    1. 백오프 즉시 리셋: _reset_backoff()가 성공 1회에 _backoff_seconds=0 → 7개 루프가 같은 transport 공유 → 첫 성공에 리셋 → 지수 백오프가 영원히 1s에서 멈춤
    2. IDLE 시 불필요한 요청: 6개 프로젝트 command 폴링이 3초마다 빈 응답 반복
    3. asyncio burst: 7개 루프가 같은 asyncio.sleep(3) → 같은 tick에 동시 깨어남 → 순간 burst로 Gateway 1초 윈도우(30 req) 초과
  • 해결: (1) _on_request_success() — 연속 5회 성공 후에만 백오프 절반 감소, (2) _poll_commands_loop adaptive 간격 (빈 응답 시 3s→10s→30s→60s), (3) Gateway 윈도우 1s/30→10s/100, (4) 루프 stagger (0~3.5s 오프셋)
  • 주의: _reset_backoff() [즉시 리셋] 패턴은 다중 소비자가 같은 transport를 공유하는 환경에서 절대 사용 금지. 단일 성공이 전체 백오프를 무효화함

[2026-03-15] DEDUP step_index 크로스 세션 충돌 — 승인 신호 누락

  • 증상: variet_agent에서 WAITING step 감지 → pending 미생성 → Discord 승인 요청 미전달 → 10분+ 대기
  • 원인: writePendingApproval()의 DEDUP 로직이 step_index로 중복 검사 시 conversation_id를 비교하지 않음. 세션 A(step=28)와 세션 B(step=28)가 동일시되어 DEDUP skip. 각 세션의 step_index는 0부터 시작하므로 크로스 세션 충돌 빈번
  • 해결: DEDUP 조건에 existing.conversation_id === data.conversation_id 가드 추가
  • 주의: project_name 가드만으로는 불충분 — 같은 Extension 인스턴스가 여러 세션을 볼 수 있음. 반드시 conversation_id까지 비교 필요

[2026-03-15] fs.watch silent fail — Discord→Extension 명령 전달 불가

  • 증상: !auto, !stop, 텍스트 릴레이 등 Discord→Extension 방향 명령이 전부 작동 안 함. Extension log에 [AUTO] 로그 0건
  • 원인: watchCommandsDir()fs.watch가 Windows에서 silent fail. watcher 세팅은 되지만 이벤트가 실제로 fire 안 됨. 실측 테스트에서 command 파일 드롭 후 2초 대기 → 미소비 확인
  • 해결: fs.watch 유지 + 3초 setInterval 폴링 fallback 추가. processAllCommands() 함수로 공통화
  • 주의: fs.watch는 Windows에서 구조적으로 불안정 — 이 프로젝트의 response watcher (known-issue [2026-03-11])에서도 동일 문제. 새 watcher 추가 시 반드시 polling fallback 병행

[2026-03-15] projectName=default 승인 오발 — workspace 없는 AG 창

  • 증상: workspace 없는 AG 창(Empty Window)이 step_probe로 다른 프로젝트의 WAITING step 감지 → project_name: "default" pending 생성 → #ag-default 채널로 전달 → 유저 미확인
  • 원인: detectProjectName()이 workspace 없으면 "default" 반환. step_probe는 LS의 GetAllCascadeTrajectories모든 세션을 볼 수 있으므로, 다른 workspace 세션의 WAITING을 감지하여 잘못된 project_name으로 pending 생성
  • 해결: step_probe 2곳(normal + offset)에서 projectName === 'default'이면 pending 생성/auto-approve 억제. 로그만 남김
  • 주의: #ag-default 채널이 생성되면 유저가 인지하지 못하므로 치명적. Empty Window에서는 bridge 기능을 최소화해야 함

[2026-03-15] Discord Gateway MESSAGE_CREATE 중복 — embed 이중 전송

  • 증상: 텍스트 메시지, !auto 등 Discord 명령 시 동일 embed가 2개 전송
  • 원인: Discord Gateway가 WebSocket 불안정 시 MESSAGE_CREATE 이벤트를 중복 전달 (known discord.py issue). 봇 프로세스 1개, 코드상 on_message 1회 실행 로직이지만 이벤트 자체가 2번 도착
  • 해결: on_message_processed_message_ids: set[int] (bounded 200개) 중복 방지 추가
  • 주의: Gateway reconnection, RESUME 실패 시 발생 빈도 증가. message ID 기반 dedup이 가장 확실한 방어

[2026-03-15] HTML 패치 멀티 인스턴스 race condition — 화면 파괴

  • 증상: Extension 패치 후 AG 재시작 시 전체 화면 날아감 (빈 화면/깨진 레이아웃)
  • 원인: 2+ Extension 인스턴스가 setupApprovalObserver()에서 동시에 같은 workbench.html/workbench-jetski-agent.htmlreadFileSync/writeFileSync → 0-byte 파일 또는 부분 데이터 → 영구 손상
  • 해결: .patch-lock 파일 기반 cross-instance lock 추가 (30초 stale 판정). Lock 취득 실패 시 패치 skip
  • 주의: Lock은 "방지"에 해당. 기존 .orig 백업은 "복구"에 해당. 둘 다 유지해야 함. Lock 파일 경로 = scriptDir/.patch-lock

[2026-03-15] 로컬 승인 ↔ Discord 승인 교차 race condition

  • 증상: AG에서 직접 Run 클릭 후 Discord 승인 요청이 "완료됨" 표시 안 됨. Discord에서도 뒤늦게 클릭 시 이미 완료된 step에 RPC 실행 → 에러 스팸
  • 원인 1: auto_resolve가 pending 상태만 변경하고 Discord에 알림 없음 → writeChatSnapshot() 추가
  • 원인 2: processResponseFile()이 pending의 auto_resolved/expired 상태를 체크하지 않음 → 상태 확인 후 skip 로직 추가
  • 원인 3: Bot의 auto_resolved 스캐너가 discord_message_id에만 의존 — Extension은 이 값을 모름 → _approval_messages dict (rid→msg_id) 추가, fallback 조회
  • 주의: processResponseFile L2534의 lastPendingStepIndex = -1 리셋이 Discord 승인 경로에서 auto_resolve 중복 진입을 방지하는 핵심 gate. 이 줄을 삭제하면 중복 알림 발생

[2026-03-15] Extension 버전 미배포 — source ≠ deployed

  • 증상: 소스(v0.3.10)에 수정한 코드가 실제 동작하지 않음. 로그에서 수정 전 동작 확인됨
  • 원인: Extension 빌드/배포 누락. ~/.antigravity/extensions/에 구 버전(v0.3.8) 남아있음
  • 해결: VSIX 빌드 → 설치 → 구 버전 디렉토리 삭제 → AG 전체 재시작 (Reload Window 불충분)
  • 주의: Extension 코드 수정 후 반드시 npm run compile && npx vsce package → 배포까지 확인. AG는 전체 File→Exit 후 재시작 필요

[2026-03-15] 크로스 프로젝트 DEDUP MERGE — Deriva→gravity_control 오염

  • 증상: Deriva의 step_probe 데이터(step_index, command)가 gravity_control의 DOM observer pending에 MERGE됨. Discord에 Deriva 명령이 gravity_control 채널에 표시
  • 원인: writePendingApproval() DEDUP MERGE 조건에 project_name 가드 없음 — source === 'dom_observer' && status === 'pending'만 검사하므로 타 프로젝트 pending에도 MERGE
  • 해결: MERGE 조건에 existing.project_name === projectName 추가 (v0.3.10)
  • 주의: bridge/pending/ 디렉토리는 모든 Extension 인스턴스가 공유. 파일 읽기/쓰기 시 반드시 project_name 기반 필터링 필수

[2026-03-15] Double-Fire Auto-Approve — AI 세션 중단

  • 증상: auto-approve ON 시 AI 세션이 간헐적으로 중단/멈춤
  • 원인: step_probe가 WAITING 감지 시 autoApproveEnabled면 직접 tryApprovalStrategies() 호출(경로A). 동시에 writePendingApproval() → Bot auto_approve_scanner → response 파일 → processResponseFile()tryApprovalStrategies() 호출(경로B). 같은 step에 대해 2번 RPC 호출 → 충돌
  • 해결: Extension auto-approve 경로 A 제거. Bot만 auto-approve 담당 (v0.3.11). Extension은 항상 writePendingApproval() 경로 사용
  • 주의: 향후 Extension에서 직접 approve 로직을 추가할 때는 Bot auto-approve와의 경합을 반드시 고려. 단일 경로 원칙 유지

[2026-03-15] DOM Observer "Deny" False Positive — Auto-approve 세션 크래시

  • 증상: auto-approve ON 시 Discord에 "Deny" command가 자동 승인됨 → AI 세션 반복 크래시
  • 원인: AG file_permission UI에 [Allow Once] [Allow This Conversation] [Deny] 3개 버튼 표시 → DOM observer가 "Deny" 텍스트를 독립 pending으로 생성 (FALSE_POSITIVE_RE에 "Deny" 미포함). 이 pending에는 step_type이 없어 default 분기 runCommand: { confirm: true } RPC 전송 → 실제 대기 중인 file_permission과 타입 불일치 → 세션 크래시
  • 해결: (1) FALSE_POSITIVE_REDeny|Allow Once|Allow This Conversation|Dismiss|Decline 추가, (2) bot.py auto-approve에 reject-word command 차단 가드, (3) smart button_index 선택 (방어)
  • 주의: FALSE_POSITIVE_RE는 렌더러 인라인 스크립트 안에 있으므로 VSIX 빌드 → AG 풀 재시작 필요. 새 UI 버튼 패턴 추가 시 반드시 이 필터 점검. 수정 시 해당 파일만 보지 말고 전체 데이터 플로우(producer→consumer→side effects) 분석 필수 (AGENT.md 규칙 #10)