From a4d7286bce53a26dcace7d7f115374d4f67c30b1 Mon Sep 17 00:00:00 2001 From: Variet Worker Date: Sun, 12 Apr 2026 06:14:46 +0900 Subject: [PATCH] refactor(observer): v7 step-aware AG Native DOM parser with data-testid/data-step-index based content extraction - Replace CSS class-based scanning with [data-testid='conversation-view'] + [data-step-index] traversal - New extractCleanStepText(): clone-and-strip buttons/SVG/icons before text extraction - New extractStepContext(): step-container-aware context with header + code block - NOISE_RE: block Material icon names, button labels, UI artifacts - Auto DOM structure dump on first conversation-view detection - Enhanced deep-inspect with step element + button inventory - known-issues: document AG Native SDK API incompatibility --- .agents/references/known-issues.md | 519 +++++++++++++++-------------- docs/devlog/2026-04-11.md | 3 +- docs/devlog/2026-04-12.md | 4 + extension/src/approval-handler.ts | 197 +++++++---- extension/src/http-bridge.ts | 19 ++ extension/src/observer-script.ts | 493 ++++++++++++++++++--------- extension/src/step-probe.ts | 3 +- 7 files changed, 766 insertions(+), 472 deletions(-) create mode 100644 docs/devlog/2026-04-12.md diff --git a/.agents/references/known-issues.md b/.agents/references/known-issues.md index 5c0590e..a0fc716 100644 --- a/.agents/references/known-issues.md +++ b/.agents/references/known-issues.md @@ -1,253 +1,266 @@ -# Known Issues & Lessons Learned - -> **이 파일은 SSOT(Single Source of Truth)입니다.** -> 디버깅이나 구현 전에 **반드시** 이 파일을 확인하세요. -> 세션 종료 시 새로 발견된 이슈를 이 파일에 추가합니다. - -> [!TIP] -> 해결 완료된 과거 이슈는 [`known-issues-archive.md`](file:///c:/Users/Variet-Worker/Desktop/gravity_control/.agents/references/known-issues-archive.md)에 보관되어 있습니다. -> 비슷한 문제가 재발하면 archive에서 검색하세요. - ---- - -### [2026-04-09] [Bridge] Discord Body Content Missing Due to Step Probe Dummy Payload -- **증상**: 대규모 UI 마이그레이션 후, 디스코드 승인 메시지 본문에 실행할 코드/명령어가 완전히 누락되고 "Step #15"와 같은 디폴트 텍스트만 전송됨. -- **원인**: Native UI 변경으로 인해 DOM observer가 추출한 버튼 텍스트("Always run")가 `http-bridge.ts` 필터 우회 및 bot.py에서 지연(defer) 처리됨. 반면 `step-probe.ts`가 `GetAllCascadeTrajectories` 폴링을 통해 동시에 발생시킨 dummy pending payload (명령어 상세 내용이 없이 `Step #XX` 라는 텍스트만 포함)가 봇에 의해 먼저 자동 승인되면서 정작 실제 코드 영역 정보가 증발함. -- **해결**: `step-probe.ts` 내에 `formatStepProbeCommand` 헬퍼 함수를 추가하여, WAITING 상태 스텝의 `argumentsJson` 데이터를 직접 파싱하고 `CommandLine`, `TargetFile` 등 실제 명령어와 상세 인자/코드를 `command`와 `description`으로 할당하여 브릿지로 넘기도록 패치함. DOM 옵저버의 불안정성과 관계없이 일관된 본문 전달 보장. -- **주의**: UI 스크래핑에 의존하는 DOM Observer 방식은 UI 레이아웃, 아이콘 삽입 등에 취약하므로, 상세 페이로드 추출은 항상 100% 신뢰 가능한 SDK RPC(`step-probe.ts`) 데이터를 우선 사용하도록 구성해야 함. - -## 포맷 - -### [2026-03-23] [Extension] Cross-Project DOM Observer Leakage -- **증상**: 다중 원격 컴퓨터에서 동일한 프로젝트명으로 실행된 VS Code들이 서로의 `execute JavaScript` (Allow) 승인 신호를 가로채거나 엉뚱한 서버로 보냄. -- **원인**: Extension이 `workbench.html`에 스크립트를 주입할 때 결정론적 포트를 하드코딩했는데, 전역 캐시된 HTML 파일을 모든 로컬/원격 연결이 공유하면서 마지막에 열린 프로젝트의 포트 번호로 덮어씌워짐. -- **해결**: `extension.ts`에서 상태 표시줄(Status Bar) `tooltip`에 포트를 주입하고, `observer-script.ts`에서 DOM 쿼리를 통해 동적으로 자신의 창(Window)에 할당된 포트를 찾아내도록 수정. `vscode.env.asExternalUri`를 사용하여 포트 충돌 시 우회된 주소까지 로컬 포워딩에 매핑되도록 지원. -- **주의**: VS Code UI 코어(HTML) 패치 시, 여러 창(Window)이나 다중 원격 접속 시 환경(Scope) 분리에 각별한 주의가 필요함. 전역 자원에 의존하는 하드코딩 지양. - -### [날짜] [키워드] — 한줄 요약 -- **증상**: 무엇이 잘못되었는가 -- **원인**: 근본 원인 -- **해결**: 올바른 해결 방법 -- **주의**: 재발 방지를 위한 교훈 -``` - ---- - -### [2026-04-08] [Discord Bot] Channel Deletion Cache Desync -- **증상**: 봇이 켜져 있는 상태에서 Discord 채널(g-project-name)을 삭제하면, 봇이 삭제를 인지하지 못하고 새 채널을 생성하지 않으며 메시지도 증발함. -- **원인**: ot.py의 self.project_channels 딕셔너리에 채널 객체가 캐시되어 있어, API 호출 없이 캐시된(삭제된) 채널로 메시지를 보내려 시도하다 404 에러 발생 후 실패함. -- **해결**: 채널 맵핑이 꼬였을 때는 **Python 봇(Docker 컨테이너)을 재시작**하여 캐시를 초기화하고 채널 목록을 새로 갱신하게 함. -- **주의**: 채널 관리는 캐시에 의존하기 때문에 강제로 Discord UI에서 채널을 지웠을 때는 반드시 봇을 재구동해야 함. - -### [2026-04-08] [Extension] Multiple Workspace LS Cross-Connection -- **증상**: ariet-llm 창에서 켰으나 gravity_control의 백그라운드 구동 중인 LS에 연결되어 자기 자신 창의 신호를 잡지 못함. -- **원인**: 여러 VS Code 창을 띄웠을 때 어떤 창에서는 Antigravity 패널을 누르지 않아 전용 LS가 시작되지 않음. ixLSConnection()이 자기 몫의 LS를 찾지 못하고 fallback으로 기존에 떠 있던 다른 창의 LS에 연결됨. -- **해결**: 대상 창에서 Developer: Reload Window 실행 후 **사이드바의 로컬 Antigravity 챗봇 패널을 한 번 열어** 자신의 LS 프로세스를 띄운 뒤에 Gravity Bridge를 Start함. -- **주의**: LS는 자동으로 시작되지 않고 사용자가 채팅 패널을 한 번 클릭/활성화해야만 Spawn 됨. - -## 🔴 Active/Recent Issues - -### [2026-04-09] [Extension] Agent UI Native Migration & Icon Text Gluing -- **증상**: UI Tailwind/Native 마이그레이션 및 아이콘 적용 후, Discord 브릿지로 신호가 전송되지 않음. -- **원인**: 네이티브 UI 버튼의 `textContent` 추출 시, Codicons 등 아이콘 폰트 문자열(e.g., ` Accept`)이 앞부분에 병합(Gluing)되면서, 기존의 `^` 앵커가 포함된 정규식 매칭(`/^(?:Always\s*)?Run/i`)이 실패함. -- **해결**: `observer-script.ts`의 스캔, Sibling 버튼 수집, Webview Trigger-click 등 `textContent`를 추출하는 모든 DOM 읽기 구간에 `txt.replace(/^[^a-zA-Z0-9]+/, '')` 전처리를 적용하여 선행 기호/아이콘을 안전하게 제거. -- **주의**: Native UI 컴포넌트 환경에서는 텍스트 노드뿐만 아니라 아이콘/SVG 컴포넌트의 텍스트 글루잉 현상으로 인해 엄격한 시작점(`^`) 정규식이 깨질 수 있으므로, 항상 불필요한 특수문자 전처리를 선행해야 함. - -### [2026-04-09] [Extension] Agent UI Native Migration & CodeLens False Positive Filter -- **증상**: UI Tailwind/Native 마이그레이션 적용 후, Discord 브릿지로 신호가 전혀 전송되지 않음 -- **원인**: Agent 패널이 탭/에디터 본문에 직접 렌더링되면서, 기존 오작동 방지 로직(`if (b.closest('.monaco-editor'))`)에 패널 전체 버튼이 포착되어 무시됨 -- **해결**: 너무 광범위한 `.monaco-editor` 방어를 해제하고, 코드 렌즈 고유 컨테이너인 `.codelens-decoration` 내부일 경우에만 무시하도록 핀포인트 수정 -- **주의**: DOM 옵저버 필터 조건 작성 시 래퍼 클래스는 UI 디자인 개편(Native, Editor Tab 등 위치 변경)에 매우 취약함. 가장 구체적인 내부 노드 클래스나 타겟 고유 속성을 통해 필터링할 것 - -### [2026-03-31] [step-probe] GetAllCascadeTrajectories 10-Item Hard Limit (Signal Drop) -- **증상**: `guitar_score` 등에서 활성화된 세션의 디스코드 승인 신호를 "계속해서" 잡지 못함. (WS 60초 타임아웃보다 더 치명적으로 신호가 아예 가지 않음) -- **원인**: Extension이 활성 세션을 찾기 위해 호출하는 `GetAllCascadeTrajectories` LS API가 `{}`(빈 인자)로 호출될 때, 기본적으로 **10개의 세션만 반환하는 하드 리밋(Pagination Limit)**이 걸려있음. 이로 인해 작업 내역이 누적되면 수많은 최신/진행 중 세션들이 10개 목록에서 밀려나 누락됨. 익스텐션은 세션이 없다고 판단해 강제로 `IDLE` 모드에 진입하며, 승인 대기열(WAITING) 자체를 검사하지 않게 됨. -- **해결** (v0.5.14): `v0.5.13`에서 도입했던 `{ limit: 100 }`이 LS 단의 쿼리 과부하로 인한 VS Code UI 프리징(DoS)을 유발하여 롤백하는 중 필수 정렬 파라미터(`descending: true`)까지 소실되었던 실수를 교정함. 최종적으로 `{ limit: 30, descending: true }`를 적용하여 파싱 부하 최소화 및 최신 세션 최상단(Index 0) 조회를 안전하게 구현함. -- **주의**: LS의 기본 SQLite/DB 응답 Limit 규칙에 의존하여 전체 데이터 스캔을 수행하는 로직은 언제든 Truncation 이슈(Data Loss)를 유발할 수 있음. - -### [2026-03-31] [WS] Browser API Fallback 60s Timeout (Zombie Connection) -- **증상**: `guitar_score` 등 모든 작업 환경에서 약 60초마다 WebSocket 연결이 끊기고 재연결되는 현상이 반복되며(extension.log에 `Heartbeat timeout` 계속 출력), 그 사이 디스코드 승인 신호를 놓침. -- **원인**: Extension이 `ws` 모듈 로드 실패(VS Code 환경 등)로 인해 브라우저 내장 `WebSocket` 객체로 Fallback 됨. 브라우저 WS는 서버의 네이티브 ping을 받아 pong을 자동 응답하지만 JS에 이벤트를 노출하지 않음. 이로 인해 `lastPongTime` 갱신이 불가능해져, `Date.now() - lastPongTime > 60000` 조건이 무조건 통과되어 멀쩡한 연결을 강제 종료함 (False Positive). -- **해결** (v0.5.12): - 1. `hub.py`: `{"type": "heartbeat"}` JSON 메시지 수신 시 명시적으로 `{"type": "pong"}` JSON을 응답하도록 수정. - 2. `ws-client.ts`: 명시적 `pong` 핸들러 추가. JSON pong 지원 서버거나 Node.js ws를 사용할 때만 60초 타임아웃 검증을 거치도록 조건 보강 (`forceHeartbeatTimeoutIfNoPong`). -- **주의**: 브라우저 표준 WebSockets(W3C)는 ping/pong 제어 프레임을 JS로 노출하지 않음. 폴리필/크로스플랫폼 WS 래퍼 사용 시 하트비트는 반드시 JSON 메세지 형태의 Application Layer Ping/Pong으로 풀어내거나, Native WS API 여부를 확실히 체크해야 함. - -### [2026-03-28] [step-probe] GetCascadeTrajectorySteps UTF-8 에러 무한 루프 -- **증상**: `guitar_score` 프로젝트에서 `[STEP-PROBE] error: ...invalid UTF-8` 에러가 5초마다 반복되며 Discord 승인 신호가 전달되지 않음. -- **원인**: AG LS 서버에서 특정 step의 `CortexStepEphemeralMessage.content`에 바이너리 데이터(이미지 등) 포함 → proto UTF-8 직렬화 500 에러. `catch(e)` 블록에서 `stallProbed=true`를 설정하지 않아 `!ctx.stallProbed` 조건이 항상 true → 5초마다 동일 요청 무한 재시도. -- **해결** (v0.5.11): `catch` 블록에서 UTF-8 에러 감지 시 `stepOffset=currentCount-20`으로 fallback 요청. offset도 실패 시 `stallProbed=true` 설정하여 루프 차단. `delta>0` 이벤트 발생 시 L433에서 자동 리셋. -- **주의**: `stallProbed=true`는 영구 Lock이 아님 — `delta>0` 시 자동 리셋. UTF-8 에러는 AG 서버 측 문제(이미지/바이너리 데이터가 ephemeral message에 포함)이므로 Extension에서 graceful fallback만 처리. - -### [2026-03-28] [approval-handler] stepIndex 미확정 시 wrong-stepIndex RPC 낭비 -- **증상**: DOM observer 경로로 `terminal_command` pending 생성 후 Discord 승인 시 `HandleCascadeUserInteraction(stepIndex=0)` → `"input not registered for step 0"` → LS reconnect → 재시도 → DOM click fallback으로 저하. (wrong-LS와 동일한 증상이나 다른 원인) -- **원인**: `ctx.lastPendingStepIndex=-1` (step-probe가 UTF-8 에러로 WAITING 미감지)임에도 `Math.max(0, -1)=0`으로 clamp되어 존재하지 않는 step 0에 RPC 전송. -- **해결** (v0.5.11): `effectiveStepIndex = stepIndex >= 0 ? stepIndex : (lastPendingStepIndex >= 0 ? lastPendingStepIndex : -1)`. `effectiveStepIndex < 0`이면 RPC 블록 전체 skip → DOM click 직행 (기존과 동작 동일, LS reconnect 낭비 제거). -- **주의**: 기존 규칙 #14(`uint32`에 음수 금지)와 충돌처럼 보이나, `effectiveStepIndex=-1`일 때 RPC 자체를 **전송하지 않으므로** 위반 아님. RPC 전송 시에는 여전히 유효한 stepIndex만 사용. - -### [2026-03-25] [Architecture] Discord Signal Drop & Extension Freezes -- **증상**: 장시간 자리비움 후 복귀 시 Discord로 승인 신호가 오지 않거나 VS Code UI가 간헐적/지속적으로 멈춤(Freeze). -- **원인**: - 1. `ws.onerror` 발생 후 `onclose` 누락 시 재연결 콜백 호출이 이루어지지 않아 무한 대기 (장시간 마비) - 2. `ws-client` 재연결 시 누적된 200개 큐를 동기식 burst 전송하여 Hub의 속도 제한(60개/10초)에 걸려 확정 영구 삭제됨 - 3. 로컬 브릿지 `http-bridge.ts`의 과거 유산인 `FALSE_POSITIVE_RE` 정규식이 AI 고유 버튼(Allow, Deny, Accept) 마저 필터링하여 Discord 전송 원천 차단 - 4. `step-probe.ts` 폴링 루프 내 동기식 파일 I/O 사용으로 인한 프리즈 -- **해결** (v0.5.10): ws-client에 하드 타임아웃 및 50ms Paced-flush 적용, http-bridge의 정규식 기능 완화, step-probe 비동기 I/O 전환 체제 적용, observer-script의 필터된 신호 무한 HTTP 폴링 방어 코드 반영. -- **주의**: Extension 내부 로직 버그였으므로 Hub(Python) 코드는 건드리지 않음. Hub 속도 제한은 정상 방어 기제이므로 클라이언트 단의 Pacing이 올바른 방향임. -### [2026-03-24] DOM Observer /trigger-click 렌더링 순서 오작동 및 False Positive 프리징 -- **증상**: v0.5.9 패치 이후 코딩 시 Agent 화면이 끊임없이 서명 대기(Pending) 상태로 멈춤. 또는 디스코드에서 `Approve` 시 에디터 내의 엉뚱한 `Run Test`(코드 렌즈)를 클릭함. -- **원인**: 텍스트와 정규식(`/^Run/i` 등)에만 의존하여 `querySelectorAll`을 수행할 경우, DOM 트리에 렌더링된 수많은 VS Code 네이티브 코드 렌즈 버튼을 Agent 버튼보다 먼저 찾아버리는 발생 위치(Context)의 한계점. -- **해결** (v0.5.10): - 1. 감지(Scan): `isVSCodeMainWindow` 및 탐색 노드 `isBodyRoot` 확인을 통해, 에디터 본문 영역에서는 "Run", "Approve" 감지를 원천 제거 (오직 패널 내로 한정). - 2. 클릭(Trigger-click): `deepFindButtons()` 내에서 `findPanel()`(에이전트 패널) -> 알림 Toasts -> Document 본문 순으로 탐색 **우선순위(Priority)**를 강제 적용. -- **주의**: 버튼 이벤트 후킹 시 텍스트 매칭에만 의존하지 말고, 반드시 DOM 탐색 우선순위와 컨텍스트 범위를 함께 필터링하여 False Positive를 차단할 것. - -### [2026-03-24] DOM Observer — VS Code Native UI Blind Spot -- **증상**: "Always Allow" 및 일반 "Allow Alt+↵" 권한 알림 버튼이 디스코드 권한 센싱에서 완전히 누락됨. -- **원인**: VS Code 네이티브 알림 및 채팅 패널 내의 버튼은 `