# 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.
