minsung f6b6e7449e 3-tier split (step 1) + engine-bridge v3 scaffold + HmegDirectStateProvider
Lays down the Generic / HmEG-aware / App-specific separation that lets us
target other HmEG-hosting WPF applications later, and lands the v3 engine
state provider on top of it.

Architecture rule (CLAUDE.md §8.1, new): every module belongs to exactly one
of three tiers — Generic / HmEG-aware / App-specific (e.g. EgBim). Dependency
direction is strictly App-specific → HmEG-aware → Generic. Generic must not
reference HmEG.dll; HmEG-aware must not reference any per-app assembly.

This commit is the first incremental step:

  + src/Recordingtest.Bridge.Abstractions/  (Generic, new csproj)
      IEngineStateProvider, CameraSnapshot, SceneSnapshot,
      NullEngineStateProvider — extracted from EgPlugin so the generic core
      owns the contract. Zero SUT references.

  + src/Hmeg/Recordingtest.Hmeg.Bridge/      (HmEG-aware, new csproj)
      HmegDirectStateProvider — IEngineStateProvider implemented against
      the HmEG public API (Space, HmEGViewport, ISelectable, ModelBase.Uid).
      Decoupled from any specific host app via Func<Space?>/Func<HmEGViewport?>
      lambdas; the EgBim plugin host supplies them. Reusable for any other
      WPF application that hosts HmEG.

      Selection traversal walks Space.Children and collects ModelBase.Uid
      for nodes whose ISelectable.IsSelected is true. We deliberately type
      nodes as object + late-bound Uid lookup to avoid pulling MemoryPack
      into the dependency graph.

  + tests/Hmeg/Recordingtest.Hmeg.Bridge.Tests/
      5 unit tests covering null lambdas, throwing lambdas, document path
      provider, and constructor null arg validation.

  + src/Recordingtest.EgPlugin/ChainedEngineStateProvider.cs
      Wraps two providers; falls back from Hmeg.Direct to the existing
      Reflection accessor when the primary returns empty/default. Lets us
      land the new wire-up before the EgBim adapter Q1~Q7 lookups are
      filled in. 7 new tests.

  + src/Recordingtest.EgPlugin/IAppManagerAccessor.cs
      Reflection accessor abstraction (preserved as the v3 fallback). Looks
      up Editor.AppManager.AppManager via well-known Instance/Current
      property names. Unit-testable through a fake.

  ~ src/Recordingtest.EgPlugin/IEngineStateProvider.cs
      Type definitions removed (now in Bridge.Abstractions); only the
      reflection-based provider remains. ReflectionEngineStateProvider
      delegates everything to IAppManagerAccessor.

  ~ src/Recordingtest.EgPlugin/HmEgBridgePlugin.cs
      BuildProvider() picks ChainedEngineStateProvider(Hmeg.Direct,
      Reflection). The HmEG-aware lambdas are stubs (return null) until the
      next step wires the EgBim adapter; the chain falls through to the
      reflection path so behaviour matches v2 for now.

  + docs/contracts/engine-bridge-v3.md       — Sprint Contract
  + docs/contracts/generic-sut-split.md      — Sprint Contract for the
      remaining mass-rename / folder move (step 2, deferred).
  + docs/hmeg-api-survey.md                  — Read-only survey of the HmEG
      public API (Space, ModelBase, HmEGViewport, IHmCamera, IPlugin) used
      to design HmegDirectStateProvider. Open Q1~Q7 listed.

Tests: 94 → 115 passing, 0 failing. The new HmEG-aware test project copies
HmEG.dll next to its output (Private=true) since it runs out-of-process.

Step 2 (deferred to next session): mass-rename
  src/Recordingtest.EgPlugin → src/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost + .Adapter
  src/Recordingtest.EngineBridge → src/Hmeg/Recordingtest.Hmeg.Catalog
  src/Recordingtest.EngineBridge.Client → split (Generic + Hmeg)
plus Recordingtest.Architecture.Tests to enforce the §8.1 dependency rule.

Ref: #10 follow-up, #14 follow-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 09:53:27 +09:00
2026-04-07 20:35:45 +09:00
2026-04-07 20:35:45 +09:00

recordingtest

사내 WPF 3D 편집 응용(자체 엔진 HmEG, MEF plugin 아키텍처)에 대한 사용자 입력 회귀 테스트 자동화 도구. 도구 자체이지 SUT가 아니다. 자세한 운영 지침은 CLAUDE.md, 현재 진행 상태는 PROGRESS.md, 다음 할 일은 PLAN.md를 참고.

핵심 전략 — Golden-file 회귀

수동 테스트 입력을 레코딩 → 리플레이 → 결과 저장 파일을 정규화 후 baseline과 diff. ApprovalTests 패턴과 동형이며 SUT 코드 변경 협조를 최소화하기 위한 의도적 선택이다.

[수동 테스트] → 입력 레코드 + 결과 파일 A (approved baseline)
[회귀 시점]   → 입력 리플레이 → 결과 파일 B → normalize → diff(A, B)

모듈 구성

모듈 책임 상태
Recordingtest.SutProber SUT 정적 probe (plugin/Json/assembly 카탈로그) PoC pass
Recordingtest.Recorder 입력 캡처 (UIA element path + offset + 키/마우스/포커스) PoC pass
Recordingtest.Player 시나리오 재생, 비동기 동기화 PoC pass
Recordingtest.Normalizer 결과 파일 정규화 (timestamp/GUID/path/float/order) PoC pass
Recordingtest.DiffReporter approved vs received diff 리포트 PoC pass
Recordingtest.EngineBridge.Client + Recordingtest.EgPlugin HmEG 내부 상태 sidecar (MEF plugin masquerade + HttpListener) v2 pass
Recordingtest.Runner 5-모듈 E2E 파이프라인 + 실패 triage PoC pass

작업 사이클 — Planner / Generator / Evaluator

Anthropic harness design 원칙을 채택. 같은 에이전트가 생성과 평가를 겸하지 않는다.

  1. /contract <name> — Sprint Contract 작성 (docs/contracts/<name>.md, 검증 가능한 DoD)
  2. Generator — 계약 기준으로 구현
  3. /evaluate <name> — 독립 evaluator가 채점, pass 시에만 PROGRESS.md 갱신

기술 스택

  • 언어: C# / .NET (SUT와 동일 생태계)
  • UI 자동화: FlaUI 1순위, Win32 low-level hook hybrid
  • 시나리오 포맷: YAML/JSON (git diff 친화적)
  • 베이스라인: *.approved.{ext} / *.received.{ext}

디렉터리

recordingtest/
├── src/                # 모듈별 C# 프로젝트
├── scenarios/          # 시나리오 YAML
├── docs/
│   ├── contracts/      # Sprint Contracts + evaluations
│   ├── history/        # 작업 히스토리
│   ├── sut-catalog/    # sut-prober 산출물
│   └── guides/         # smoke test, deploy 가이드
├── CLAUDE.md           # 에이전트 운영 지침
├── PROGRESS.md         # 완료 상태
└── PLAN.md             # 우선순위 큐

저장소

Description
WPF Application User Input Regression Test
Readme 1 MiB
Languages
C# 93.2%
Python 4.6%
Shell 1.4%
Batchfile 0.8%