docs: compress CLAUDE.md, extract architecture layout to docs/architecture.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
265
CLAUDE.md
265
CLAUDE.md
@@ -1,254 +1,59 @@
|
||||
# CLAUDE.md — recordingtest
|
||||
|
||||
이 파일은 Claude Code가 본 저장소에서 작업할 때 항상 읽는 프로젝트 운영 지침이다.
|
||||
## 세션 시작 (필수)
|
||||
|
||||
## 0. 세션 시작 시 필독 (모든 에이전트)
|
||||
1. [PROGRESS.md](PROGRESS.md) 읽기 — 완료/진행 중/차단 현황
|
||||
2. [PLAN.md](PLAN.md) 읽기 — 다음 할 일 우선순위 큐
|
||||
3. 작업 선택 → PROGRESS.md "In progress" 표시
|
||||
4. 완료 시: PROGRESS.md Done 이동 + PLAN.md 갱신 + `docs/history/YYYY-MM-DD_{작업명}.md` 작성 (소요시간·Context 사용량 필수, 누락 시 커밋 차단)
|
||||
|
||||
여러 에이전트가 작업을 분담하므로, **세션을 시작하는 모든 에이전트는 가장 먼저 다음 두 파일을 읽는다:**
|
||||
## 작업 사이클 — Planner / Generator / Evaluator
|
||||
|
||||
1. [PROGRESS.md](PROGRESS.md) — 지금까지 *무엇이 끝났는가*. 모듈별 진행 상태, 최근 완료 작업, 현재 차단 이슈.
|
||||
2. [PLAN.md](PLAN.md) — 앞으로 *무엇을 해야 하는가*. 모듈별 To-Do, 담당 에이전트, 우선순위, 의존 관계.
|
||||
비자명한 작업은 반드시 3단계:
|
||||
|
||||
읽고 나서 자신이 맡을 작업을 PLAN.md에서 고르고, 시작 시 PROGRESS.md에 "in progress"로 표시한다. 작업이 끝나면:
|
||||
- PROGRESS.md 의 해당 항목을 "done"으로 옮기고 날짜·결과·산출물 경로 기록
|
||||
- PLAN.md 의 완료 항목 제거 또는 다음 단계로 갱신
|
||||
- `docs/history/YYYY-MM-DD_{작업명}.md` 히스토리 파일 작성 (소요 시간·Context 사용량 필수)
|
||||
1. `/contract <name>` → `docs/contracts/<name>.md` (Goal, DoD, Interfaces, Risks)
|
||||
2. Generator — DoD만 충족, 스코프 이탈 금지
|
||||
3. `/evaluate <name>` → `docs/contracts/<name>.evaluation.md` — **pass여야만** PROGRESS.md Done 이동
|
||||
|
||||
**원칙:** PROGRESS.md와 PLAN.md는 *에이전트 간 공유 메모리*다. 자기 머릿속에만 두지 말고 반드시 파일에 반영해야 다음 에이전트가 이어받을 수 있다. 충돌 시 최신 커밋 기준으로 머지하고, 모호하면 사용자에게 질문한다.
|
||||
**Generator와 Evaluator는 같은 세션이 겸하지 않는다.**
|
||||
|
||||
## 0.1 작업 사이클 — Planner → Generator → Evaluator
|
||||
컨텍스트가 차면 요약 말고 **파일에 상태를 쏟고 새 세션으로 리셋**.
|
||||
|
||||
Anthropic의 "Harness Design for Long-Running Agent Applications" 설계 원칙을 채택한다.
|
||||
핵심: **생성자와 평가자를 같은 에이전트가 겸하지 않는다**. 자기 작업을 과대평가하는 편향을 피하기 위해서다.
|
||||
## 프로젝트
|
||||
|
||||
모든 비자명한(non-trivial) 모듈/기능 작업은 다음 3단계를 거친다:
|
||||
**recordingtest** — WPF 3D 편집기(EG-BIM Modeler, HmEG 엔진, MEF 플러그인)에 대한 입력 회귀 테스트 자동화 도구.
|
||||
|
||||
1. **Planner (`/contract <name>`)** — 사용자의 요청을 Sprint Contract로 변환.
|
||||
- 산출물: `docs/contracts/<name>.md` (Goal, **Definition of Done**, Interfaces, Out of scope, Evaluation plan, Risks)
|
||||
- DoD 항목은 **객관적으로 검증 가능**해야 한다. "잘 동작한다"는 금지.
|
||||
- `PLAN.md`에 해당 항목 추가.
|
||||
전략: 입력 레코딩 → 리플레이 → 결과물을 `*.approved.*` 베이스라인과 diff (ApprovalTests 패턴).
|
||||
|
||||
2. **Generator** — Sprint Contract를 계약으로 삼고 실제 구현. 일반 세션 또는 전용 구현 에이전트가 수행.
|
||||
- 계약을 읽고 DoD 항목만 충족시키는 데 집중.
|
||||
- 스코프 이탈 금지. 범위 변경이 필요하면 planner를 다시 호출.
|
||||
## 코드 계층 (의무)
|
||||
|
||||
3. **Evaluator (`/evaluate <name>`)** — 독립된 `evaluator` 서브에이전트가 계약 기준으로 채점.
|
||||
- 산출물: `docs/contracts/<name>.evaluation.md` (verdict + evidence table)
|
||||
- **fail**이면 PROGRESS.md에 done으로 옮기지 않는다. Generator가 재작업.
|
||||
- **pass**여야만 호출자가 PROGRESS.md를 갱신한다.
|
||||
|
||||
### 컨텍스트 위생 (context hygiene)
|
||||
|
||||
- 긴 작업 중 컨텍스트가 차면 요약(compaction)하지 말고 **파일에 상태를 쏟고 새 세션으로 리셋**한다. PROGRESS.md/PLAN.md/Sprint Contract가 그 인계 창구다.
|
||||
- Stop hook이 핸드오프 누락을 경고한다. 무시하지 말 것.
|
||||
- 모델/하네스가 진화하므로 `.claude/` 비계는 주기적으로 감사·축소한다 (PLAN.md에 "scaffolding review" 상시 항목 유지).
|
||||
|
||||
## 1. 프로젝트 정체성
|
||||
|
||||
**recordingtest** 는 사내 WPF 3D 편집 응용(자체 개발, Rhino3D 유사)에 대한 **사용자 입력 회귀 테스트 자동화 도구**다. 도구 자체이지 SUT가 아니다.
|
||||
|
||||
### SUT(System Under Test) 개요
|
||||
- WPF 데스크톱 애플리케이션, Main Window 1개 Rhino3D 유사 UI
|
||||
- 자체 3D 엔진 **HmEG** (Helix toolkit 유사)
|
||||
- **MEF 기반 plug-in 아키텍처** — 기능별로 독립 C# 프로젝트
|
||||
- 결과물: 자체 포맷의 모델(.hmeg)/프로젝트 저장 파일
|
||||
|
||||
## 2. 핵심 전략 — Golden-file 회귀
|
||||
|
||||
> 수동 테스트 입력을 레코딩 → 리플레이 → 결과 저장 파일을 베이스라인과 diff.
|
||||
|
||||
ApprovalTests 패턴과 동형. SUT 코드 변경 협조를 최소화하기 위한 의도적 선택.
|
||||
3개 계층, 단방향 의존:
|
||||
|
||||
```
|
||||
[수동 테스트] → 입력 레코드 + 결과 파일 A (baseline)
|
||||
[회귀 시점] → 입력 리플레이 → 결과 파일 B → normalize → diff(A, B)
|
||||
App-specific (Sut/EgBim/) → HmEG-aware (Hmeg/) → Generic (src/ 직속)
|
||||
```
|
||||
|
||||
**우선순위:**
|
||||
- 1순위: recorder, player, 정규화(normalizer), diff-reporter
|
||||
- 2순위: engine-bridge (엔진 상태 sidecar JSON 덤프)
|
||||
- 후순위: viewport-verifier (픽셀/이미지 비교) — golden-file로 못 잡는 케이스 보강용
|
||||
|
||||
## 3. 아키텍처 구성요소(예정)
|
||||
|
||||
| 모듈 | 책임 |
|
||||
|------|------|
|
||||
| `sut-prober` | 대상 앱 실행, UIA 트리·MEF plugin 목록 덤프 |
|
||||
| `recorder` | 입력 캡처(키/마우스/포커스) + element path + offset 동시 저장 |
|
||||
| `player` | 시나리오 재생, 비동기 작업 동기화 |
|
||||
| `normalizer` | 저장 파일 정규화(타임스탬프/GUID/경로/부동소수점/순서) |
|
||||
| `diff-reporter` | baseline vs received diff, 갈라진 지점 시각화 |
|
||||
| `engine-bridge` | HmEG 내부 상태(카메라/선택/씬그래프) sidecar JSON 노출 |
|
||||
| `test-runner` | 시나리오 묶음 실행, 리포트 |
|
||||
| `viewport-verifier` | (후순위) 3D 스크린샷 SSIM 비교 |
|
||||
|
||||
각 모듈은 독립 PoC → 통합 순서로 진행한다.
|
||||
|
||||
## 4. 기술 스택 가이드
|
||||
|
||||
- **언어**: C# / .NET (SUT와 동일 생태계, in-process probe 가능)
|
||||
- **UI 자동화**: **FlaUI** 1순위 (UIA 기반, .NET 네이티브). WinAppDriver/Appium은 fallback.
|
||||
- **저수준 입력**: Win32 SetWindowsHookEx (low-level mouse/keyboard) — element 매칭과 hybrid
|
||||
- **시나리오 포맷**: JSON 또는 YAML (git diff 친화적). 바이너리 금지.
|
||||
- **베이스라인 파일**: `*.approved.{ext}` / `*.received.{ext}` 명명 규칙
|
||||
- **이미지/큰 베이스라인**: Git LFS
|
||||
|
||||
## 5. 반드시 지킬 설계 원칙
|
||||
|
||||
1. **결정성(Determinism) 우선** — 비결정적 요소(시각·랜덤·경로·GUID·부동소수점·컬렉션 순서)는 정규화 파이프라인을 통과해야 한다. 새 필드 추가 시 정규화 규칙 동시 등록.
|
||||
2. **Element-aware 입력 캡처** — 좌표만 저장 금지. 항상 UIA element path + 상대 offset을 같이 기록해 해상도/DPI/창크기 변화에 견디게 한다.
|
||||
3. **타이밍 동기화** — 고정 sleep 금지. UIA 이벤트, property 변경, plugin 로드 완료 신호를 대기한다.
|
||||
4. **Dispatcher marshaling** — SUT 내부 probe/hook 코드는 반드시 WPF UI thread 위에서 동작.
|
||||
5. **체크포인트** — 한 시나리오 안에서 여러 번 저장→비교 가능해야 한다(이분 탐색용).
|
||||
6. **실패 아티팩트 풀세트** — 실패 시 스크린샷, UIA 트리 덤프, 엔진 상태 sidecar, 입력 로그, diff를 한 폴더에 동시 저장.
|
||||
7. **SUT 침습 최소화** — AutomationPeer/probe 부착이 필요하면 별도 어셈블리로 격리하고 SUT 팀과 합의 후 진행.
|
||||
8. **민감정보 마스킹** — 레코딩에 비밀번호/토큰 포함 금지.
|
||||
|
||||
## 6. 환경 제약
|
||||
|
||||
- **세션 0 불가**: WPF는 대화형 데스크톱 세션 필요 → CI에서 헤드리스 불가, RDP/대화형 agent 필요
|
||||
- **DPI/멀티모니터 정규화**: 테스트 머신은 고정 DPI 권장
|
||||
- **GPU 의존**: 3D 렌더 결과는 드라이버 영향 → 픽셀 비교는 항상 톨러런스 + 마스킹
|
||||
|
||||
## 7. 작업 흐름 규칙
|
||||
|
||||
### 히스토리 기록 (필수)
|
||||
모든 작업 완료 시 `docs/history/YYYY-MM-DD_{작업명}.md` 작성. 필수 항목:
|
||||
- **소요 시간**
|
||||
- **Context 사용량**
|
||||
- 관련 이슈 (#N)
|
||||
|
||||
누락 시 저장이 차단된다.
|
||||
|
||||
### 저장소
|
||||
- Origin: https://gitea.hmac.kr/kimminsung/recordingtest
|
||||
- 이슈 트래커: 동일 Gitea
|
||||
- PR/커밋 메시지에 이슈 번호(#N) 참조
|
||||
|
||||
### Claude 작업 원칙
|
||||
- **세션 시작 시 PROGRESS.md / PLAN.md 먼저 읽기** (§0 참조)
|
||||
- 코드 변경 전 관련 파일 read 필수
|
||||
- 테스트 자동화 도구 자체의 회귀를 위해 본 저장소 코드도 단위 테스트 보유 권장
|
||||
- 의존성 추가는 사전에 사용자 확인
|
||||
- 메모리 시스템(`~/.claude/projects/.../memory/`)에 프로젝트 진행 상태/전략 결정 보존
|
||||
- 작업 종료 시 PROGRESS.md / PLAN.md 업데이트 + 히스토리 파일 작성 (3종 세트)
|
||||
|
||||
## 8. 디렉터리 구조 (예정 — 셋업 시 확정)
|
||||
|
||||
```
|
||||
recordingtest/
|
||||
├── src/
|
||||
│ ├── Recordingtest.Recorder/
|
||||
│ ├── Recordingtest.Player/
|
||||
│ ├── Recordingtest.Normalizer/
|
||||
│ ├── Recordingtest.DiffReporter/
|
||||
│ ├── Recordingtest.EngineBridge/
|
||||
│ ├── Recordingtest.SutProber/
|
||||
│ └── Recordingtest.Runner/
|
||||
├── tests/
|
||||
├── scenarios/ # 시나리오 JSON/YAML
|
||||
├── baselines/ # *.approved.* (LFS 후보)
|
||||
├── docs/
|
||||
│ ├── history/ # 작업 히스토리
|
||||
│ ├── contracts/ # Sprint Contracts + evaluations
|
||||
│ └── sut-catalog/ # sut-explorer 산출물
|
||||
├── PROGRESS.md
|
||||
├── PLAN.md
|
||||
└── CLAUDE.md
|
||||
```
|
||||
|
||||
## 9. 비목표 (Out of Scope)
|
||||
|
||||
- SUT 자체의 기능 변경/버그 수정
|
||||
- 일반 웹/모바일 자동화
|
||||
- 부하·성능 테스트
|
||||
- 단위 테스트 프레임워크 대체
|
||||
|
||||
## 8.1 코드 계층 분리 (의무 규칙)
|
||||
|
||||
본 도구는 **EG-BIM Modeler 외에도 다양한 WPF 응용**을 회귀 자동화 대상으로 삼는다. 또한 사용자 WPF 응용군의 **대다수가 자체 3D 엔진 `HmEG`를 공유**한다. 따라서 코드는 다음 **3개 계층** 중 하나에 명시적으로 속한다.
|
||||
|
||||
| 계층 | 의미 | 의존 가능 | 폴더/네이밍 |
|
||||
| 계층 | 참조 가능 | 위치 | 네임스페이스 |
|
||||
|---|---|---|---|
|
||||
| **Generic** | 임의 WPF 데스크톱 응용에 동작 | .NET BCL, FlaUI/UIA3, Win32, YamlDotNet 등 SUT-중립 라이브러리만 | `src/` 직속, 네임스페이스 `Recordingtest.*` |
|
||||
| **HmEG-aware** | HmEG 엔진을 호스팅하는 임의 WPF 응용에 동작 (앱은 고정 안 됨) | Generic + `HmEG.dll` 만 | `src/Hmeg/` 하위, 네임스페이스 `Recordingtest.Hmeg.*` |
|
||||
| **App-specific** | 특정 응용(예: EG-BIM Modeler)에만 동작 | Generic + HmEG-aware + 해당 앱 어셈블리 (`Editor03.PluginInterface.dll` 등) | `src/Sut/<AppName>/` 하위, 네임스페이스 `Recordingtest.Sut.<AppName>.*` |
|
||||
| Generic | .NET BCL, FlaUI, Win32, YAML만 | `src/` | `Recordingtest.*` |
|
||||
| HmEG-aware | Generic + HmEG.dll만 | `src/Hmeg/` | `Recordingtest.Hmeg.*` |
|
||||
| App-specific | Generic + HmEG-aware + 앱 어셈블리 | `src/Sut/<App>/` | `Recordingtest.Sut.<App>.*` |
|
||||
|
||||
### 의존 방향 (단방향)
|
||||
역참조 금지. `Recordingtest.Architecture.Tests` 가 의존 그래프를 자동 검증한다.
|
||||
|
||||
```
|
||||
App-specific ──→ HmEG-aware ──→ Generic
|
||||
(e.g. EgBim) (e.g. HmegBridge) (Recorder/Player/...)
|
||||
```
|
||||
계층 이동·신규 SUT 추가 시 `/contract` 필수. 폴더 레이아웃: [docs/architecture.md](docs/architecture.md)
|
||||
|
||||
역참조 금지: Generic은 HmEG-aware/App-specific을 모름. HmEG-aware는 App-specific을 모름.
|
||||
## 설계 규칙
|
||||
|
||||
### 강제 사항
|
||||
- **고정 sleep 금지** — UIA 이벤트/property change 대기
|
||||
- **좌표만 저장 금지** — UIA element path + 상대 offset 필수 기록
|
||||
- **새 필드 추가 시 정규화 규칙 동시 등록**
|
||||
- **SUT in-process 코드는 WPF UI thread에서 실행**
|
||||
- 베이스라인 명명: `*.approved.*` / `*.received.*`
|
||||
- 실패 아티팩트: 스크린샷 + UIA 트리 + sidecar JSON + diff를 한 폴더에
|
||||
|
||||
1. **Generic 코드는 어떤 SUT 어셈블리도 참조하지 않는다.** `HmEG.dll`도 안 됨.
|
||||
2. **HmEG-aware 코드는 `HmEG.dll`만 참조**한다. 특정 앱(`Editor03.PluginInterface.dll` 등)은 참조 금지.
|
||||
3. **App-specific 코드만이 자기 앱의 어셈블리를 참조**한다.
|
||||
4. **확장 지점은 항상 한 계층 아래에 인터페이스로 둔다.** 예:
|
||||
- `IEngineStateProvider` (Generic) ← `HmegEngineStateProvider` (HmEG-aware) ← `EgBimAppManagerAdapter` (App-specific 진입점만 제공)
|
||||
- `ITargetResolver` (Generic) ← `HmegSceneNodeTargetResolver` (HmEG-aware) ← ...
|
||||
5. **시나리오 포맷, 베이스라인 포맷, 정규화 규칙은 Generic.** HmEG/앱 특화 정규화 규칙이 필요하면 그 계층에서 plugin 식으로 등록한다.
|
||||
6. **새 SUT를 추가할 때 HmEG-aware 코드는 재사용**한다. 새로 작성하지 말 것. 앱마다 다른 부분만 App-specific에 둔다 (보통: 플러그인 호스트 진입점 + 명령 lifecycle 이벤트 어댑터).
|
||||
## 저장소
|
||||
|
||||
### 폴더 레이아웃 (목표 — 본 규칙 추가 후 점진 마이그레이션)
|
||||
|
||||
```
|
||||
src/
|
||||
├── Recordingtest.Recorder/ # Generic
|
||||
├── Recordingtest.Player/ # Generic
|
||||
├── Recordingtest.Normalizer/ # Generic
|
||||
├── Recordingtest.DiffReporter/ # Generic
|
||||
├── Recordingtest.Runner/ # Generic
|
||||
├── Recordingtest.SutProber/ # Generic
|
||||
├── Recordingtest.Bridge.Abstractions/ # Generic — IEngineStateProvider, ITargetResolver, ...
|
||||
├── Recordingtest.Bridge.Client/ # Generic — HTTP 클라이언트
|
||||
├── Hmeg/
|
||||
│ ├── Recordingtest.Hmeg.Bridge/ # HmEG-aware — Space/Camera/Selection을 HmEG 공개 API로 읽기
|
||||
│ ├── Recordingtest.Hmeg.TargetResolver/ # HmEG-aware — 씬 노드 hit-test/포커스 식별
|
||||
│ └── Recordingtest.Hmeg.Catalog/ # HmEG-aware — 정적 분석/카탈로그 (현 EngineBridge 일부)
|
||||
└── Sut/
|
||||
└── EgBim/ # EG-BIM Modeler 전용
|
||||
├── Recordingtest.Sut.EgBim.PluginHost/ # MEF entry, EditorPlugin base 상속
|
||||
└── Recordingtest.Sut.EgBim.Adapter/ # AppManager 진입점 / command lifecycle 어댑터
|
||||
tests/
|
||||
├── Recordingtest.*.Tests/ # Generic
|
||||
├── Hmeg/Recordingtest.Hmeg.*.Tests/ # HmEG-aware
|
||||
└── Sut/EgBim/Recordingtest.Sut.EgBim.*.Tests/
|
||||
```
|
||||
|
||||
새 SUT(예: 다른 HmEG 호스트 앱)를 추가할 때:
|
||||
```
|
||||
src/Sut/<NewApp>/
|
||||
Recordingtest.Sut.<NewApp>.PluginHost/
|
||||
Recordingtest.Sut.<NewApp>.Adapter/
|
||||
```
|
||||
이 두 개만 새로 만들면 되고 Generic + HmEG-aware는 그대로 재사용된다.
|
||||
|
||||
### 현재 모듈 분류 (2026-04-09 시점, 마이그레이션 전)
|
||||
|
||||
| 모듈 | 분류 | 비고 |
|
||||
|---|---|---|
|
||||
| `Recordingtest.Recorder` | **Generic** | OK |
|
||||
| `Recordingtest.Player` | **Generic** | OK |
|
||||
| `Recordingtest.Normalizer` | **Generic** | OK |
|
||||
| `Recordingtest.DiffReporter` | **Generic** | OK |
|
||||
| `Recordingtest.Runner` | **Generic** | OK |
|
||||
| `Recordingtest.SutProber` | **Generic** | OK |
|
||||
| `Recordingtest.EgPlugin` | **혼합 — 분할 필요** | 본체는 EG-BIM 전용(MEF entry), reflection accessor는 HmEG 비의존 generic, HmEG state는 HmEG-aware. 3개로 split. |
|
||||
| `Recordingtest.EngineBridge` | **HmEG-aware** | HmEG 카탈로그/CandidateFinder. rename → `Recordingtest.Hmeg.Catalog` |
|
||||
| `Recordingtest.EngineBridge.Client` | **혼합 — 분할 필요** | HTTP 호출부 → Generic, `HmEgHttpSnapshot` → HmEG-aware |
|
||||
| `IEngineStateProvider` (현 EgPlugin 안) | → **Generic** | `Recordingtest.Bridge.Abstractions` 로 추출 |
|
||||
| `ReflectionAppManagerAccessor` (현 EgPlugin 안) | → **App-specific** | EG-BIM Modeler의 `Editor.AppManager.AppManager`를 찾는 코드. EgBim 어댑터로 이동. CI fallback 용도로만 유지. |
|
||||
| 향후 `HmegDirectStateProvider` | **HmEG-aware** | `HmEG.dll` 공개 API 직접 호출. 모든 HmEG 호스트 앱에서 재사용 |
|
||||
|
||||
### Sprint Contract 의무
|
||||
|
||||
새 SUT를 추가하거나 기존 모듈을 generic↔SUT 사이에서 옮기는 모든 작업은 `/contract <name>` 으로 Sprint Contract를 먼저 작성한다. DoD에 "분류 라벨", "의존 그래프 검증", "네임스페이스 규칙" 항목 필수.
|
||||
|
||||
## 10. 결정 로그 위치
|
||||
|
||||
주요 기술 결정과 그 근거는 `docs/history/`와 Claude 메모리(`project_recordingtest_*`)에 분산 저장된다. 새 결정 시 반드시 둘 다 갱신한다.
|
||||
- Origin: https://gitea.hmac.kr/kimminsung/recordingtest (이슈 트래커 동일)
|
||||
- 커밋·PR에 이슈 번호(#N) 참조
|
||||
- 기술 결정 근거: `docs/history/` + Claude 메모리
|
||||
|
||||
45
docs/architecture.md
Normal file
45
docs/architecture.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Architecture — recordingtest 3-tier layout
|
||||
|
||||
## 폴더 레이아웃
|
||||
|
||||
```
|
||||
src/
|
||||
├── Recordingtest.Recorder/ # Generic
|
||||
├── Recordingtest.Player/ # Generic
|
||||
├── Recordingtest.Normalizer/ # Generic
|
||||
├── Recordingtest.DiffReporter/ # Generic
|
||||
├── Recordingtest.Runner/ # Generic
|
||||
├── Recordingtest.SutProber/ # Generic
|
||||
├── Recordingtest.Bridge.Abstractions/ # Generic — IEngineStateProvider, ITargetResolver
|
||||
├── Recordingtest.Bridge.Client/ # Generic — HTTP sidecar 클라이언트
|
||||
├── Hmeg/
|
||||
│ ├── Recordingtest.Hmeg.Bridge/ # HmEG-aware — Space/Camera/Selection
|
||||
│ ├── Recordingtest.Hmeg.Catalog/ # HmEG-aware — 정적 분석/후보 탐색
|
||||
│ └── Recordingtest.Hmeg.Bridge.Client/# HmEG-aware — HmEgHttpSnapshot
|
||||
└── Sut/
|
||||
└── EgBim/
|
||||
└── Recordingtest.Sut.EgBim.PluginHost/ # MEF entry, EditorPlugin 상속, HttpListener
|
||||
tests/
|
||||
├── Recordingtest.*.Tests/
|
||||
├── Recordingtest.Architecture.Tests/ # 의존 그래프 11건 강제
|
||||
├── Hmeg/Recordingtest.Hmeg.*.Tests/
|
||||
└── Sut/EgBim/Recordingtest.Sut.EgBim.*.Tests/
|
||||
```
|
||||
|
||||
## 새 SUT 추가 시
|
||||
|
||||
HmEG-aware 재사용. 앱마다 다른 부분만 신규 작성:
|
||||
|
||||
```
|
||||
src/Sut/<NewApp>/
|
||||
Recordingtest.Sut.<NewApp>.PluginHost/ # MEF entry
|
||||
Recordingtest.Sut.<NewApp>.Adapter/ # AppManager 어댑터 (필요 시)
|
||||
```
|
||||
|
||||
## 모듈 분류 현황 (2026-04-09)
|
||||
|
||||
| 모듈 | 계층 |
|
||||
|---|---|
|
||||
| Recorder, Player, Normalizer, DiffReporter, Runner, SutProber, Bridge.Abstractions, Bridge.Client | Generic |
|
||||
| Hmeg.Bridge, Hmeg.Catalog, Hmeg.Bridge.Client | HmEG-aware |
|
||||
| Sut.EgBim.PluginHost | App-specific |
|
||||
Reference in New Issue
Block a user