# EM 观察网页可视化阶段 01 交接

状态：完成

阶段目标：完成可复用 `netstandard2.0` 可视化类库的基础：不可变通用契约、防御性复制、紧凑占用 bitset、容量一帧交换、有界周期历史、已验证选项快照和稳定 JSON；不包含 HTTP/SSE、网页、EM Adapter 或 MovementTest 集成。

基线提交：`fa4938b3fc60620bee2c1694e232a5c2b35ca392`（`b0b79e5` 已确认是祖先）。

实现提交：

- `55d8e1eebf592b03caff28dfee28745959e41e09` — `feat: add planning visualization contracts`
- `ab8e4010f8d42dd8ddcd6066b82eaba7c163fc28` — `feat: add bounded visualization snapshots`

修改文件：

- `ClumsyPilot/ClumsyPilot.csproj`
- `ClumsyPilot/TrajectoryPlanningVisualization/TrajectoryPlanningVisualization.csproj`
- `ClumsyPilot/TrajectoryPlanningVisualization/Contracts/VisualizationPrimitives.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Contracts/VisualizationGeometry.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Contracts/VisualizationCharts.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Contracts/PlanningVisualizationSnapshots.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Runtime/PlanningVisualizationOptions.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Runtime/LatestVisualizationFrameStore.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Runtime/BoundedCycleHistory.cs`
- `ClumsyPilot/TrajectoryPlanningVisualization/Runtime/VisualizationJson.cs`
- `ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/TrajectoryPlanningVisualizationVerificationHost.csproj`
- `ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/Program.cs`
- `ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/Verification.cs`
- `ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/ContractChecks.cs`
- `ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/RuntimeChecks.cs`

新增或确认的接口：

- 不可变契约：`VisualizationPoint`、`VisualizationPose`、`VisualizationBounds`、`VisualizationValue`、`VisualizationConfigurationGroup`、`VisualizationPolyline`、`VisualizationMarker`、`VisualizationDirectionSegment`、`VisualizationOccupancyGrid`、`VisualizationSeries`、`VisualizationChart`、`PlanningVisualizationStaticSnapshot`、`PlanningVisualizationDynamicSnapshot` 和 `VisualizationCycleSummary`。所有携带集合的构造函数拒绝 null 元素并复制为 `ReadOnlyCollection<T>`；数值字段拒绝 NaN/Infinity。
- `VisualizationOccupancyGrid` 严格验证 `ceil(rows * columns / 8)` 字节长度，防御性复制 row-major、LSB-first bitset，并只暴露 `OccupancyBitsBase64`。
- `PlanningVisualizationOptions.CreateValidatedSnapshot()` 返回不可变 `PlanningVisualizationOptionsSnapshot`；默认端口 0、刷新 10 Hz、历史 60、固定最多 2 客户端。
- `LatestVisualizationFrameStore.Publish` 使用 `Interlocked.Exchange` 发布最新一帧；`TryReadAfter` 只返回较新 store version。
- `BoundedCycleHistory` 有界、按 `CycleVersion` 去重，且 `Snapshot()` 返回新只读副本；`VisualizationJson.Serialize` 以不变文化、ISO 日期、紧凑 camelCase 输出。

验证命令与结果：

1. `git merge-base --is-ancestor b0b79e5 HEAD` — 退出码 0。
2. `dotnet build ClumsyPilot/ClumsyPilot.csproj -p:ExcludeLegacyAutoAvoidance=true`（实现前基线）— 退出码 0；2 条既有弃用警告。
3. `dotnet run --project ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/TrajectoryPlanningVisualizationVerificationHost.csproj`（Task 1 RED）— 退出码 1；首个有效错误为缺少 `TrajectoryPlanningVisualization` 命名空间/契约类型。
4. 同一宿主（Task 1 GREEN）— 退出码 0，输出 `PASS trajectory-planning-visualization`；随后主项目构建退出码 0。
5. 同一宿主（Task 2 RED）— 退出码 1；首个有效错误为缺少 `LatestVisualizationFrameStore`，其余运行时类型同样缺失。
6. 同一宿主连续两次（Task 2 GREEN）— 两次退出码均为 0，均输出 `PASS trajectory-planning-visualization`。
7. `dotnet build ClumsyPilot/TrajectoryPlanningVisualization/TrajectoryPlanningVisualization.csproj` — 退出码 0。
8. 阶段退出：`dotnet run --project ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/TrajectoryPlanningVisualizationVerificationHost.csproj`、`dotnet build ClumsyPilot/TrajectoryPlanningVisualization/TrajectoryPlanningVisualization.csproj`、`dotnet build ClumsyPilot/ClumsyPilot.csproj -p:ExcludeLegacyAutoAvoidance=true` — 全部退出码 0；宿主输出 PASS，类库构建 0 警告，主项目构建保留 2 条既有弃用警告。
9. `git diff --check -- <阶段文件路径>` 和 `git diff --check 55d8e1e^..ab8e401 -- <阶段文件路径>` — 均退出码 0；已用 `git diff-tree --no-commit-id --name-status -r` 分别核对两个实现提交的实际文件树。

未运行的验证及原因：无。

已知警告或遗留问题：主项目构建持续报告两条实现前已存在的弃用警告：`MovementTests.TireFollowing.cs(70)` 的 `Lidar2dDetect2LegTray.LegWidth` 与 `TireFollowing.cs(243)` 的 `MultiWheelChassis.GetSteerWheels()`；与本阶段无关。

与原计划的偏差：为使 Task 1 的验证宿主能以“契约类型不存在”而非“被引用项目不存在”进入 RED，在 RED 前先创建了不含源码的最小类库项目文件；契约与项目依赖内容仍在 GREEN 阶段完成，未改变功能或文件范围。

下一阶段注意事项：阶段 2 只能实现原类库 Task 3 的 HTTP/SSE 和会话门面。先核对以上两项实现提交与本交接状态，并重新运行独立验证宿主；不得实现网页资源、EM/MovementTest 适配或任何执行器接口。`PlanningVisualizationOptionsSnapshot` 是应传入服务的冻结配置，动态帧完整轨迹只应从 `LatestVisualizationFrameStore` 获取，周期历史只能保存 `VisualizationCycleSummary`。
