Files
recordingtest/docs/history/2026-04-08_이슈13-smoke3-fix-generator.md
minsung b139f2b169 Fix smoke 2차 gaps: hotkey tests, focus filter, viewport picking (#13)
Gap E — Hotkey named key
- UiaPlayerHost: extract ParsedHotkey record + ParseHotkey static
- HotkeyParseTests: 8 tests (enter/tab/a/ctrl+c/ctrl+shift+s/f5/alt+f4/empty)

Gap F — recorder focus_change SUT filter
- FocusEventFilter.ShouldAccept static rule (same/zero/unknown/unknown-sut)
- Program.cs wires it inside RegisterFocusChangedEvent callback
- FocusEventFilterTests: 4 tests

Gap G — viewport picking foreign-process fallback
- IWindowPointSource + WindowPointResolver pure resolver
- FlaUiPointSource wired in Program.cs (best-effort hit test, honest partial for live SUT)
- WindowPointResolverTests: 5 tests

Tests: 77 → 94, build 0/0 (TreatWarningsAsErrors preserved).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 18:21:36 +09:00

3.8 KiB

2026-04-08 이슈 #13 — smoke 2차 gap fix (Generator + orchestrator 수습)

  • 이슈: #13
  • 소요 시간: ~40분 (Generator 3회 시도 중 첫 2번 API 529 overload, 3번째가 실질 완료 후 529로 종료되어 orchestrator가 history/commit만 수습)
  • Context 사용량: ~500k tokens (orchestrator 누적)

요약

Smoke 2회차 후속 4개 gap 중 E/F/G 수정. Generator 서브에이전트가 세 번째 시도에서 약 30회 tool 호출 후 Anthropic API 529 overload로 조기 종료되었으나, 실제 코드 작성은 사실상 완료된 상태였음. Orchestrator가 빌드/테스트 검증 후 history/commit 단계만 수습.

수정 내역

Gap E — Hotkey named key (단위 테스트 추가)

src/Recordingtest.Player/UiaPlayerHost.cs:

  • internal sealed record ParsedHotkey(IReadOnlyList<VirtualKeyShort> Modifiers, VirtualKeyShort? Main) 신규
  • internal static ParsedHotkey ParseHotkey(string keys) 메서드로 기존 switch body 추출
  • Hotkey(string keys) 는 이제 ParseHotkey 호출 후 press/release만 수행
  • 신규 테스트: tests/Recordingtest.Player.Tests/HotkeyParseTests.cs8 tests (enter/tab/a/ctrl+c/ctrl+shift+s/f5/alt+f4/empty)

Gap F — recorder focus_change SUT 필터

src/Recordingtest.Recorder/FocusEventFilter.cs 신규:

public static bool ShouldAccept(int candidatePid, int sutPid) {
    if (sutPid <= 0) return true;       // unknown SUT: permissive
    if (candidatePid <= 0) return false; // unknown element pid: drop
    return candidatePid == sutPid;
}

Program.csautomation.RegisterFocusChangedEvent 콜백에서 element.ProcessId 확인 후 FocusEventFilter.ShouldAccept 호출 — false면 큐 쓰기 skip.

신규 테스트: tests/Recordingtest.Recorder.Tests/FocusEventFilterTests.cs4 tests (same/different/unknownCandidate/unknownSut)

Gap G — viewport picking foreign-process fallback

src/Recordingtest.Recorder/WindowPointResolver.cs 신규:

  • IWindowPointSource 인터페이스 (GetProcessIdAt, GetElementAt, GetElementFromSutScope)
  • WindowPointResolver.Resolve(source, x, y, sutPid) — primary element의 process가 SUT가 아니면 SUT-scoped fallback 시도, fallback null이면 primary 유지 (last resort)

Program.cs 내부 FlaUiPointSource 구현체로 wire. GetElementFromSutScope는 현재 mainWindow 기반 best-effort hit-test (라이브 SUT 없이 완전 검증 불가 → honest partial).

신규 테스트: tests/Recordingtest.Recorder.Tests/WindowPointResolverTests.cs5 tests (samePid/differentPid/unknownPid/zeroPid/fallbackNull)

테스트 결과

프로젝트 Before After
Player.Tests 16 24
Recorder.Tests 17 26
기타 변경 없음
합계 77 94

Build: 0 warn / 0 err. 모든 테스트 green.

Honest partial — Gap G

FlaUiPointSource.GetElementFromSutScope는 라이브 SUT 환경에서만 완전 검증 가능. Pure WindowPointResolver 로직은 fake-backed로 완전히 테스트됨. smoke 3회차에서 실환경 검증 예정.

Regression trap

  • HotkeyParseTests: 각 테스트가 pre-refactor의 p.Length == 1 체크만으로는 실패 — named key entries 필수
  • FocusEventFilterTests: 기존 Program.cs에는 이 static이 없었으므로 compile trap
  • WindowPointResolverTests: 기존에 없던 새 타입 → compile trap + behavior assertion

커밋 (wip)

Generator가 커밋 전 529로 터져서 orchestrator가 대신 커밋.

Anthropic API 주의

3회 연속 시도 중 2회 즉시 529, 3회째는 작업 거의 완료 후 529로 종료. 서브에이전트 세션의 "중단 후 부분 작업 보존" 동작이 유용함을 실증 — 파일이 디스크에 이미 쓰인 상태라 orchestrator가 이어받아 마무리 가능.