# EM Longitudinal Rolling Planning — Final Acceptance Handoff ## Scope and commits - Phase 4 start baseline: `6cfbaf6` (`feat: reuse prior trajectory in longitudinal planning`) - Task 8: `eb050b1` (`test: cover rolling-to-stop EM planning flow`) - Task 9: `302798b` (`docs: explain rolling longitudinal planning diagnostics`) - Phase 4 code/documentation end: `302798b` Only original-plan Tasks 8, 9, and 10 were executed. No fifth phase is defined or created. ## Delivered behavior ### Task 8 — service-level rolling-to-stop regressions - Added service coverage for `RollingContinuation -> ApproachStopBoundary -> ExactStopAtBoundary`. - The rolling case uses `DistanceHorizonMeters=5m`, `TimeHorizonSeconds=2s`, `OutputTimeStepSeconds=0.1s`, and `MaximumForwardSpeedMetersPerSecond=0.2m/s`; it publishes 21 points, stops short of 5m, and retains nonzero terminal speed. - Goal and `CreateGearPairReferencePath()` exact-stop cases verify the true boundary anchor, following QP stationary point, zero speed, and the absence of points from the next direction segment. - The parameterized gear-pair fixture retains its existing 2m default and supports a short first segment for exact-stop service tests. - The existing rolling integration regression now explicitly proves the 21-knot / 5m-LS / 2s-ST semantics. ### Task 9 — observation diagnostics and documentation - The one-time configuration diagnostic reports the worst forward/reverse jerk-limited stopping capability: `maximumJerkLimitedStopDistance`, `maximumJerkLimitedStopDuration`, and `requiredDistanceHorizon`. - Published trajectory summaries now report `longitudinalMode`, `terminalSpeed`, and `terminalAcceleration`. - Failure summaries preserve every upstream value and explicitly mark any missing longitudinal context as `unavailable`; the required fields are `longitudinalMode`, `remainingToBoundary`, `minimumStoppingDistance`, `minimumStoppingDuration`, and `maximumStoppedReachableDistance`. - EMPlanner and MovementTest documentation now distinguish the L-S distance window from the S-T duration and state that rolling observation remains `OBSERVE_ONLY`. ## TDD and debugging record Task 8 began with new service assertions and an `em-core-all` red run. The first failure was an undersized ±3m fixture map for a 10m rolling path. Subsequent red runs established that a scripted solver warm start is not a validated exact stop solution. The final fixture uses the pre-existing, discretely feasible exact-stop service scenario while the separate 5m/2s case covers rolling semantics. No acceleration, jerk, solver residual, or publication-validation limit was changed. Task 9 began with new required-field assertions. `trajectory-observation` failed because the configuration diagnostic did not report jerk-limited stopping capability; the minimal implementation then made that test pass. ## Verification evidence All commands below were run from the repository root. | Command | Exit | Key output | | --- | ---: | --- | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-core-all` (Task 8 red) | 1 | New fixture exposed map-boundary and unvalidated exact-stop warm-start failures. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- longitudinal-integration` | 0 | `PASS longitudinal-integration` after reverting an unsuccessful seed experiment. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-core-all` (Task 8 green) | 0 | `PASS longitudinal-model`, `PASS longitudinal-integration`, `PASS trajectory`, `PASS em-planning-service`. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation` (Task 9 red) | 1 | Missing `maximumJerkLimitedStopDistance=` assertion. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation` (Task 9 green) | 0 | `PASS trajectory-observation`. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-core-all` | 0 | All four core PASS lines. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- coordinator` | 0 | `PASS coordinator`. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- executor` | 0 | `PASS executor`. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation` | 0 | `PASS trajectory-observation`. | | `dotnet build ClumsyPilot/ClumsyPilot.csproj -p:ExcludeLegacyAutoAvoidance=true` | 0 | Build succeeded with 0 warnings and 0 errors. | | `dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- longitudinal-real-osqp-probe` | 0 | `PASS longitudinal-real-osqp`. | | `git diff --check` | 0 | No whitespace errors; only CRLF notices from unrelated user edits. | | `git status --short` / `git log --oneline -12` | 0 | Task commits are present; unrelated user work remains unstaged. | The automated C# runs emitted the pre-existing obsolete-API warnings in `MovementTests.TireFollowing.cs` and `TireFollowing.cs`; the Task 10 build with `ExcludeLegacyAutoAvoidance=true` itself reported 0 warnings. ## OSQP and observation-only target verification The real OSQP probe succeeded on this Windows workspace host, so the native DLL was loadable for the probe. The manual `TrajectoryObservationMovementTest` observation-only run remains pending on the deployed vehicle/MDCS host: it is a vehicle-UI MovementTest that requires live localization and chassis-speed read interfaces and has no standalone non-interactive launcher in this workspace. It must confirm the startup configuration prints once, the `RollingContinuation -> ApproachStopBoundary -> ExactStopAtBoundary` progression, no point-21 `JerkLimitExceeded`, and continuing `OBSERVE_ONLY: no chassis command is sent.` output. ## Preserved user worktree and safety constraints The branch remains `trajplanner`. Unrelated modified, deleted, and untracked user work in PathSmoothing, CoarsePath, Map, reports, configuration, MovementTest, and planning/spec documents remains untouched and unstaged. No `reset`, `checkout`, `clean`, `stash`, broad `git add`, or worktree cleanup was used. No chassis command, trajectory follower, or watchdog was added. `OBSERVE_ONLY` remains unchanged. ## Retained invariants - `DistanceHorizonMeters` remains the L-S reference window; `TimeHorizonSeconds` remains one S-T output duration. - Only real Goal/GearSwitch boundaries use exact zero-speed terminals and an in-QP stationary S/U/A tail. - `RollingContinuation` and `ApproachStopBoundary` may publish nonzero terminal speed and do not gain a synthetic hold. - `ZeroSpeedHoldSeconds` remains outside the QP horizon. - Previous-trajectory PathS/speed arrays remain objective soft references, never terminal hard constraints. - No jerk, acceleration, solver, or publication-validation threshold was relaxed.