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

状态：完成

阶段目标：完成集成计划 Task 4–5 的 EM 静态/动态数据可视化适配，在不启动网页会话、不改变 Painter 生命周期或插件发布的前提下，为冻结配置、地图/路径、运动学图表和周期交接提供可验证的不可变快照。

基线提交：`a7dde0f5e4c37438f775b706e3886ace00fe0e04`；启动检查确认 `b0b79e5` 是祖先，分支为 `trajplanner`。

实现提交：

- `0a1cbe9` `feat: export EM observation configuration`
- `a7dde0f` `feat: visualize EM rolling kinematics`
- `cc6b0f1` `fix: complete EM observation visualization contracts`

修改文件：

- `ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationStaticSnapshotBuilder.cs`
- `ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationKinematicChartBuilder.cs`
- `ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationHandoffAnalyzer.cs`
- `ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationDynamicSnapshotBuilder.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationVisualizationChecks.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationChecks.cs`

新增或确认的接口：

- `TrajectoryObservationStaticSnapshotBuilder.Build(...)` 按固定十组顺序导出冻结生效配置、车辆/地图和网页/换向确认字段；占据图为 row-major、LSB-first 紧凑 bitset，静态数据包含粗路径、完整 Local G2、方向段与换向标记。
- `TrajectoryObservationKinematicChartBuilder.Build(...)` 固定导出 `ls`、`st`、`curvature-s`、`curvature-t`、`velocity-t`、`acceleration-t`、`jerk-t`、`yaw-rate-t`；jerk 仅有 `N-1` 个真实区间，LS 使用完整活动段的共享 `ReferenceS`，ST 保留局部 `PathS`。
- `TrajectoryObservationHandoffAnalyzer.Analyze(...)` 使用 `EffectiveAtUtc + TimeFromStart` 采样，保留世界位置、速度、加速度差；仅在任一投影失败时使 `DeltaReferenceSMeters` 不可用，不比较独立局部 `PathS`。
- `TrajectoryObservationDynamicSnapshotBuilder.Build(...)` 产生当前/上一轨迹、活动段/当前视界、八图、滚动或精确停车中文语义、真实终端 `v/a`、换向确认和交接状态；`VisualizationCycleSummary` 不含完整点数组。

验证命令与结果：

1. RED：`dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation`，退出码 `1`；首个有效断言为 `static configuration group count expected 10 but was 4`，证明原验证仅检查类型存在且静态导出未满足契约。
2. `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation`，退出码 `0`，输出 `PASS trajectory-observation`。
3. `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-core-all`，退出码 `0`，输出 `PASS longitudinal-model`、`PASS longitudinal-integration`、`PASS trajectory`、`PASS em-planning-service`。
4. `dotnet run --project ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/TrajectoryPlanningVisualizationVerificationHost.csproj`，退出码 `0`，输出 `PASS trajectory-planning-visualization`。
5. `rg -n "rolling publishes the two-second ST knot count|cycle 1 has nonzero terminal speed|jerk has N-1 intervals" ...` 确认 rolling service 的 21 knot、非零末速断言和本阶段 jerk 20 区间断言均已纳入通过的入口。
6. `git diff --check 0a1cbe9^..cc6b0f1 -- <Task 4–5 路径>`，退出码 `0`；已核对 `0a1cbe9`、`a7dde0f`、`cc6b0f1` 的精确文件树。

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

已知警告或遗留问题：主项目构建仍报告两条既有 obsolete 警告，位于 `MovementTests.TireFollowing.cs` 的 `Lidar2dDetect2LegTray.LegWidth` 和 `TireFollowing.cs` 的 `MultiWheelChassis.GetSteerWheels()`，均不属于本阶段文件。一次并发启动三个验证宿主触发共享 DLL 写锁（CS2012/MSB3026）；根因是并发构建，随后按串行方式重跑三条入口均通过，未修改代码规避该环境锁。

与原计划的偏差：原 Task 4–5 实现提交已存在但验证仅检查适配器类型可构造。本阶段以 TDD 增补真实行为断言并用 `cc6b0f1` 精确修正既有阶段文件；未扩大到 Task 6–7，也未启动网页会话、修改 Painter 生命周期或插件发布。

下一阶段注意事项：阶段 07 只执行集成计划 Task 6–7。应消费本阶段静态/动态快照构建器，添加网页发布熔断与可选 Painter 生命周期、插件 DLL 打包和操作文档；继续保持 `OBSERVE_ONLY`，不得把观察循环变为控制输出。
