## 배경
2026-04-08 smoke 2회차에서 **첫 E2E 성공** (Box geometry 생성 확인). 상세: `docs/history/2026-04-08_smoke-2회차-첫-e2e-성공.md`.
성공과 함께 발견된 잔여 gap 4개:
## Gap E — `UiaPlayerHost.Hotkey` named key 미지원 ✅ fix 완료
`src/Recordingtest.Player/UiaPlayerHost.cs:Hotkey` switch가 single-char만 처리. `"enter"`, `"tab"`, `"escape"` 등은 default 브랜치에서 길이 체크 실패 → **키 미합성**.
**증상**: type "BOX" 이후 enter hotkey 발동 안 됨 → "BOX10"이 command box에 한 줄로 입력됨 → Box 명령 시작 안 됨.
**Fix** (이미 적용): switch에 `return`, `tab`, `escape`, `space`, `backspace`, `delete`, `home`, `end`, `pageup`/`pagedown`, `up`/`down`/`left`/`right`, `F1-F9` 매핑 추가. smoke 2회차에서 fix 후 Box 생성 성공 확인.
**TODO**: 단위 테스트 추가 + commit.
## Gap F — recorder focus_change 필터 미작동
`automation.RegisterFocusChangedEvent` 콜백이 **시스템 전역** focus 이벤트를 수신. #12 Gap C는 mouse/key에만 WindowFilter 적용, focus는 "UIA 콜백이라 SUT-scoped" 가정했으나 실측은 반대.
**증상**: box-v5.yaml 상단 40+ focus 스텝이 VS Code, PowerShell, Chrome 등 외부 창 path.
**수정**: focus_change 콜백 안에서 element의 ProcessId 확인 후 SUT pid가 아니면 drop.
## Gap G — recorder 뷰포트 클릭이 Console Window로 잡힘
사용자가 SUT 뷰포트 위를 클릭했음에도 `FromPoint(x, y)`가 `ConsoleWindowClass/Text Area` 반환. PowerShell 콘솔이 z-order 상위에 있거나 최근 활성 때문 추정.
**증상**: box-v5.yaml line 512-541 — 뷰포트 코너 클릭이 Console Window path로 저장됨.
**수정 아이디어**:
1. WindowFromPoint HWND가 SUT pid가 아니면 해당 이벤트 drop (이미 Gap C에 부분 구현 → 확장 필요)
2. 또는 SUT hwnd 기준 `ChildWindowFromPointEx` 재귀 검색
## Gap H — cleaned yaml offset 추측값
smoke 2회차에서 cleaned yaml 만들 때 뷰포트 offset을 임의 지정 `(0.35, 0.55)` / `(0.5, 0.35)` — 결과 길쭉한 박스 생성.
**해결**: Gap G 해결되면 자동 해결 (recorder가 뷰포트 호스팅 컨트롤을 정확히 식별).
## 사이클
1. Gap E fix commit (이미 적용, unit test만 추가)
2. Generator: Gap F + G 동시 수정
3. Evaluator
4. smoke 3회차: box-v5.yaml 원본을 거의 그대로 재생 시도
## 비용 추정
~150~200k tokens
Related: #2, #6, #7, #11, #12
Smoke 2의 "BOX10" 한 줄 입력 버그 → enter/tab/arrows 등 named key가 실제 합성됨
yaml 상단 40+ 외부 창 focus 스텝 → SUT pid 기준 드롭
뷰포트 클릭이 Console Window로 잡히는 문제 → WindowPointResolver가 foreign pid 감지 시 SUT-scoped fallback 시도 (pure 로직 검증 완료, 실제 hit-test walker는 partial)
API 주의사항
Generator 서브에이전트 3회 시도 중 2회 즉시 API 529, 3회째는 실질 작업 완료 후 529. Orchestrator가 history/commit 수습. 디스크에 쓰인 중간 산출물이 그대로 사용 가능하여 큰 손실 없음 — 서브에이전트의 부분 작업 보존 동작이 유용함을 실증.
비용
단계
Tokens
Generator 3회 시도 합계
~2.2k (전부 529로 조기 종료, 마지막 시도의 tool 실행 결과만 파일에 남음)
Orchestrator 수습 (build/test/history/commit)
~12k
Evaluator
~40k
합계
~54k
예외적으로 낮은 비용 — Generator가 실질 작업을 파일로 이미 완료했기 때문.
다음 단계
Smoke 3회차 — box-v5.yaml 원본을 거의 그대로 재생 시도. 이번엔 focus 스텝이 SUT path로만 채워지고 뷰포트 클릭이 ConsoleWindowClass로 빠지지 않아야 함.
closing.
## Smoke 2차 gap fix — Verdict: **pass with caveat** ✅
### Commits
- `7db9cd0` — hotkey 즉석 fix + smoke 2 milestone history
- `b139f2b` — Gap E/F/G 정식 refactor + 신규 테스트
### Evaluator DoD
| Gap | 결과 | 증거 |
|-----|------|------|
| E (Hotkey named key) | pass | `ParsedHotkey` record + `ParseHotkey` 추출, `Hotkey()` 재wire, 8 HotkeyParseTests |
| F (focus_change SUT 필터) | pass | `FocusEventFilter.ShouldAccept` + `Program.cs` 콜백 wire (`el.Properties.ProcessId.ValueOrDefault` try/catch), 4 FocusEventFilterTests |
| G (viewport picking fallback) | pass with caveat | `IWindowPointSource` + `WindowPointResolver.Resolve` pure 로직 + 5 fake-backed 테스트. `FlaUiPointSource.GetElementFromSutScope`는 **honest stub** (null 반환), 라이브 검증은 smoke 3회차 과제 |
### 테스트
**77 → 94** (Player 16→24, Recorder 17→26). Build 0/0. Thread.Sleep 0건 유지.
### 핵심 개선점
- **Smoke 2의 "BOX10" 한 줄 입력 버그** → `enter`/`tab`/`arrows` 등 named key가 실제 합성됨
- **yaml 상단 40+ 외부 창 focus 스텝** → SUT pid 기준 드롭
- **뷰포트 클릭이 Console Window로 잡히는 문제** → WindowPointResolver가 foreign pid 감지 시 SUT-scoped fallback 시도 (pure 로직 검증 완료, 실제 hit-test walker는 partial)
### API 주의사항
Generator 서브에이전트 3회 시도 중 2회 즉시 API 529, 3회째는 실질 작업 완료 후 529. Orchestrator가 history/commit 수습. 디스크에 쓰인 중간 산출물이 그대로 사용 가능하여 큰 손실 없음 — 서브에이전트의 부분 작업 보존 동작이 유용함을 실증.
### 비용
| 단계 | Tokens |
|------|--------|
| Generator 3회 시도 합계 | ~2.2k (전부 529로 조기 종료, 마지막 시도의 tool 실행 결과만 파일에 남음) |
| Orchestrator 수습 (build/test/history/commit) | ~12k |
| Evaluator | ~40k |
| **합계** | **~54k** |
예외적으로 낮은 비용 — Generator가 실질 작업을 파일로 이미 완료했기 때문.
### 다음 단계
**Smoke 3회차** — box-v5.yaml 원본을 거의 그대로 재생 시도. 이번엔 focus 스텝이 SUT path로만 채워지고 뷰포트 클릭이 ConsoleWindowClass로 빠지지 않아야 함.
closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
배경
2026-04-08 smoke 2회차에서 첫 E2E 성공 (Box geometry 생성 확인). 상세:
docs/history/2026-04-08_smoke-2회차-첫-e2e-성공.md.성공과 함께 발견된 잔여 gap 4개:
Gap E —
UiaPlayerHost.Hotkeynamed key 미지원 ✅ fix 완료src/Recordingtest.Player/UiaPlayerHost.cs:Hotkeyswitch가 single-char만 처리."enter","tab","escape"등은 default 브랜치에서 길이 체크 실패 → 키 미합성.증상: type "BOX" 이후 enter hotkey 발동 안 됨 → "BOX10"이 command box에 한 줄로 입력됨 → Box 명령 시작 안 됨.
Fix (이미 적용): switch에
return,tab,escape,space,backspace,delete,home,end,pageup/pagedown,up/down/left/right,F1-F9매핑 추가. smoke 2회차에서 fix 후 Box 생성 성공 확인.TODO: 단위 테스트 추가 + commit.
Gap F — recorder focus_change 필터 미작동
automation.RegisterFocusChangedEvent콜백이 시스템 전역 focus 이벤트를 수신. #12 Gap C는 mouse/key에만 WindowFilter 적용, focus는 "UIA 콜백이라 SUT-scoped" 가정했으나 실측은 반대.증상: box-v5.yaml 상단 40+ focus 스텝이 VS Code, PowerShell, Chrome 등 외부 창 path.
수정: focus_change 콜백 안에서 element의 ProcessId 확인 후 SUT pid가 아니면 drop.
Gap G — recorder 뷰포트 클릭이 Console Window로 잡힘
사용자가 SUT 뷰포트 위를 클릭했음에도
FromPoint(x, y)가ConsoleWindowClass/Text Area반환. PowerShell 콘솔이 z-order 상위에 있거나 최근 활성 때문 추정.증상: box-v5.yaml line 512-541 — 뷰포트 코너 클릭이 Console Window path로 저장됨.
수정 아이디어:
ChildWindowFromPointEx재귀 검색Gap H — cleaned yaml offset 추측값
smoke 2회차에서 cleaned yaml 만들 때 뷰포트 offset을 임의 지정
(0.35, 0.55)/(0.5, 0.35)— 결과 길쭉한 박스 생성.해결: Gap G 해결되면 자동 해결 (recorder가 뷰포트 호스팅 컨트롤을 정확히 식별).
사이클
비용 추정
150200k tokensRelated: #2, #6, #7, #11, #12
Smoke 2차 gap fix — Verdict: pass with caveat ✅
Commits
7db9cd0— hotkey 즉석 fix + smoke 2 milestone historyb139f2b— Gap E/F/G 정식 refactor + 신규 테스트Evaluator DoD
ParsedHotkeyrecord +ParseHotkey추출,Hotkey()재wire, 8 HotkeyParseTestsFocusEventFilter.ShouldAccept+Program.cs콜백 wire (el.Properties.ProcessId.ValueOrDefaulttry/catch), 4 FocusEventFilterTestsIWindowPointSource+WindowPointResolver.Resolvepure 로직 + 5 fake-backed 테스트.FlaUiPointSource.GetElementFromSutScope는 honest stub (null 반환), 라이브 검증은 smoke 3회차 과제테스트
77 → 94 (Player 16→24, Recorder 17→26). Build 0/0. Thread.Sleep 0건 유지.
핵심 개선점
enter/tab/arrows등 named key가 실제 합성됨API 주의사항
Generator 서브에이전트 3회 시도 중 2회 즉시 API 529, 3회째는 실질 작업 완료 후 529. Orchestrator가 history/commit 수습. 디스크에 쓰인 중간 산출물이 그대로 사용 가능하여 큰 손실 없음 — 서브에이전트의 부분 작업 보존 동작이 유용함을 실증.
비용
예외적으로 낮은 비용 — Generator가 실질 작업을 파일로 이미 완료했기 때문.
다음 단계
Smoke 3회차 — box-v5.yaml 원본을 거의 그대로 재생 시도. 이번엔 focus 스텝이 SUT path로만 채워지고 뷰포트 클릭이 ConsoleWindowClass로 빠지지 않아야 함.
closing.