From 6d605d8879a9366028aa3d64fe8ab30860f09e14 Mon Sep 17 00:00:00 2001 From: Variet Worker Date: Wed, 15 Apr 2026 08:20:42 +0900 Subject: [PATCH] =?UTF-8?q?fix(observer/bridge):=20PROMPT=5FONLY=5FRE=20?= =?UTF-8?q?=E2=80=94=20regex=20escaping=20+=20ellipsis=20prefix=20handling?= =?UTF-8?q?=20(v0.5.45)=20#task-619?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Observer: \\\\s (4-backslash) → \\s (2-backslash) in template literal regex - Per known-issues rule: regex literals need 2-backslash for \s, \d etc. - Old: literal \\s matched, new: whitespace class matched correctly http-bridge: /^[\s\\\/]*[\w_.-]+\s*[>»$#]\s*$/ → /^.*[>»$#]\s*$/ - Old pattern failed on ellipsis '…' prefix (U+2026 not in charset) - Terminal prompt '…\\gravity_control >' was passing through as cmd - New pattern: any text ending with prompt marker is skipped --- .agents/references/known-issues.md | 876 ++++++++++++++++++----------- extension/package.json | 2 +- extension/src/http-bridge.ts | 2 +- extension/src/observer-script.ts | 2 +- 4 files changed, 550 insertions(+), 332 deletions(-) diff --git a/.agents/references/known-issues.md b/.agents/references/known-issues.md index 26fafcd..5d698d4 100644 --- a/.agents/references/known-issues.md +++ b/.agents/references/known-issues.md @@ -1,330 +1,548 @@ -# Known Issues & Lessons Learned - -> **�씠 �뙆�씪��� SSOT(Single Source of Truth)�엯�땲�떎.** -> �뵒踰꾧퉭�씠�굹 援ы쁽 �쟾�뿉 **諛섎뱶�떆** �씠 �뙆�씪�쓣 �솗�씤�븯�꽭�슂. -> �꽭�뀡 醫낅즺 �떆 �깉濡� 諛쒓껄�맂 �씠�뒋瑜� �씠 �뙆�씪�뿉 異붽���빀�땲�떎. - -# 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-14] [Extension] Observer template literal 정규식 이스케이핑 오류 — "Running N commands" 스킵 미작동 -- **증상**: v9에서 `Running N commands` 그룹 헤더를 스킵하는 정규식 `/^Running\s*\d+\s*commands?$/i`를 추가했으나, 실제로 "Running2 commands" 텍스트를 전혀 매칭하지 못하여 여전히 Discord에 `cmd="Running2 commands"`가 전송됨 -- **원인**: `observer-script.ts`의 전체 코드가 TypeScript template literal (`` ` `` ... `` ` ``) 안에 있으므로, 정규식 리터럴의 백슬래시가 2중 해석됨: - - TS 소스 `\\\\s` (4중) → template literal 출력 `\\s` → **브라우저에서 regex 리터럴 `\\s` = 리터럴 백슬래시+s** ❌ - - TS 소스 `\\s` (2중) → template literal 출력 `\s` → **브라우저에서 regex 리터럴 `\s` = whitespace class** ✅ - - TS 소스 `\s` (1중) → template literal에서 이스케이프 소멸 → **출력 `s`** ❌ -- **영향 범위**: `NOISE_CODE_RE`, `cleanLines()` (word boundary `\b`, newline `\n`), `cleanButtonText()` (whitespace `\s`), port 탐색 regex `\d`, "Running N commands" 스킵 regex 전부 미작동이었음 - - 단, `NOISE_RE` (new RegExp() 사용)는 문자열 이스케이핑이므로 4중 백슬래시가 올바름 (string → RegExp는 별도 이스케이핑 레이어) -- **해결**: 모든 정규식 리터럴 (`/pattern/flags`) 안의 `\\\\s` → `\\s`, `\\\\d` → `\\d`, `\\\\b` → `\\b`, `\\\\n` → `\\n` 으로 수정 (v0.5.41, `8e89209`) -- **주의**: **template literal 안에서 정규식 특수문자를 쓸 때 반드시 구분:** - - `new RegExp('pattern')` 문자열: `\\\\s` (4중) — string 이스케이핑(1번)+regex 이스케이핑(1번) = 총 2번 - - `/pattern/` 정규식 리터럴: `\\s` (2중) — template literal 이스케이핑(1번)만 = 총 1번 - - **검증법**: `node -e "var f = require('./extension/out/observer-script.js').generateApprovalObserverScript; require('fs').writeFileSync('tmp.js', f(0)); console.log(require('fs').readFileSync('tmp.js','utf8').match(/Running.{10}/g));"` 으로 생성된 코드 확인 - ---- - -### [2026-04-13] [Extension] Observer v8 "Running N commands" 그룹 헤더를 승인 버튼으로 오인 — Discord 빈 내용+잘못된 버튼 -- **증상**: Discord 승인 요청에 command="Running2 commands", description 비어있음, 버튼도 "Running2 commands / Always run" 형태. 실제 코드/명령어 내용이 전혀 표시되지 않음 -- **원인 1**: `observer-script.ts`의 `isActionBtn()`에 `/Running\\s*\\d*\\s*command/i` 패턴이 있어 AG UI의 그룹 헤더 버튼("Running 3 commands")을 승인 버튼으로 분류. `scan()`이 이 버튼을 먼저 만나고 `break`로 나가 실제 "Always run"/"Cancel" 버튼은 처리 안 됨 -- **원인 2**: `extractStepContext()`가 `data-step-index` 속성 없으면 `cleanButtonText(btn)` = "Running2 commands"를 그대로 반환. AG Native에는 `data-step-index`/`data-testid` 속성이 없음 (DOM 덤프로 확인) -- **원인 3**: `http-bridge.ts`의 "Run/Always run" 필터가 step-probe 미활성(activeSessionId 비어있음) 시에도 DOM observer 신호를 차단 -- **해결**: observer v9 (v0.5.40): - 1. `isActionBtn()`에서 "Running N commands" 패턴 제거 - 2. `scan()`에서 `^Running\\s*\\d+\\s*commands?$` 명시적 스킵 - 3. `extractContextFromNearby()` 추가: `data-step-index` 없이 DOM 트리를 20레벨까지 올라가며 `pre`/`code` 블록에서 실제 명령어 추출 - 4. `collectSiblingButtons()` 범위를 parent → grandparent → great-grandparent로 확대, 그룹 헤더 스킵 - 5. `http-bridge.ts`의 "Run" 필터에 `ctx.activeSessionId` 체크 추가 — step-probe 미활성 시 DOM observer 허용 -- **주의**: AG Native UI의 "Running N commands"는 아코디언/그룹 헤더이며, 실제 승인 버튼은 하위 레벨의 "Run"/"Always run"/"Cancel". DOM 구조상 버튼 탐색 시 그룹 헤더를 반드시 스킵해야 함 - -### [2026-04-13] [Extension] HTTP Bridge UTF-8 인코딩 깨짐 — 한글 description 손실 -- **증상**: pending/ 파일의 description 필드에서 한글이 `[AI ]`처럼 깨져서 저장됨. Discord로 전달되는 승인 요청 본문도 깨짐 -- **원인**: Node.js HTTP 서버의 `req.on('data', chunk)` 콜백에서 chunk가 Buffer 타입으로 전달되는데, `body += chunk`로 string 결합 시 Buffer의 기본 인코딩(latin1)이 사용되어 multi-byte UTF-8 문자가 손실됨 -- **해결**: 모든 POST 핸들러(`/pending`, `/dump-html`, `/chat`, `/deep-inspect-result`, `/test-rpc`)에 `req.setEncoding('utf8')` 추가 (v0.5.39) -- **주의**: Node.js HTTP 서버에서 POST body를 문자열로 수집할 때는 반드시 `req.setEncoding('utf8')`을 호출하거나, Buffer를 배열로 모은 후 `Buffer.concat().toString('utf8')`로 변환해야 함 - -### [2026-04-13] [Extension] Observer noise 필터 미작동 — textContent가 아이콘 텍스트를 줄바꿈 없이 합침 -- **증상**: pending description에 `Thought for 1s`, `chevron_right` 등 Material 아이콘명과 UI 노이즈가 그대로 남아있음 -- **원인**: DOM `textContent`는 block 요소 사이에 newline을 삽입하지 않아 `[AI 본문 요약]Thought for 1schevron_right[결행 명령]`처럼 한 줄로 합쳐짐. `cleanLines()`의 줄 단위 noise 필터(`^pattern$`)가 매칭 실패. 또한 `codeText` 추출에는 `cleanLines()`가 아예 미적용 -- **해결**: `cleanLines()`에 인라인 pre-strip 추가 — icon명 18종을 regex로 먼저 `\n`으로 치환 후 줄 단위 필터 적용. `codeText`에도 `cleanLines()` 적용 (v0.5.39) -- **주의**: DOM에서 텍스트 추출 시 `textContent`는 레이아웃 무시, `innerText`는 detached 노드에서 미작동. 노이즈 필터링은 줄 단위뿐 아니라 인라인 패턴 제거도 병행해야 함 - -### [2026-04-13] [Extension] html-patcher String.replace() `$'` 특수 패턴으로 인라인 스크립트 SyntaxError -- **증상**: Observer v8 인라인 스크립트가 workbench.html에 삽입되었으나 렌더러에서 전혀 실행되지 않음 (BEACON 핑 0건). V8 캐시 삭제 + AG 재시작 후에도 동일 -- **원인**: `html-patcher.ts`에서 `html.replace('', '\n' + inlineBlock + '\n')`를 사용. 인라인 스크립트의 NOISE_RE 정규식에 `')$', 'i'`가 있는데, `$'`는 JS `String.replace()`의 특수 대체 패턴(match 뒤의 텍스트)으로 해석됨. 이로 인해 `` 뒤의 원본 HTML 구조(``, `