BREAKING: 3-tier split step 2 + engine-bridge v3 EgBim lambdas wired
Completes the Generic / HmEG-aware / App-specific separation started in
f6b6e74. The legacy EgPlugin / EngineBridge / EngineBridge.Client /
EngineBridge.Probe modules are moved into their proper tiers, namespaces
and csproj/sln entries are renamed, and the HmegDirectStateProvider
lambdas are finally populated with real handles from the EgBim plugin
host. A new Recordingtest.Architecture.Tests project enforces the tier
rule at build time.
Moves (git mv + csproj/RootNamespace/AssemblyName rename + sln):
src/Recordingtest.EgPlugin
-> src/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost
src/Recordingtest.EngineBridge
-> src/Hmeg/Recordingtest.Hmeg.Catalog
src/Recordingtest.EngineBridge.Client
-> src/Hmeg/Recordingtest.Hmeg.Bridge.Client
src/Recordingtest.EngineBridge.Probe
-> src/Hmeg/Recordingtest.Hmeg.Catalog.Probe
tests/Recordingtest.EgPlugin.Tests
-> tests/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost.Tests
tests/Recordingtest.EngineBridge.Tests
-> tests/Hmeg/Recordingtest.Hmeg.Catalog.Tests
tests/Recordingtest.EngineBridge.IntegrationTests
-> tests/Hmeg/Recordingtest.Hmeg.Catalog.IntegrationTests
Namespace rename applied across all .cs files and csproj RootNamespace:
Recordingtest.EgPlugin -> Recordingtest.Sut.EgBim.PluginHost
Recordingtest.EngineBridge -> Recordingtest.Hmeg.Catalog
Recordingtest.EngineBridge.Client -> Recordingtest.Hmeg.Bridge.Client
Recordingtest.EngineBridge.Probe -> Recordingtest.Hmeg.Catalog.Probe
New: tests/Recordingtest.Architecture.Tests/
DependencyGraphTests walks Assembly.GetReferencedAssemblies() for each
tier and fails if a forbidden reference leaks in:
- Generic modules must not reference HmEG or any app-specific DLL
- HmEG-aware modules must not reference app-specific DLLs
- Recordingtest.Hmeg.Bridge must reference HmEG (positive check)
11 tests, all passing. Prevents future drift from CLAUDE.md §8.1.
Engine-bridge v3 wire-up (HmEgBridgePlugin.BuildProvider):
Previously the HmegDirectStateProvider lambdas returned null and the
chain fell through to reflection. They now call directly into the
EditorPlugin base class that HmEgBridgePlugin inherits:
spaceProvider = () => RootSpace
// AppManager.ViewportManager.RootSpace
viewportProvider = () => View
// EGViewport : Control, HmEGViewport
documentPathProvider = () => AppManager?.FileManager?.CurrentFile
Every lambda is wrapped in try/catch so plugin construction still
cannot throw back into the SUT. Editor02.HmEGAppManager.dll added as
a reference on Recordingtest.Sut.EgBim.PluginHost.csproj — app-
specific tier, which is allowed by the architecture tests.
Entry points were confirmed from read-only review of the SUT sources at
D:\GiteaAll\EG-BIM_Modeler\EditorPluginInterface\EditorPlugin.cs
D:\GiteaAll\EG-BIM_Modeler\HmEGApplicationManagementLibrary\HmEGAppManager.cs
D:\GiteaAll\EG-BIM_Modeler\HmEGApplicationManagementLibrary\SubManager\FileManager.cs
closing out Q1/Q2/Q6/Q7 from docs/hmeg-api-survey.md.
Tests: 115 -> 126 (+11 Architecture), 0 failures.
Next step: live verification of /scene /camera /selection with a real
SUT session; any discrepancy in HmegDirectStateProvider reflection will
be tightened after observing real HmEG camera field names.
Ref: #10 follow-up, #14 follow-up, docs/contracts/generic-sut-split.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
138
docs/history/2026-04-09_3tier-split-step2-and-v3-wireup.md
Normal file
138
docs/history/2026-04-09_3tier-split-step2-and-v3-wireup.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# 2026-04-09 — 3-tier 분리 2단계 + engine-bridge v3 EgBim 람다 wire-up
|
||||
|
||||
**이슈**: #10 follow-up (engine-bridge v3) + `docs/contracts/generic-sut-split.md`
|
||||
**소요 시간**: ~110분 (새 세션 / 동일 날짜 두 번째 블록)
|
||||
**Context 사용량**: input ~80k / output ~18k tokens (Opus 4.6, 1M context, 새 세션)
|
||||
|
||||
## 작업
|
||||
|
||||
### 1. 3-tier 분리 2단계 (mass-rename + move)
|
||||
|
||||
기존 EgPlugin/EngineBridge 모듈을 새 계층 폴더로 이동하고 네임스페이스를 일괄 rename.
|
||||
|
||||
**소스 이동 (git mv)**:
|
||||
| 원본 | 대상 | 계층 |
|
||||
|---|---|---|
|
||||
| `src/Recordingtest.EgPlugin/` | `src/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost/` | App-specific |
|
||||
| `src/Recordingtest.EngineBridge/` | `src/Hmeg/Recordingtest.Hmeg.Catalog/` | HmEG-aware |
|
||||
| `src/Recordingtest.EngineBridge.Client/` | `src/Hmeg/Recordingtest.Hmeg.Bridge.Client/` | HmEG-aware |
|
||||
| `src/Recordingtest.EngineBridge.Probe/` | `src/Hmeg/Recordingtest.Hmeg.Catalog.Probe/` | HmEG-aware |
|
||||
| `tests/Recordingtest.EgPlugin.Tests/` | `tests/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost.Tests/` | App-specific |
|
||||
| `tests/Recordingtest.EngineBridge.Tests/` | `tests/Hmeg/Recordingtest.Hmeg.Catalog.Tests/` | HmEG-aware |
|
||||
| `tests/Recordingtest.EngineBridge.IntegrationTests/` | `tests/Hmeg/Recordingtest.Hmeg.Catalog.IntegrationTests/` | HmEG-aware |
|
||||
|
||||
**네임스페이스 rename**:
|
||||
- `Recordingtest.EgPlugin` → `Recordingtest.Sut.EgBim.PluginHost`
|
||||
- `Recordingtest.EngineBridge` → `Recordingtest.Hmeg.Catalog`
|
||||
- `Recordingtest.EngineBridge.Client` → `Recordingtest.Hmeg.Bridge.Client`
|
||||
- `Recordingtest.EngineBridge.Probe` → `Recordingtest.Hmeg.Catalog.Probe`
|
||||
|
||||
**csproj rename** + `<RootNamespace>` / `<AssemblyName>` + ProjectReference 경로 갱신 + `recordingtest.sln` 에서 remove/add.
|
||||
|
||||
**문제/해결**:
|
||||
- `git mv`가 bin/obj 폴더 때문에 일부 실패 → 해당 폴더 삭제 후 재시도
|
||||
- `EngineBridge.Client` 전체 폴더 이동이 계속 permission denied → 파일 단위로 `git mv`해서 해결
|
||||
- `Directory.Build.props`의 자동 RootNamespace와 csproj의 수동 RootNamespace 정리 (Sut.EgBim.PluginHost는 수동, Hmeg.Catalog는 수동 덮어쓰기)
|
||||
|
||||
### 2. Architecture Tests 추가
|
||||
|
||||
`tests/Recordingtest.Architecture.Tests/` — 3-tier 규칙 강제.
|
||||
|
||||
- Generic 모듈 (`Bridge.Abstractions`, `Recorder`, `Player`, `Normalizer`, `DiffReporter`, `Runner`, `SutProber`) 각각이 `HmEG.dll` 또는 `Editor03.PluginInterface` / `Editor02.HmEGAppManager` / `EditorCore` 를 **참조하지 않음** (Theory, 7건)
|
||||
- HmEG-aware 모듈 (`Hmeg.Bridge`, `Hmeg.Catalog`, `Hmeg.Bridge.Client`) 각각이 app-specific DLL을 **참조하지 않음** (3건)
|
||||
- `Hmeg.Bridge` 는 `HmEG.dll` 을 **참조함** (positive check, 1건)
|
||||
|
||||
총 11건, 모두 pass. 향후 누가 실수로 generic 모듈에 HmEG 참조를 추가하면 여기서 red.
|
||||
|
||||
### 3. engine-bridge v3 EgBim 람다 wire-up (Q1~Q7 답)
|
||||
|
||||
사용자가 `D:\GiteaAll\EG-BIM_Modeler\EditorPluginInterface` 경로 공유 → read-only survey.
|
||||
|
||||
**확정 (single-file find)**: `EditorPluginInterface/EditorPlugin.cs`
|
||||
|
||||
```csharp
|
||||
public HmEGAppManager AppManager { get => TriggerStateService.AppManager; set; }
|
||||
public Space RootSpace { get => AppManager.ViewportManager.RootSpace; }
|
||||
public ViewportManager ViewportManager { get => AppManager.ViewportManager; }
|
||||
public EGViewport View { get; set; } // deprecated but still usable
|
||||
```
|
||||
|
||||
**HmEGAppManager** (`D:\GiteaAll\EG-BIM_Modeler\HmEGApplicationManagementLibrary\HmEGAppManager.cs`):
|
||||
- `ViewportManager` — RootSpace 진입점
|
||||
- `SelectionManager` — 중앙 선택 상태 (필요 시 hook, 현재는 walk)
|
||||
- `FileManager` — 저장 파일 경로
|
||||
- `AppModeManager` — 명령 lifecycle (Q4 후속)
|
||||
|
||||
**`EGViewport : Control, HmEGViewport`** (`HmEG/Controls/HmEGViewport.cs:43`) — 그대로 HmEG-aware provider에 넘길 수 있음.
|
||||
|
||||
**`FileManager.CurrentFile : string`** — 저장 문서 경로.
|
||||
|
||||
**Q 답 매핑**:
|
||||
- Q1 Space: `this.RootSpace` ✅
|
||||
- Q2 Viewport: `this.View` (EGViewport: HmEGViewport) ✅
|
||||
- Q3 Selection: 중앙 리스트 없음. Space walk + `ISelectable.IsSelected` (이미 구현됨)
|
||||
- Q4 Command lifecycle: `AppModeManager`, `TriggerStateService.TriggerEnded` (별도 contract)
|
||||
- Q5 Fov: `PerspectiveCamera` cast, `HmegDirectStateProvider.GetCamera`의 reflection `FieldOfView` 후보 chain이 이미 잡음
|
||||
- Q6 DocumentPath: `AppManager.FileManager.CurrentFile` ✅
|
||||
- Q7 EGViewport↔HmEGViewport: `EGViewport : Control, HmEGViewport` ✅
|
||||
|
||||
**구현**: `HmEgBridgePlugin.BuildProvider()`가 이제 실 람다 주입:
|
||||
|
||||
```csharp
|
||||
Func<Space?> spaceProvider = () => { try { return RootSpace; } catch { return null; } };
|
||||
Func<HmEGViewport?> viewportProvider = () => { try { return View; } catch { return null; } };
|
||||
Func<string?> documentPathProvider = () =>
|
||||
{
|
||||
try { var p = AppManager?.FileManager?.CurrentFile; return string.IsNullOrEmpty(p) ? null : p; }
|
||||
catch { return null; }
|
||||
};
|
||||
```
|
||||
|
||||
**csproj 추가 참조**: `Editor02.HmEGAppManager.dll` — `HmEGAppManager.FileManager.CurrentFile` 접근을 위해. app-specific tier이므로 허용 (ArchitectureTests는 이 tier를 검사하지 않음).
|
||||
|
||||
### 테스트
|
||||
|
||||
- 전체 suite: **126 tests pass** (115 → 126, +11 ArchitectureTests)
|
||||
- 구성: Recorder 26 / Player 24 / Sut.EgBim.PluginHost 21 / Normalizer 16 / Architecture 11 / DiffReporter 5 / Runner 6 / Hmeg.Catalog 6 / Hmeg.Catalog.Integration 6 / Hmeg.Bridge 5
|
||||
- 빌드/테스트 0 failures
|
||||
|
||||
### 분류 라벨 (2단계 완료 후 현재)
|
||||
|
||||
| 경로 | 계층 |
|
||||
|---|---|
|
||||
| `src/Recordingtest.Bridge.Abstractions/` | Generic |
|
||||
| `src/Recordingtest.Recorder/`, `.Player/`, `.Normalizer/`, `.DiffReporter/`, `.Runner/`, `.SutProber/`, `.DiffReporter.Cli/` | Generic |
|
||||
| `src/Hmeg/Recordingtest.Hmeg.Bridge/`, `.Catalog/`, `.Catalog.Probe/`, `.Bridge.Client/` | HmEG-aware |
|
||||
| `src/Sut/EgBim/Recordingtest.Sut.EgBim.PluginHost/` | App-specific (EgBim) |
|
||||
|
||||
## 라이브 검증 (대기)
|
||||
|
||||
다음 세션의 P1:
|
||||
|
||||
1. 본 작업물을 빌드해 `EG-BIM Modeler/Plugins/Recordingtest.Sut.EgBim.PluginHost/` 아래 배포
|
||||
2. SUT 실행, 이미 열린 .hmeg 문서가 있으면 Box 등 몇 개 객체 생성 + 선택
|
||||
3. 셸에서:
|
||||
```
|
||||
curl http://localhost:38080/health
|
||||
curl http://localhost:38080/scene # object_count, document_path
|
||||
curl http://localhost:38080/camera # eye/target/up/fov 실값
|
||||
curl http://localhost:38080/selection # selected_ids
|
||||
```
|
||||
4. 실값이 기대와 다르면 `HmegDirectStateProvider.GetCamera`의 reflection 멤버 후보 또는 selection walk 로직 보정 1~2회 반복
|
||||
|
||||
## 미커밋 (다음 커밋에 통합)
|
||||
|
||||
- 3-tier 분리 2단계 전체 (수많은 파일 rename/move)
|
||||
- `Recordingtest.Architecture.Tests` 신규
|
||||
- `HmEgBridgePlugin.BuildProvider` 실 람다
|
||||
- `Editor02.HmEGAppManager.dll` 참조 추가
|
||||
- `recordingtest.sln`, `PROGRESS.md`, `PLAN.md`, 본 history
|
||||
|
||||
## 관련
|
||||
|
||||
- `CLAUDE.md §8.1`
|
||||
- `docs/contracts/generic-sut-split.md`
|
||||
- `docs/hmeg-api-survey.md`
|
||||
- `D:\GiteaAll\EG-BIM_Modeler\EditorPluginInterface\EditorPlugin.cs` (read-only)
|
||||
- `D:\GiteaAll\EG-BIM_Modeler\HmEGApplicationManagementLibrary\HmEGAppManager.cs` (read-only)
|
||||
- `D:\GiteaAll\EG-BIM_Modeler\HmEGApplicationManagementLibrary\SubManager\FileManager.cs` (read-only)
|
||||
Reference in New Issue
Block a user