## 배경
2026-04-07 smoke test 1회차 — EG-BIM Modeler 라이브 환경에서 recorder attach → Box 명령 수동 수행 → player 재생 시도. 결과:
- recorder: 3375 이벤트 → 113 스텝으로 collapse (정상)
- **player가 113개 전부 skip** — target 필드 100% null
- `unresolved_paths=0` 카운터가 거짓 (실제로 해석을 시도하지 않은 경우를 0으로 집계)
단위 테스트는 `IElementSnapshot` fake 기반이라 실제 UIA 호출 경로를 커버하지 못함 — 전형적 integration gap.
## 발견된 gap 4개
| # | 위치 | 문제 |
|---|------|------|
| 1 | recorder | `target` 필드 100% null. UIA resolver가 호출 안 되거나 결과가 버려짐. `unresolved_paths=0` 카운터 부정확 |
| 2 | recorder | `type` value가 문자 아닌 Win32 VK 코드 (예: 162=LCtrl, 67=C) |
| 3 | player | `StepKind` enum에 `Wheel`/`Focus` 누락 → recorder가 쓴 yaml 파싱 실패 |
| 4 | player | target null 시 무조건 (0,0) 클릭/드래그 — 데스크톱 파괴 위험 |
## 수정 요구사항
### recorder
- Win32 hook 이벤트 → 각 이벤트에서 **실제로 UIA resolver를 호출**해 element path와 offset_norm을 채움
- `unresolved_paths` 카운터는 "resolver 호출했으나 null" 케이스만 세는 것이 아니라 "호출 시도했으나 실패"를 명확히 구분
- Key event: Win32 VK 코드를 `KeyInterop.KeyFromVirtualKey` 또는 유사 API로 문자/키명으로 변환. 필요 시 raw VK는 별도 필드로 보존
- integration test 추가 (fake Win32 event stream + fake UIA resolver가 실제 호출됨을 검증)
### player
- `StepKind` enum에 `Wheel`, `Focus` 추가. recorder와 schema 공유 또는 검증 기반 문서화
- target null 스텝은 **안전하게 skip** + warning 로그 (또는 에러 종료 옵션)
- `Wheel`/`Focus` 처리: PoC 수준에서 no-op + 로그, 이후 `IPlayerHost.Wheel(point, delta)` / `IPlayerHost.Focus(uiaPath)` 추가
- Scenario 스키마 단일 소스화(DRY) 방안 제안: 공유 `Recordingtest.Model` 라이브러리로 recorder/player가 같은 DTO 참조
## 사이클
1. Generator 세션 (recorder + player 동시 작업)
2. Evaluator 세션
3. Smoke 2회차 재시도
## 비용 추정
~150~250k tokens (recorder 조사 포함)
Related: #2, #6, #7
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-07 smoke test 1회차 — EG-BIM Modeler 라이브 환경에서 recorder attach → Box 명령 수동 수행 → player 재생 시도. 결과:
unresolved_paths=0카운터가 거짓 (실제로 해석을 시도하지 않은 경우를 0으로 집계)단위 테스트는
IElementSnapshotfake 기반이라 실제 UIA 호출 경로를 커버하지 못함 — 전형적 integration gap.발견된 gap 4개
target필드 100% null. UIA resolver가 호출 안 되거나 결과가 버려짐.unresolved_paths=0카운터 부정확typevalue가 문자 아닌 Win32 VK 코드 (예: 162=LCtrl, 67=C)StepKindenum에Wheel/Focus누락 → recorder가 쓴 yaml 파싱 실패수정 요구사항
recorder
unresolved_paths카운터는 "resolver 호출했으나 null" 케이스만 세는 것이 아니라 "호출 시도했으나 실패"를 명확히 구분KeyInterop.KeyFromVirtualKey또는 유사 API로 문자/키명으로 변환. 필요 시 raw VK는 별도 필드로 보존player
StepKindenum에Wheel,Focus추가. recorder와 schema 공유 또는 검증 기반 문서화Wheel/Focus처리: PoC 수준에서 no-op + 로그, 이후IPlayerHost.Wheel(point, delta)/IPlayerHost.Focus(uiaPath)추가Recordingtest.Model라이브러리로 recorder/player가 같은 DTO 참조사이클
비용 추정
150250k tokens (recorder 조사 포함)Related: #2, #6, #7
Smoke gap fix — Verdict: pass ✅
Generator (
139fbbc)근본 원인: Main 스레드가 MTA여서 UIA3 호출이 조용히 실패 + 키 이벤트의 (0,0) 좌표로 resolver 호출도 null.
[STAThread]누락이 진짜 원인이었음.수정:
[STAThread]추가unresolved_paths/no_resolver_attempt/null_target_stepsKeyTranslator.cs— Win32 VK → 문자/키명 번역 (printable →"BOX", modifier+letter →"ctrl+c")DragCollapser가 printable key 런을 단일type스텝으로 묶음StepKind에Wheel/Focus추가Evaluator — 모든 gap 통과
DragCollapser_PrintableKeys_CollapseIntoSingleTypeStepKeyTranslator.csfull tableValue == "BOX"assertionWheel/Focus추가SmokeRegressionTestsyaml parsePlayerEngine_NullTarget_SkipsWithoutCallingRegression trap 검증:
git show HEAD~1로 이전 코드 vs 새 테스트 assertion 비교 → 모든 새 테스트가 fix 전에 실패함을 확인.테스트: 53 → 60 pass, build 0/0.
비용
다음 단계
Smoke test 2회차 — EG-BIM Modeler에서 Box 명령 재녹화 → 재생. 이번에는 target 필드가 채워지고 "BOX" 문자열이 yaml에 나와야 정상.
closing.