Files
ParkingRobot/.superpowers/sdd/final-fix-report.md
T

11 KiB

EM observation MovementTest final-fix report

Date: 2026-08-04

Reviewed base/head: d0e673b

Scope: final-review fixes for the observe-only TrajectoryObservationMovementTest

Outcome

All final-review findings were addressed without adding any chassis, motor, steering, brake, wheel, adapter, or geometric-controller write call. The runtime hardware access remains limited to:

  • DetourInterface.getCartLocation()
  • BasicPilotBase.Chassis.GetCarSpeed(true)

The dirty worktree contained extensive unrelated changes before this fix wave. They were not edited, staged, or reverted as part of this work.

Modified files

  • ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/MovementTest.TrajectoryObservationTest.cs
    • Added the four public editable vehicle fields with Task-1 defaults.
    • Copies all vehicle fields into a validated settings snapshot before the worker starts.
    • Replaced the per-cycle planner await with a non-blocking observation tick coordinator.
    • Uses the freshly captured state timestamp for planning and observation.
    • Draws and session-guard logs on every configured observer tick while planning is in flight.
    • Clears all three painter layers for a current-session runtime fault under SessionSync.
    • Preserves the intentional bootstrap-failure diagnostic view.
    • Passes the exact GearSwitch wait state to the world presentation without changing segment 0.
  • ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationContracts.cs
    • Added CreateValidatedSnapshot() to copy and validate all map, cadence, and vehicle settings.
  • ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationPipeline.cs
    • Added TrajectoryObservationLoop/TrajectoryObservationLoopTick for one asynchronous in-flight planning cycle plus non-blocking observer ticks.
    • Added a Painter-free session-end decision model.
    • Added a pure GearSwitch runtime-state model containing the exact operator notice.
  • ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationPresentation.cs
    • Draws the exact GearSwitch wait notice in the existing World layer.
  • ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/README.md
    • Documents all four vehicle inputs, units, defaults, snapshot behavior, asynchronous cadence, and fault/bootstrap cleanup behavior.
  • ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationChecks.cs
    • Added delayed rolling-planner cadence, lifecycle cleanup, GearSwitch presentation, vehicle defaults/snapshot, full settings validation, fresh state-time, and valid non-empty obstacle-source coverage.
  • .superpowers/sdd/final-fix-report.md
    • This evidence and self-review report.

Finding-by-finding resolution

1. Planner latency no longer blocks observation cadence

TrajectoryObservationLoop.Tick(...) polls a completed planning task but never waits for an incomplete one. It permits at most one planner task in flight, observes the controller's atomically published trajectory using the current tick's state and timestamp, and returns a tick record for drawing and logging. The host calls it after every configured delay, draws all layers, and invokes LogIfCurrent(...) for every tick.

The deterministic regression first establishes an existing published trajectory, starts a second planning call that is held by ManualResetEventSlim, and proves that a later observer tick:

  • returns before the planner is released;
  • retains the existing published trajectory;
  • uses the later state sequence and timestamp;
  • is eligible for session-guarded logging;
  • consumes the planning result after release without reusing the pre-plan state/time.

There is no planner continuation that logs results. A result is consumed only by a tick after its cancellation check, and all host drawing/logging remains guarded by the active session ID.

2. Runtime faults clear stale painter layers

ClearAndLogRuntimeFaultIfCurrent(...) acquires SessionSync, verifies the session ID, clears World/LS/ST together through Presentation.ClearAll(), and then reports the fault. The pure lifecycle model specifies:

  • bootstrap failure: preserve the diagnostic view;
  • runtime fault: clear all layers;
  • cancellation: clear all layers.

Bootstrap failure still follows the normal successful-task completion path after drawing its diagnostic world view, so the fault cleanup path does not erase it.

3. Vehicle inputs are editable, validated, and frozen

The MovementTest now exposes:

Field Default
VehicleLengthMeters 0.80d
VehicleWidthMeters 0.60d
SafetyMarginMeters 0.05d
MaximumCurvaturePerMeter 1d / 1.20d

All four are copied into TrajectoryObservationSettings before CreateValidatedSnapshot() validates and copies every setting. Tests mutate the original settings after snapshot creation and prove that the bootstrap vehicle retains the configured values. Validation coverage includes map padding, resolution, replan period, observer period, length, width, safety margin, and maximum curvature.

4. GearSwitch wait state is painted

TrajectoryObservationRuntimeState.Create(...) enters the wait state only when a GearSwitch trajectory reaches its final TimeFromStart. Its WorldNotice is exactly:

等待真实档位/方向确认;观察模式不会推进下一方向段

The host passes that state to DrawWorld(...), which draws it in TrajectoryObserver.World. The controller continues to plan and observe segment 0; no direction-change action or segment advancement was added.

5. Coverage additions

The verification host now proves that a valid non-empty obstacle list creates exactly one required trajectory-observer-manual source, preserves the positive snapshot version, projects as Applied, and retains its geometry. The existing forbidden-call audit remains intact.

RED/GREEN evidence

Command used for each focused cycle:

dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation

Regression RED evidence GREEN evidence
Delayed planner cadence Exit 1; CS0246 for missing TrajectoryObservationLoop and TrajectoryObservationLoopTick. Exit 0; PASS trajectory-observation. The strengthened version delays the second rolling plan and observes the existing first publication.
Every-tick logging signal Exit 1; CS1061 for missing TrajectoryObservationLoopTick.ShouldLog. Exit 0; PASS trajectory-observation.
Session cleanup decisions Exit 1; missing TrajectoryObservationSessionLifecycle and TrajectoryObservationSessionEndReason. Exit 0; PASS trajectory-observation.
Vehicle input/snapshot contract Exit 1; missing four MovementTest fields and CreateValidatedSnapshot(); the first draft also exposed an inappropriate direct MovementTest/ClumsyCore test dependency, so the default-field check was corrected to the existing UTF-8 source seam before implementation. Exit 0; PASS trajectory-observation. Invalid-setting and valid-obstacle checks run in the same focused suite.
GearSwitch world state Exit 1; CS0246/missing TrajectoryObservationRuntimeState. Exit 0; PASS trajectory-observation.
Fresh observation timestamp Exit 1; assertion observer host uses the fresh state snapshot time for each observation tick was false. Exit 0; PASS trajectory-observation.

Final verification evidence

Focused trajectory observation

Command:

dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation

Result: exit 0, PASS trajectory-observation.

EM all-up suite

Command:

dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-all

Result: exit 0. Passed foundation, segmentation, frenet, corridor, optimization, OSQP solve/loader, lateral model/integration/real OSQP, longitudinal model/integration, trajectory, EM planning service, coordinator, executor, plugin packaging, trajectory observation, rolling end-to-end, and rolling execution tail.

Project build

Command:

dotnet build ClumsyPilot/ClumsyPilot.csproj --no-restore

Result: exit 0, 0 warnings, 0 errors.

Whitespace check

Command:

git diff --check

Result: exit 0. Git emitted only line-ending conversion warnings for existing and scoped working-copy files; it reported no whitespace errors.

Forbidden-call audit

Command pattern:

SendXYThSpeed|SendMotion|SendTh|AccumulateSpeed|ComputeWheelsGeometrically|DriveStop|PredefinedDriveStop

Scope: ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/**/*.cs

Result: exit 0 from the audit wrapper: PASS forbidden-call audit: no enumerated actuator write calls found.

A second scoped method-name audit for Brake|Steer|Wheel|Motor|Adapter invocations also passed with no matches. A live-access inspection found only the two approved read paths listed at the start of this report.

Remaining limitations

  • The verification host deliberately does not instantiate Painter or connect to a live vehicle. GearSwitch presentation and lifecycle cleanup are covered through pure decision/state models plus a source seam proving the World painter consumes runtimeState.WorldNotice. Actual colors/placement and MDCS UI rendering still require an operator environment.
  • The forbidden-call test exhaustively covers the established explicit token list inside the observation runtime directory. The additional brake/steer/wheel/motor/adapter audit is a scoped method-name heuristic. Proving an exhaustive list of every possible external adapter write API would require inventorying unrelated proprietary hardware assemblies/source outside this feature's authorized scope; this report does not guess at names that are not present in the repository sources.
  • Some fresh dotnet run builds emitted two pre-existing obsolete-API warnings in MovementTests.TireFollowing.cs and TireFollowing.cs. The required final project build completed with 0 warnings and 0 errors; no unrelated warning source was changed.

Self-review

  • Confirmed there is no await controller.StartCycle(...) in the host loop.
  • Confirmed each tick reads one fresh vehicle state, uses its capture time, observes, draws, and session-guard logs.
  • Confirmed only one planning task can be in flight and stale continuation logging does not exist.
  • Confirmed current-session runtime fault cleanup and cancellation cleanup call ClearAll() while the session lock is held.
  • Confirmed bootstrap failure returns normally after its diagnostic draw and is not cleared by Finish(...).
  • Confirmed GearSwitch state is drawn in World and segment index remains 0.
  • Confirmed all vehicle fields match Task-1 defaults, are copied before validation, and are included in the settings snapshot.
  • Confirmed documentation lists units/defaults and explains snapshot, cadence, and cleanup behavior.
  • Confirmed the runtime source introduces no new hardware write reference and retains only the approved live reads.
  • Confirmed unrelated dirty-worktree files remain outside the scoped diff and staging list.