Raw 레코딩 시나리오를 수동 cleanup 없이 재생 가능하게 #14

Closed
opened 2026-04-08 18:32:26 +09:00 by kimminsung · 1 comment
Owner

배경

Smoke 2회차 첫 E2E 성공(2026-04-08_smoke-2회차-첫-e2e-성공.md)은 scenarios/box-v5-clean.yaml로 달성했다. 그러나 이는 원본 box-v5.yaml(676줄)을 AI로 수작업 정리해 54줄로 축약한 파일이다. 즉 raw 레코딩 그대로는 재생 불가였던 상태.

이슈 #13에서 root cause 3건을 수정했다:

  • Gap E — Hotkey 매핑 누락 (enter/tab/esc/arrows)
  • Gap F — recorder focus_change 이벤트가 시스템 전역으로 수신되어 VS Code/PowerShell 경로 다수 포함 → FocusEventFilter로 SUT ProcessId 필터
  • Gap G — viewport 클릭이 top-level z-order(ConsoleWindowClass)로 잡힘 → WindowPointResolver SUT scope fallback

목표

box-v5.yaml(cleanup 없이 raw 그대로)을 player로 재생해 Box geometry가 생성되는 것을 검증한다. 성공 시 cleanup 단계를 워크플로우에서 제거할 수 있다.

Definition of Done

  1. 사용자 라이브 환경에서 dotnet run --project src/Recordingtest.Player -- --scenario scenarios/box-v5.yaml --output-dir artifacts/replay-v5-raw --no-launch 실행
  2. SUT에 Box geometry가 생성된다(엔진 상태/저장파일로 확인)
  3. 실패 시 남은 gap을 재분석해 recorder/player 측 fix로 해결 (시나리오 편집이 아닌)

비목표

  • recorder 출력 포맷 변경
  • normalizer 확장

관련

  • #13 (선행 fix)
  • docs/history/2026-04-08_smoke-2회차-첫-e2e-성공.md
  • scenarios/box-v5.yaml (raw, 676줄) vs scenarios/box-v5-clean.yaml (54줄)
## 배경 Smoke 2회차 첫 E2E 성공(`2026-04-08_smoke-2회차-첫-e2e-성공.md`)은 `scenarios/box-v5-clean.yaml`로 달성했다. 그러나 이는 원본 `box-v5.yaml`(676줄)을 AI로 수작업 정리해 54줄로 축약한 파일이다. 즉 **raw 레코딩 그대로는 재생 불가**였던 상태. 이슈 #13에서 root cause 3건을 수정했다: - Gap E — Hotkey 매핑 누락 (enter/tab/esc/arrows) - Gap F — recorder focus_change 이벤트가 시스템 전역으로 수신되어 VS Code/PowerShell 경로 다수 포함 → `FocusEventFilter`로 SUT ProcessId 필터 - Gap G — viewport 클릭이 top-level z-order(ConsoleWindowClass)로 잡힘 → `WindowPointResolver` SUT scope fallback ## 목표 `box-v5.yaml`(**cleanup 없이 raw 그대로**)을 player로 재생해 Box geometry가 생성되는 것을 검증한다. 성공 시 cleanup 단계를 워크플로우에서 제거할 수 있다. ## Definition of Done 1. 사용자 라이브 환경에서 `dotnet run --project src/Recordingtest.Player -- --scenario scenarios/box-v5.yaml --output-dir artifacts/replay-v5-raw --no-launch` 실행 2. SUT에 Box geometry가 생성된다(엔진 상태/저장파일로 확인) 3. 실패 시 남은 gap을 재분석해 recorder/player 측 fix로 해결 (시나리오 편집이 아닌) ## 비목표 - recorder 출력 포맷 변경 - normalizer 확장 ## 관련 - #13 (선행 fix) - `docs/history/2026-04-08_smoke-2회차-첫-e2e-성공.md` - `scenarios/box-v5.yaml` (raw, 676줄) vs `scenarios/box-v5-clean.yaml` (54줄)
Author
Owner

Raw 시나리오 E2E 성공 🎉

scenarios/box-v6.yaml 원본(AI 후처리 없음) → Player 재생 → Box geometry 생성 확인.

해결 방식: recorder를 재공사하는 대신 Player가 record→replay gap을 흡수하도록 포스트프로세싱 추가. (recorder Gap I-1은 follow-up.)

변경 (commit 70bf570)

  • Null-target fallback (PlayerEngine)
    • Type + null → 현재 포커스로 host.Type()
    • Click + null + raw_coord → screen-absolute 좌표로 클릭
    • Step.RawCoord 필드 추가
  • SUT foreground 강제UiaPlayerHost.BringSutToForeground() (SetForeground + Focus + 600ms settle) — 재생 시작 전 1회
  • 선두 alt+tab 자동 skip — 녹화 startup 노이즈
  • 스텝 간 타이밍 보존Step.Ts + IPlayerHost.Delay (150ms~3s 클램프). 엔진 내부 Thread.Sleep 금지 DoD 유지하려 host로 위임
  • 스텝별 console 로그

라이브 결과

[player] info: skipping leading alt+tab step 0 (issue #14)
[player] info: skipping leading alt+tab step 1 (issue #14)
[player] step 2 kind=Type value=BOX
[player] step 3 kind=Hotkey value=enter
[player] step 4 kind=Click value=
[player] info: step 4 kind=Click null target — using raw_coord (338,593) (issue #14)
[player] step 5 kind=Click value=
[player] info: step 5 kind=Click null target — using raw_coord (1149,372) (issue #14)
[player] step 6 kind=Type value=10
[player] step 7 kind=Hotkey value=enter
...

1차 시도 실패 / 2차 성공. foreground settle이 경계선(600ms) — 1차에 "BOX" 타이핑이 부분 누락됨. Follow-up 등록.

Follow-up

  • foreground 안정화: GetForegroundWindow == sut_hwnd 능동 대기 또는 Keyboard warm-up. PLAN.md P1.
  • recorder Gap I-1: null_target_steps 근본 해결 — key_down 시 Automation.FocusedElement 직접 쿼리해 typeRes 채우기. PLAN.md P1.

토큰 사용량

  • 단일 세션 (Opus 4.6, 1M context)
  • Orchestrator (본 세션): 약 60k tokens
  • Generator / Evaluator 분리 없이 직접 구현 — 변경 범위가 작고 추가 테스트로 검증 가능한 범위라 정식 Sprint Contract 생략

DoD 달성도

  1. Raw box-v6.yaml 재생 명령 실행
  2. SUT에 Box geometry 생성 ✓ (2차 시도)
  3. 시나리오 편집 없이 해결 ✓ (recorder는 이번 수정 없음, player만)

Close 가능 — 안정화 follow-up은 별개 이슈로 추적.

## Raw 시나리오 E2E 성공 🎉 `scenarios/box-v6.yaml` 원본(AI 후처리 없음) → Player 재생 → Box geometry 생성 확인. **해결 방식**: recorder를 재공사하는 대신 Player가 record→replay gap을 흡수하도록 포스트프로세싱 추가. (recorder Gap I-1은 follow-up.) ### 변경 (commit `70bf570`) - **Null-target fallback** (PlayerEngine) - Type + null → 현재 포커스로 `host.Type()` - Click + null + raw_coord → screen-absolute 좌표로 클릭 - `Step.RawCoord` 필드 추가 - **SUT foreground 강제** — `UiaPlayerHost.BringSutToForeground()` (`SetForeground + Focus + 600ms settle`) — 재생 시작 전 1회 - **선두 alt+tab 자동 skip** — 녹화 startup 노이즈 - **스텝 간 타이밍 보존** — `Step.Ts` + `IPlayerHost.Delay` (150ms~3s 클램프). 엔진 내부 `Thread.Sleep` 금지 DoD 유지하려 host로 위임 - **스텝별 console 로그** ### 라이브 결과 ``` [player] info: skipping leading alt+tab step 0 (issue #14) [player] info: skipping leading alt+tab step 1 (issue #14) [player] step 2 kind=Type value=BOX [player] step 3 kind=Hotkey value=enter [player] step 4 kind=Click value= [player] info: step 4 kind=Click null target — using raw_coord (338,593) (issue #14) [player] step 5 kind=Click value= [player] info: step 5 kind=Click null target — using raw_coord (1149,372) (issue #14) [player] step 6 kind=Type value=10 [player] step 7 kind=Hotkey value=enter ... ``` **1차 시도 실패 / 2차 성공.** foreground settle이 경계선(600ms) — 1차에 "BOX" 타이핑이 부분 누락됨. Follow-up 등록. ### Follow-up - **foreground 안정화**: `GetForegroundWindow == sut_hwnd` 능동 대기 또는 Keyboard warm-up. PLAN.md P1. - **recorder Gap I-1**: null_target_steps 근본 해결 — key_down 시 `Automation.FocusedElement` 직접 쿼리해 typeRes 채우기. PLAN.md P1. ### 토큰 사용량 - 단일 세션 (Opus 4.6, 1M context) - Orchestrator (본 세션): 약 60k tokens - Generator / Evaluator 분리 없이 직접 구현 — 변경 범위가 작고 추가 테스트로 검증 가능한 범위라 정식 Sprint Contract 생략 ### DoD 달성도 1. ~~Raw box-v6.yaml 재생 명령 실행~~ ✓ 2. ~~SUT에 Box geometry 생성~~ ✓ (2차 시도) 3. ~~시나리오 편집 없이 해결~~ ✓ (recorder는 이번 수정 없음, player만) Close 가능 — 안정화 follow-up은 별개 이슈로 추적.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kimminsung/recordingtest#14