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

状态：完成

阶段目标：完成集成计划 Task 3 的活动方向段滚动规划控制器和异步观察循环；保持 `OBSERVE_ONLY`，不实现静态/动态图表 Adapter、网页生命周期或插件发布。

基线提交：`e141a76fdbef33f20821d6b69cad684d438eef43`（阶段 04 交接）。`b0b79e5` 已核对为祖先。

实现提交：

- `51f744b` `feat: observe EM planning across gear segments`

修改文件：

- `ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationPipeline.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationSegmentChecks.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationChecks.cs`

新增或确认的接口：

- `TrajectoryObservationController.ActiveSegment`、`SegmentState` 和 `PreviousTrajectoryForVisualization` 由 tracker 的不可变状态统一驱动；`TryAdvanceSegment(...)` 仅在 tracker 确认 `N -> N+1` 后替换 coordinator/executor。
- 同段请求使用当前 coordinator 的 `PublishedTrajectory` 作为 previous seed；确认换向时旧轨迹只保留在 `PreviousTrajectoryForVisualization`，新 coordinator 首次请求的 `PreviousTrajectory` 为 `null`。
- 会话 trajectory ID 在 coordinator 替换后继续单调增长；`CreateEffectiveConfigurationSnapshot()` 返回 `configuration.Copy()`。
- 等待换向时 executor 使用当前确认方向、下一段期望方向和 `directionConfirmed=false`；没有伪造档位读数。
- `TrajectoryObservationLoopTick` 暴露 `SegmentAdvanced` 与 tracker 的不可变 `SegmentState`。loop 仅在已消费完成任务且无飞行任务时调用 `TryAdvanceSegment`，不会为切段取消规划。

验证命令与结果：

1. `git merge-base --is-ancestor b0b79e5 HEAD`：退出码 `0`。
2. RED：`dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation`：退出码 `1`，首个断言为 `active observation segment is not hardcoded to zero was false`，准确捕获既有 `segmentIndex = 0`。
3. GREEN 与最终回归：`dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation`：退出码 `0`，输出 `PASS trajectory-observation`。
4. `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- coordinator`：退出码 `0`，输出 `PASS coordinator`。
5. `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- executor`：退出码 `0`，输出 `PASS executor`。
6. `rg -n "segmentIndex = 0|SendXYThSpeed|SendMotion|DriveStop|PredefinedDriveStop|AccumulateSpeed" ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest`：退出码 `1`，无匹配；运行源码既无硬编码活动段，也无执行器写调用。
7. `git diff --check 51f744b^..51f744b -- <Task 3 三个文件>`：退出码 `0`；`git diff-tree --no-commit-id --name-status -r 51f744b` 只列出这三个 Task 3 文件。

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

已知警告或遗留问题：退出验证中的主项目编译保留两条既有 obsolete 警告，位于 `MovementTests.TireFollowing.cs` 的 `Lidar2dDetect2LegTray.LegWidth` 和 `TireFollowing.cs` 的 `MultiWheelChassis.GetSteerWheels()`；均不属于本阶段文件。启动时 `trajectory-observation` 首次构建曾因 `TrajectoryPlanningVisualization.dll` 的一次性写锁报 CS2012（退出码 `1`）；经进程与目标检查后单独重跑同一入口通过，未修改源码处理该环境锁。实现提交后仍有 129 项无关工作区脏项，暂存区为空，均未展开、重置或提交。

与原计划的偏差：无代码范围偏差；Task 3 的三文件实现提交保持独立。阶段文件按阶段协议单独提交。

下一阶段注意事项：阶段 06 只实现集成计划 Task 4–5 的静态/动态快照、图表和 handoff 指标。它必须消费 `ActiveSegment`、`SegmentState`、`PublishedTrajectory` 与 `PreviousTrajectoryForVisualization`，不能恢复跨方向 previous seed，也不能改变 `OBSERVE_ONLY` 或引入网页生命周期。
