docs: Observer 개발 가이드 SSOT 문서 생성 — 제약사항/배포/DOM구조/교훈 종합
This commit is contained in:
167
.agents/references/observer-dev-guide.md
Normal file
167
.agents/references/observer-dev-guide.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Observer Script 개발 가이드 — SSOT
|
||||
|
||||
> **이 문서는 Observer 코드 변경 전 반드시 확인하는 SSOT입니다.**
|
||||
> 모든 Observer 관련 설계, 배포, 제약사항이 이 문서에 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. Observer 코드 특성
|
||||
|
||||
### 1.1 실행 환경
|
||||
- Observer는 **workbench-jetski-agent.html**에 인라인 `<script>`로 삽입됨
|
||||
- **AG Native의 Electron 렌더러 프로세스**에서 실행 (VS Code extension host가 아님)
|
||||
- 렌더러는 **strict mode 아님** (확인 필요), 하지만 V8 parser는 일부 strict-like 규칙 적용
|
||||
- `generateApprovalObserverScript(port)` 함수가 **TypeScript template literal**로 스크립트 생성
|
||||
|
||||
### 1.2 코드 작성 규칙 (위반 시 Observer 전체 크래시)
|
||||
|
||||
| 규칙 | 이유 | 예시 |
|
||||
|------|------|------|
|
||||
| **for 루프 안에 function 선언 금지** | V8 strict mode error | `var fn = function(){}` 사용 |
|
||||
| **문자열 리터럴에 특수문자 금지** | template literal 이스케이핑 깨짐 | `'??'` → `'MAX'` |
|
||||
| **regex에 `\\s` 등 이스케이프 금지** | template literal이 `\\\\s` → `\\s` (리터럴) | 문자열 비교 사용 |
|
||||
| **ES6+ 구문 금지** | 구 V8 호환 | `var` 사용, `let/const/arrow` 금지 |
|
||||
| **배포 전 SYNTAX CHECK 필수** | Observer 크래시 방지 | 아래 검증 명령어 참조 |
|
||||
|
||||
### 1.3 필수 검증 명령어 (모든 빌드 전 실행)
|
||||
```powershell
|
||||
npm.cmd run compile; node -e "const {generateApprovalObserverScript}=require('./out/observer-script'); let s=generateApprovalObserverScript(18080); try { new Function(s); console.log('SYNTAX OK'); } catch(e) { console.log('ERROR:', e.message); }"
|
||||
```
|
||||
**SYNTAX OK가 나오지 않으면 절대 배포하지 않는다.**
|
||||
|
||||
---
|
||||
|
||||
## 2. 배포 프로세스
|
||||
|
||||
### 2.1 Observer 코드가 포함된 변경
|
||||
Observer 코드 변경은 **extension host 코드 변경보다 비용이 높다**:
|
||||
|
||||
```
|
||||
VSIX 빌드 → VSIX 설치 → AG 재시작 #1 (extension이 HTML 패치)
|
||||
→ AG 재시작 #2 (패치된 HTML 로드) → Observer 실행
|
||||
```
|
||||
|
||||
**총 2번 AG 재시작 필요**
|
||||
|
||||
### 2.2 Extension host 코드만 변경 (approval-handler, http-bridge 등)
|
||||
```
|
||||
VSIX 빌드 → VSIX 설치 → AG 재시작 #1 → 즉시 적용
|
||||
```
|
||||
|
||||
**1번 AG 재시작 필요**
|
||||
|
||||
### 2.3 VSIX 설치 확인
|
||||
```powershell
|
||||
Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "*gravity*" -Directory |
|
||||
ForEach-Object { $j = Get-Content (Join-Path $_.FullName "package.json") | ConvertFrom-Json; "$($_.Name): v$($j.version)" }
|
||||
```
|
||||
|
||||
### 2.4 HTML 패치 확인 (Observer 코드가 반영되었는지)
|
||||
```powershell
|
||||
Select-String -Path "$env:LOCALAPPDATA\Programs\Antigravity\resources\app\out\vs\code\electron-browser\workbench\workbench-jetski-agent.html" -Pattern "검색할_함수명" -Quiet
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. AG Native DOM 구조
|
||||
|
||||
### 3.1 Chat Panel (Observer가 접근 가능)
|
||||
- 위치: `document.querySelector('#conversation')` 또는 `document.querySelector('[class*="conversation"]')`
|
||||
- AI 응답 블록: `.leading-relaxed.select-text`
|
||||
- 사용자 메시지 블록: `.select-text.rounded-lg` (v0.5.74+)
|
||||
- Thinking 블록: 조상에 `max-h-[200px]` 클래스 있음 → 필터링
|
||||
|
||||
### 3.2 승인 버튼 (Observer가 접근 가능)
|
||||
- "Always run" 버튼: `<button>` 태그, chat panel 내
|
||||
- 명령어 텍스트: `footer`의 **형제(sibling)** 요소의 `pre.font-mono` (조상 아님!)
|
||||
- 조상 탐색 trail: `d0:button → d1:div → d2:footer` (footer.parentElement === null)
|
||||
- "Retry" 버튼: `<button>` 태그, chat panel 내
|
||||
|
||||
### 3.3 Diff Review (Accept all / Reject all) — Observer 접근 **불가**
|
||||
- "Accept all" / "Reject all" 버튼은 **에디터 webview**에 렌더링
|
||||
- Observer의 `document`에서 `querySelectorAll('button')` 등으로 찾을 수 없음
|
||||
- ACCEPT-SCAN 디버그 로그로 확인: `button, a, div, span, [role="button"]` 전체 스캔해도 미발견
|
||||
- **해결 경로**: Extension host에서 `antigravity.acceptAgentStep` 명령 실행 (CMD-DISCOVERY에서 발견됨)
|
||||
|
||||
### 3.4 DOM 렌더링 타이밍
|
||||
- "Always run" 버튼이 DOM에 나타난 후, `pre.font-mono` (명령어 텍스트)는 **100~300ms 후** 렌더링
|
||||
- 해결: DEFERRED 컨텍스트 — 500ms 딜레이 후 재추출 (v0.5.84+)
|
||||
|
||||
---
|
||||
|
||||
## 4. 파일 경로 매핑
|
||||
|
||||
| 항목 | 경로 |
|
||||
|------|------|
|
||||
| AG 설치 경로 | `$env:LOCALAPPDATA\Programs\Antigravity\` |
|
||||
| workbench HTML | `...\resources\app\out\vs\code\electron-browser\workbench\workbench-jetski-agent.html` |
|
||||
| Extension 로그 | `$env:USERPROFILE\.gemini\antigravity\bridge\extension.log` |
|
||||
| Pending 파일 | `$env:USERPROFILE\.gemini\antigravity\bridge\pending\*.json` |
|
||||
| Response 파일 | `$env:USERPROFILE\.gemini\antigravity\bridge\response\*.json` |
|
||||
| VSIX extensions | `$env:USERPROFILE\.vscode\extensions\variet.gravity-bridge-*\` |
|
||||
| HTTP Bridge 포트 | 34332 (또는 `getDeterministicPort('gravity_control')`) |
|
||||
| Discord 채널 | `#ag-gravity_control` (ID: 1483082084540223663) |
|
||||
|
||||
---
|
||||
|
||||
## 5. 과거 실수 및 교훈
|
||||
|
||||
### 5.1 VSIX 미설치 (v0.5.78~83)
|
||||
- **증상**: 빌드만 하고 `code --install-extension` 실행 안 함
|
||||
- **결과**: 설치된 버전이 v0.5.50, 모든 수정사항 미적용
|
||||
- **교훈**: 빌드 후 반드시 `code --install-extension *.vsix --force` 실행
|
||||
- **확인**: `Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "*gravity*"`
|
||||
|
||||
### 5.2 function 선언 → Observer 크래시 (v0.5.84~86)
|
||||
- **증상**: `function _isGenericDesc(d){}` 를 for 루프 내부에 선언
|
||||
- **결과**: Observer 전체 크래시, chat relay + auto-approve 중단
|
||||
- **교훈**: `var fn = function(){}` 사용, 배포 전 SYNTAX CHECK 필수
|
||||
|
||||
### 5.3 깨진 문자열 리터럴 (v0.5.86)
|
||||
- **증상**: `{tag:'??',...}` (특수문자가 따옴표 깨뜨림)
|
||||
- **결과**: SYNTAX ERROR, Observer 미작동
|
||||
- **교훈**: template literal 안에서 특수문자/이모지 사용 주의
|
||||
|
||||
### 5.4 regex 이스케이핑 실패 (v0.5.83~84)
|
||||
- **증상**: `/Always\\s+run/` → 생성 시 `\\s` (리터럴 백슬래시+s)로 출력
|
||||
- **결과**: "Always run" 매칭 실패
|
||||
- **교훈**: template literal 안에서 regex 대신 **문자열 비교** 사용
|
||||
|
||||
### 5.5 _from_ws 파일 무한 누적 (v0.5.78~84)
|
||||
- **증상**: response 파일에 `_from_ws: true` 마커 → processResponseFile이 스킵 → 영원히 삭제 안 됨
|
||||
- **결과**: 3초마다 4개 파일 × SKIP 로그 → 로그 스팸, 다른 처리 방해
|
||||
- **교훈**: 보존 파일에는 반드시 **TTL(자동 만료)** 추가
|
||||
|
||||
---
|
||||
|
||||
## 6. 디버깅 체크리스트
|
||||
|
||||
### Observer가 작동하지 않을 때
|
||||
1. `extension.log`에서 `setup complete` 확인 → Observer 로드 여부
|
||||
2. `OBSERVER-LOG` 패턴 검색 → 스캔 활동 여부
|
||||
3. `HTTP-REQ` 검색 → HTTP bridge에 요청 도달 여부
|
||||
4. **SYNTAX CHECK** 실행 → 생성 스크립트 문법 검증
|
||||
5. `SKIP _from_ws` 반복 확인 → stale response 파일 정리
|
||||
|
||||
### Discord에 메시지가 안 올 때
|
||||
1. `POST /chat` 검색 → chat relay 전송 여부
|
||||
2. `WS.*send` 검색 → WebSocket 전송 여부
|
||||
3. Discord API로 직접 확인: `node extension/scratch/discord_read.js`
|
||||
4. stale response 파일 확인: `Get-ChildItem $env:USERPROFILE\.gemini\antigravity\bridge\response\*.json`
|
||||
|
||||
---
|
||||
|
||||
## 7. 버전 히스토리 요약
|
||||
|
||||
| 버전 | 핵심 변경 | 결과 |
|
||||
|------|----------|------|
|
||||
| v0.5.50 | 기본 릴레이 시스템 | ✅ 안정 |
|
||||
| v0.5.78 | `_from_ws` 마커 (Retry 보존) | ✅ 작동 (TTL 미구현) |
|
||||
| v0.5.79 | sibling 탐색 + thinking 필터 | ✅ 작동 |
|
||||
| v0.5.80~81 | Accept all offsetParent 완화 | ❌ 구조적 불가 (에디터 webview) |
|
||||
| v0.5.82 | 버튼 셀렉터 확장 + ACCEPT-SCAN | 진단용 |
|
||||
| v0.5.83 | DEFERRED 컨텍스트 500ms | regex 이스케이핑 실패 |
|
||||
| v0.5.84 | regex → 문자열 비교 | function 선언 크래시 |
|
||||
| v0.5.85 | `_from_ws` TTL 60초 | ✅ stale 정리 |
|
||||
| v0.5.86 | function → var expression | 깨진 문자열 미발견 |
|
||||
| v0.5.87 | 깨진 문자열 2건 수정 | ✅ SYNTAX OK |
|
||||
Reference in New Issue
Block a user