# EM planning cycle deadline and longitudinal publication contract

Date: 2026-08-11

Status: approved design; implementation has not started

## Problem and evidence

The offline longitudinal acceptance command measures one end-to-end interval but the current system supplies separate five-second budgets to coarse-path bootstrap and to EM lateral/longitudinal solving.  A single-circle run therefore consumed roughly 4.94 seconds in bootstrap and another 5 seconds in EM.  This can exceed the five-second end-to-end contract without either component individually violating its own budget.

The same evidence establishes two longitudinal contract gaps:

1. A 15 m straight has a 1.0 m/s schedule and envelope but publishes approximately 0.893 m/s after three accepted half-trust anchors.  The full-trust high-precision candidates pass the QP residual audit but fail the independent jerk-limited stoppable-set validator at knot 3.  Existing traces do not include the state or stopping margin required to distinguish a numerical boundary mismatch from a material physical violation.
2. A single-rectangle candidate passes the knot-level validator, then publication resampling reports a PathS decrease of 1.1611352794815843E-05 m at sample 308.  The validator does not currently prove the continuous profile used by the publisher is nondecreasing.

Existing focused model and integration checks pass, but the four-scenario real-OSQP acceptance command remains red.  The relevant diagnosis reports are `.superpowers/sdd/em-acceptance-timing-speed-diagnosis.md` and `.superpowers/sdd/em-rectangle-paths-diagnosis.md`.

## Goals

1. Give each complete planning cycle one five-second deadline shared by bootstrap, smoothing, lateral planning, longitudinal planning, and publication.
2. Make timeout behavior safe: never replace a verified trajectory with a partial or unverified trajectory.
3. Prove before publication that the continuous longitudinal PathS profile cannot regress under the same constant-jerk interpolation used for trajectory samples.
4. Capture the minimum data needed to diagnose stoppable-set and publication-contract rejections without weakening physics, tolerances, iteration limits, or trust-region safety.
5. Preserve the four offline acceptance requirements: each scenario must ultimately publish a validated trajectory inside five seconds.  A safe timeout is correct runtime behavior, but is not counted as a successful acceptance scenario.

## Non-goals and boundaries

- Do not modify `Control`, `Shared`, state estimation, chassis, hardware, or partner-owned code.
- Do not increase the five-second budget, relax residuals, relax physical validation, or treat a timeout as a published trajectory.
- Retain the established longitudinal limits: 12 QP calls, one high-precision retry for an identical QP, strict QP audit, and independent physical validation.
- Do not automatically clamp or rewrite a candidate's PathS during publication.  Such a rewrite could invalidate its S/U/A/J dynamics.

## Design

### 1. Single cycle deadline and safe handoff

The top-level movement/trajectory-observation planning cycle creates one monotonic deadline at cycle start.  Each phase receives only the remaining time, bounded by its existing configured limit:

```text
cycle deadline (5 s)
  -> map + Hybrid A* coarse path
  -> smoothing
  -> lateral
  -> longitudinal QP and validation
  -> trajectory assembly and publication
```

No phase may create a fresh five-second allowance.  Each phase records its start time, supplied remaining budget, elapsed time, and terminal reason.  A phase that begins with no remaining budget exits without new planning work.

The planning layer returns an explicit non-published result when its deadline is reached.  It does not construct a partial trajectory and does not call the controller.  The movement-test/trajectory handoff retains the previous verified trajectory when one is still valid; during startup, where no verified trajectory exists, it sends no movement replacement and the vehicle remains stopped.  This behavior resides above the unchanged controller boundary.

The deadline is a safety and responsiveness contract.  It does not weaken the offline acceptance test: a scenario that times out before it has a valid replacement remains a failed acceptance result.

### 2. Continuous longitudinal publication contract

`LongitudinalSolutionValidator` becomes the owner of the publication precondition.  Before a candidate is accepted, it evaluates every constant-jerk knot interval using the same equations as publication:

```text
U(t) = U0 + A0*t + 0.5*J*t^2
S(t) = S0 + U0*t + 0.5*A0*t^2 + (J*t^3)/6
```

For every interval the validator checks finite values, nonnegative continuous progress speed within numerical round-off, nondecreasing continuous PathS, and continuity at the next knot.  The check is evaluated at mathematical extrema as well as endpoints, so it does not depend on a particular output sampling period.  Its numerical tolerance is at least as strict as the publisher's PathS monotonicity tolerance (numerically no larger).

Failure rejects the candidate inside the optimizer with a reason containing the source interval and first violating state.  Publication remains defensive, but a valid candidate cannot first fail there for a continuous PathS regression.  The system does not repair a failing candidate by clamping S values.

### 3. Deadline-aware optimization and diagnosis gate

The existing safety rules remain: a candidate is promoted only after QP audit, continuous publication validation, jerk-limited stopping validation, objective acceptance, and cancellation/deadline checks.  A maximum of 12 QP calls and one high-precision retry for an identical QP remain in force.

The optimizer checks the shared remaining deadline before every build, solve, retry, and promotion.  It reserves 250 ms for validation, assembly, and publication.  Once a fully validated anchor exists, every optional objective-improvement solve is capped at the remaining time after that reserve and is not started when that allocation is zero; it publishes the current anchor instead.  With no validated anchor, expiration yields the safe non-published result.

No numerical or physical rule is changed based on incomplete evidence.  New diagnostics are mandatory before choosing a physical-model repair:

- A stoppable-set rejection records knot index, S/U/A, exact braking distance, stop boundary, signed stopping margin, trust scale, and solve/audit status.
- A continuous PathS rejection records interval index, local time, endpoint S/U/A/J values, raw S/U at the first violating point, and the signed regression.
- Every phase records deadline remaining and elapsed time; each QP trace records its phase, tolerance, status, iterations, residuals, elapsed time, and rejection category.

The diagnostic branch is deterministic:

- A materially negative stopping margin means the QP's linear constraints are not an adequate inner approximation of the exact stopper.  A subsequent, separately designed repair must add an exact-safe inner approximation; it may not bypass validation.
- A margin within the explicitly measured numerical band means the follow-up repair targets numerical consistency between the trusted QP and exact validator.

This specification deliberately does not choose either physical-model repair before the actual margin is captured.

## Test strategy

Tests are written before each production change.

1. Cycle-deadline unit/integration checks: bootstrap consumes part of the cycle, EM receives only the remainder, no solve starts with zero time, timeout creates no replacement, and an existing verified trajectory is retained by the movement-test handoff.
2. Continuous-profile unit checks: an interior PathS regression with monotonic endpoints is rejected; a knot-boundary regression is rejected; a valid constant-jerk candidate is accepted; diagnostics identify the first source interval.
3. Optimizer checks: the 12-call cap and one-retry rule remain unchanged; a validated anchor is returned rather than an optional improvement when the publication reserve prevents another attempt; a physical stop failure is not promoted.
4. Real-OSQP regression: run `longitudinal-model`, `longitudinal-integration`, `em-speed-profile`, and the exact four-scenario `em-longitudinal-contract-offline` command twice.  The final command must show all four scenarios published, physically valid, nondecreasing in PathS, terminally stopped, peak speed within the existing envelope, and total elapsed time below five seconds.

## Offline speed-comparison artifacts

Before any production planner behavior changes, the offline verifier exports a real-OSQP baseline for the four acceptance scenarios.  After the repair, it exports the same scenarios with the same fixed geometry and configuration.  Each run uses a new timestamped, ignored artifact directory so a later test cannot overwrite a baseline.

Every published trajectory CSV contains one row per emitted trajectory point with the run label, scenario name, sample time, PathS, progress speed, progress acceleration, progress jerk, curvature, total planning elapsed time, peak speed, terminal speed, and publication status.  A non-published scenario writes a summary CSV row containing its status, elapsed time, and diagnostic reason, but it writes no invented trajectory-point rows.

A repository Python script using `matplotlib` accepts one baseline artifact directory and one repaired artifact directory.  It produces one PNG per scenario with baseline and repaired speed-versus-time curves on their native time coordinates, a 1.0 m/s reference line, and annotated peak and terminal speeds.  It also produces a compact CSV summary of published state, total planning time, peak speed, and terminal speed before and after repair.  Artifacts are test evidence, not source-controlled deliverables; the exporter, schema validation, and plotting-script invocation are version-controlled verification code.

The comparison is observational only.  It must never substitute a reference schedule, seed, or fabricated zero-speed curve for a failed publication.  The final acceptance run still uses the existing trajectory and timing contracts rather than an image-based assertion.

## Failure handling and observability

The public result distinguishes validation failure, solver timeout, cancellation, and deadline-expired non-publication.  Diagnostics must state whether any earlier trajectory was retained, but must not expose unbounded raw solver output.  Failure messages include enough local state to reproduce the first rejecting condition without logging whole trajectories.

## Acceptance criteria

- No planning phase obtains an independent fresh five-second allowance inside one cycle.
- No unsafe or partial trajectory is published after timeout.
- No candidate accepted by the longitudinal validator can trigger the known continuous PathS regression during publication.
- Stoppable-set and PathS failures contain the stated local diagnostics.
- Existing strict solver/physical limits remain unchanged.
- The four real-OSQP acceptance scenarios are green only when they independently publish valid trajectories inside five seconds; safety timeout behavior cannot make them green.
- The baseline and repaired artifact directories contain schema-valid CSV evidence, and the Python plotter produces a speed-comparison PNG for every scenario published in both runs.
