[AZ-489] [AZ-490] ADR-010 design pass: operator-mission as cold-start anchor

Architecture, contracts, and task amendments for the flight-route-driven
preflight + cold-start origin feature (ADR-010). No source code touched
in this commit; the implementation commits for AZ-489 / AZ-490 / AZ-419
land separately.

* architecture.md: ADR-010, new Principle #14, amended Principle #11,
  external systems gain flights service + Mission Planner UI, data
  model gains Flight / Waypoint / TakeoffOrigin.
* system-flows.md: F1 gains phase 0 (Flight resolve), F2 gains
  cold-start ladder, F7 gains mid-flight bounded-delta GPS gate.
* glossary.md: Flight, Flights API, Mid-flight bounded-delta GPS gate,
  Mission Planner UI, Takeoff origin, Waypoint.
* C10: description + cache_provisioner + manifest_verifier bumped to
  v1.1 carrying takeoff_origin + flight_id in the manifest hash.
* C12: description updated + new flights_api_client.md contract v1.0.
* C5: description + state_estimator_protocol bumped to v1.1 with
  set_takeoff_origin + 3-clause spoof-promotion gate.
* AZ-323/324/325/326/328/419 amended in place. AZ-490 spec created
  (C5 set_takeoff_origin entrypoint).
* Dependencies table: 142 tasks / 478 pts / 15 forward edges
  (2 new tasks, 2 backward deps, 2 forward deps from AZ-419).
* Leftovers cleared: 2026-05-11 Jira transition entries for AZ-355
  and AZ-386 are deleted (Jira reconnected; both already transitioned
  in their respective implementation commits).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-12 01:28:05 +03:00
parent db27e25630
commit e0be591b06
20 changed files with 875 additions and 221 deletions
@@ -22,6 +22,7 @@
| Method | Input | Output | Async | Error Types |
|--------|-------|--------|-------|-------------|
| `set_takeoff_origin` (AZ-490, ADR-010) | `origin: LatLonAlt, sigma_m: float` | `None` | No | `EstimatorConfigError`, `EstimatorFatalError` |
| `add_vio` | `VioOutput` | `None` | No | `EstimatorDegradedError`, `EstimatorFatalError` |
| `add_pose_anchor` | `PoseEstimate` | `None` | No | `EstimatorDegradedError`, `EstimatorFatalError` |
| `add_fc_imu` | `ImuWindow` | `None` | No | `EstimatorDegradedError` |
@@ -76,7 +77,8 @@ C5 is bounded by design — no unbounded growth.
**State Management**:
- iSAM2 graph + Values + Marginals lifecycle for the flight.
- Source-label state machine: tracks the AC-NEW-2 / AC-NEW-8 spoofing-promotion gate (≥10 s + visual consistency check before re-promoting a previously-spoofed FC GPS source).
- Cold-start ladder (ADR-010, AZ-490): `set_takeoff_origin(origin, sigma_m)` MUST be invoked before any `add_vio` / `add_fc_imu` / `add_pose_anchor` call. iSAM2 attaches a `PriorFactorPose3` on the initial pose key with covariance derived from `sigma_m` (default 50 m horizontal, 100 m vertical); ESKF seeds the nominal position and writes the position-block of the error covariance to `sigma_m^2`. The method is idempotent within `INIT` state (re-invocation overwrites the prior); once the estimator transitions to `TRACKING`, further calls raise `EstimatorConfigError`.
- Source-label state machine: tracks the AC-NEW-2 / AC-NEW-8 spoofing-promotion gate (≥10 s + visual consistency check + ≤ 200 m bounded-delta before re-promoting a previously-spoofed FC GPS source).
- Last-anchor-age timer for AC-1.3 binning.
**Key Dependencies**:
@@ -88,9 +90,10 @@ C5 is bounded by design — no unbounded growth.
| Eigen | matches GTSAM | Lie-algebra math |
**Error Handling Strategy**:
- `EstimatorConfigError`: `set_takeoff_origin` called after `TRACKING` state, OR called with a malformed `LatLonAlt` / non-positive `sigma_m`. Caller must surface to operator; takeoff blocked.
- `EstimatorDegradedError`: factor add yielded poor convergence; covariance inflated; emit `EstimatorOutput` with degraded label.
- `EstimatorFatalError`: iSAM2 numerical failure, KEYFRAME_LIMIT exceeded, etc.; emit no `EstimatorOutput` for this tick. AC-5.2 fallback (3 s no estimate → FC IMU-only) applies.
- Spoof-promotion gate: never re-introduce a previously-spoofed FC GPS source until BOTH (i) FC `gps_health == STABLE_NON_SPOOFED` for ≥ 10 s AND (ii) the next satellite-anchored frame agrees with the FC GPS within a configurable tolerance (AC-NEW-8). Document every reject in FDR + GCS STATUSTEXT.
- Spoof-promotion gate (Principle #11 amended, AZ-385 + AZ-490 follow-up): never re-introduce a previously-spoofed FC GPS source until ALL THREE hold — (i) FC `gps_health == STABLE_NON_SPOOFED` for ≥ 10 s, (ii) the next satellite-anchored frame agrees with the FC GPS within a configurable tolerance, AND (iii) the FC's reported position is within ≤ 200 m of the companion's last emitted `PoseEstimate`. The same gate is applied at takeoff when a Manifest `takeoff_origin` is present: an FC GPS reading that disagrees with the operator origin by > 200 m is logged as suspect and the operator origin wins. Document every reject in FDR + GCS STATUSTEXT.
## 6. Extensions and Helpers