Files
gps-denied-onboard/_docs/02_document/FINAL_report.md
T
Oleksandr Bezdieniezhnykh a92e5ee482 [AZ-329] [AZ-330] [AZ-523] [AZ-524] Doc sweep: arch + glossary for Batch 44
Propagate Batch 44 SRP refactor (C11 internal flight-state gate moved to
C12; PostLandingUploadOrchestrator gates on flight_footer.clean_shutdown;
OperatorReLocService dispatches AC-3.4 hints via OperatorCommandTransport)
into the suite-wide architecture documents that the per-component sweep
in Phase F did not yet cover.

Files updated:
- architecture.md: C11/C12 component entries, principle #4 phrasing,
  Data Model table (FlightStateSignal annotation + new
  FlightFooterRecord / PostLandingUploadRequest / ReLocHint rows),
  post-landing + reloc data-flow summaries, ADR-004 "Why the gate
  moved to C12" rationale, deployment + security wording.
- glossary.md: Tile Manager entry — gate-removal note.
- data_model.md: FlightStateSignal row clarified; new rows for
  Batch 44 DTOs.
- system-flows.md: F10 row, dependencies, full F10 prose +
  preconditions + mermaid + error table reworked around the
  footer-based gate.
- epics.md: E-C11 scope/interface/AC/child-issue table (gate
  stripped, AZ-317 superseded); E-C12 scope/interface/AC/child-
  issue table expanded with PostLandingUploadOrchestrator,
  OperatorReLocService, FdrFooterReader, OperatorCommandTransport.
- FINAL_report.md: component table rows 12 + 13.
- components/10_c8_fc_adapter/description.md: removed stale claim
  that C11 TileUploader consumes FlightStateSignal.
- contracts/c6_tile_cache/tile_metadata_store.md: minor C12
  naming fix.

Tests: 1543 passed / 80 skipped — doc-only sweep, no regressions.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 21:28:59 +03:00

218 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GPS-Denied Onboard Pose Estimation — Planning Report
> Generated 2026-05-09 at the close of greenfield Plan (Step 3) — Final / Quality Checklist phase.
> Sources: `architecture.md`, `glossary.md`, `system-flows.md`, `data_model.md`, `risk_mitigations.md`, `epics.md`, `tests/traceability-matrix.md`, `tests/*.md`, `components/**/*.md`, `common-helpers/*.md`, `deployment/*.md`.
## Executive Summary
A Jetson Orin Nano Super-hosted Python+C++ companion replaces real GPS for fixed-wing UAVs in GPS-denied/spoofed environments by fusing pre-flight-cached `satellite-provider` tiles, live nav-camera frames (3 Hz), and FC IMU/attitude (100200 Hz) through a hierarchical pipeline `VIO → VPR → re-rank → matcher → AdHoP-conditional refinement → pose → state` and emits a WGS84 fix with honest 6×6 covariance + provenance label to the FC at 5 Hz, all inside a 400 ms p95 latency budget. Plan decomposes the system into **14 components + 8 common helpers**, **22 numbered system-level Mermaid flows across F1F10**, **39 acceptance criteria + 20 restrictions** with **92.4 % inclusive / 89.8 % strict test coverage**, and **19 Jira epics (AZ-244..AZ-262)** with a total estimated effort of **~295477 story points** (range across t-shirt sizes).
## Problem Statement
Fixed-wing UAVs operating in eastern/southern Ukraine must continue to navigate when the FC's GPS is denied or actively spoofed. The companion provides a drop-in replacement WGS84 fix derived from pre-cached `satellite-provider` imagery + onboard vision + FC IMU, with honest covariance and a `{satellite_anchored | visual_propagated | dead_reckoned}` provenance label, while remaining read-only against `satellite-provider` in flight (post-landing tile uploads run from the operator workstation only). Mission profile: 8 h flights, ~60 km/h cruise, ≤1 km AGL, ≤400 km² total cached area, 25 W TDP, -20 °C to +50 °C envelope.
## Architecture Overview
Single Python-with-C++-extensions monolithic process per binary track on the Jetson Orin Nano Super (8 GB shared LPDDR5, 25 W, JetPack 6.2). Cross-component coupling routes through a shared GTSAM substrate so posterior covariance is recovered natively (`Marginals.marginalCovariance`, D-C5-5 = (c)). Interface-first components live under `src/components/<component>/` with constructor-injected dependencies; per-binary CMake `BUILD_*` flags select which `Strategy` implementations are linked into each artifact (`production-binary` = OKVIS2 + KltRansac + UltraVPR + …; `research-binary` = all candidate strategies for the IT-12 comparative study). The operator-side Tile Manager (C11) is a separate binary excluded from the airborne CMake target — process-level isolation is the primary defence for ADR-004 (no in-flight `satellite-provider` I/O in either direction).
**Technology stack**: Python 3.10 + C++17, TensorRT 10.3 (JetPack 6.2 pin) / ONNX Runtime + TRT EP / pure PyTorch FP16 baseline; OpenCV ≥ 4.12.0; GTSAM iSAM2 + `IncrementalFixedLagSmoother`; FAISS HNSW; PostgreSQL 16 (`tiles` schema mirrored from `satellite-provider`); pymavlink + MAVLink 2.0 signing for ArduPilot, YAMSPy + INAV-Toolkit MSP2 for iNav.
**Deployment**: two execution tiers — Tier-1 workstation Docker (fast/cheap, AC-bound jobs that do not require Jetson hardware) and Tier-2 self-hosted Jetson runner (AC-NEW-1 / NFT-PERF / NFT-LIM); pre-flight + post-landing operator tooling runs on the operator workstation; companion image is bare JetPack 6.2 (no Docker on Tier-2 to keep INT8 calibration cache trustworthy per D-C10-6).
See `architecture.md` for the full ADR set (ADR-001..ADR-009), 12 architectural principles, and per-component intent statements.
## Component Summary
| # | Component | Purpose | Dependencies | Epic |
|---|-----------|---------|-------------|------|
| 01 | C1 VIO | Pluggable `VioStrategy` (OKVIS2 default, VINS-Mono research, KltRansac mandatory simple-baseline) producing per-frame `VioOutput` | C7, helpers (IMU preintegrator, SE3 utils) | AZ-254 |
| 02 | C2 VPR | Pre-cached satellite-tile retrieval (UltraVPR primary, MegaLoc/MixVPR/SelaVPR/EigenPlaces/NetVLAD/SALAD candidates) behind `VprStrategy` | C6, C7 | AZ-255 |
| 03 | C2.5 Re-rank | Single-pair LightGlue inlier-count rerank K=10 → N=3 | C2, C7, helper LightGlue runtime | AZ-256 |
| 04 | C3 Matcher | DISK+LightGlue cross-domain matching + RANSAC + reprojection residual filter | C2.5, C7, helper RANSAC filter | AZ-257 |
| 05 | C3.5 AdHoP | Conditional refinement when initial reprojection residual exceeds threshold | C3, C7 | AZ-258 |
| 06 | C4 Pose | OpenCV `solvePnPRansac` (IPPE) wrapped in GTSAM `Marginals` for native 6×6 covariance | C3.5, C5 (shared GTSAM substrate) | AZ-259 |
| 07 | C5 State | GTSAM iSAM2 + `IncrementalFixedLagSmoother` (K=1020); spoof-promotion gate; AC-4.5 internal smoothing | C1, C4, C8 inbound, C13 | AZ-260 |
| 08 | C6 Tile Cache | PostgreSQL btree spatial index + filesystem `./tiles/{zoom}/{x}/{y}.jpg` mirroring `satellite-provider`; FAISS HNSW VPR descriptor index | E-BOOT, E-CC-LOG, E-CC-CONF | AZ-250 |
| 09 | C7 Inference Runtime | TensorRT 10.3 engines (Polygraphy / trtexec / IBuilderConfig hybrid); ORT+TRT EP fallback; PyTorch FP16 baseline | E-BOOT, E-CC-CONF, E-CC-FDR-CLIENT | AZ-249 |
| 10 | C8 FC + GCS Adapter | `pymavlink` `GPS_INPUT` for ArduPilot (signed) + `MSP2_SENSOR_GPS` for iNav (unsigned, accepted residual risk); honest 6×6 → 2×2 covariance projection; GCS 12 Hz downsampled telemetry | C5, E-CC-CONF, E-CC-LOG | AZ-261 |
| 11 | C10 Pre-flight Cache Provisioning | Builds model-derived cache (descriptors, engines, manifest, content hashes); F2 takeoff verifier; does NOT touch `satellite-provider` (network I/O lives in C11) | C6, C7, E-CC-LOG | AZ-252 |
| 12 | C11 Tile Manager | Operator-side `TileDownloader` (pre-flight) + `TileUploader` (post-landing — no internal flight-state gate after Batch 44; gating lives in C12); excluded from airborne image | C6, E-CC-CONF, E-CC-LOG | AZ-251 |
| 13 | C12 Operator Pre-flight Orchestrator | CLI subcommands (`download`, `build-cache`, `upload-pending`, `reloc-confirm`); `PostLandingUploadOrchestrator` (gates on `flight_footer.clean_shutdown`); `OperatorReLocService` (AC-3.4 hint via `OperatorCommandTransport`); sector classification UI hook; FDR retrieval helpers | C10, C11, E-CC-LOG | AZ-253 |
| 14 | C13 Flight Data Recorder | Per-flight ≤64 GB NVM ring (estimates + IMU + emitted MAVLink + health + mid-flight tiles + ≤0.1 Hz failed-tile thumbnails); raw nav/AI-cam frames excluded | E-BOOT, E-CC-LOG, E-CC-CONF, E-CC-FDR-CLIENT | AZ-248 |
**Cross-cutting epics** (not components, but shared concerns): E-BOOT (AZ-244), E-CC-LOG (AZ-245), E-CC-CONF (AZ-246), E-CC-FDR-CLIENT (AZ-247).
**System-level test epic**: E-BBT (AZ-262) parents the FT/NFT scenarios across all components.
**Implementation order** (from dependency graph in `epics.md`):
1. **Phase 1 (foundation, parallel)**: E-BOOT (AZ-244) → E-CC-LOG (AZ-245), E-CC-CONF (AZ-246), E-CC-FDR-CLIENT (AZ-247).
2. **Phase 2 (data + runtime + recorder)**: E-C13 (AZ-248), E-C7 (AZ-249), E-C6 (AZ-250).
3. **Phase 3 (operator tooling chain)**: E-C11 (AZ-251) → E-C10 (AZ-252) → E-C12 (AZ-253).
4. **Phase 4 (perception pipeline)**: E-C1 (AZ-254), E-C2 (AZ-255) → E-C2.5 (AZ-256) → E-C3 (AZ-257) → E-C3.5 (AZ-258) → E-C4 (AZ-259).
5. **Phase 5 (state + emission)**: E-C5 (AZ-260) → E-C8 (AZ-261).
6. **Phase 6 (system tests)**: E-BBT (AZ-262) — hardens behind every other epic.
## System Flows
| Flow | Description | Key Components |
|------|-------------|---------------|
| F1 | Pre-flight cache provisioning | C11 (TileDownloader), C6, C10, C12 |
| F2 | Takeoff load (cold-start TTFF, AC-NEW-1) | C10, C7, C6, C8, C5 |
| F3 | Steady-state per-frame estimation (the F3 hot path) | C1, C2, C2.5, C3, C3.5, C4, C5, C8, C13 |
| F4 | Mid-flight tile generation + local cache write | C5 (orthorectifier subpath), C6, C13 |
| F5 | Visual blackout + spoofed-GPS failsafe (AC-NEW-8) | C1, C5, C8 (STATUSTEXT) |
| F6 | Sharp-turn / disconnected-segment re-localization | C2, C2.5, C3, C5 |
| F7 | Spoofing-promotion via EKF source-set switch (AC-NEW-2) | C5 (SourceLabelStateMachine), C8 (AP D-C8-2) |
| F8 | Companion reboot recovery | C13 (FDR replay), C5, C8 |
| F9 | GCS telemetry stream (AC-6.1) | C8 (GcsAdapter) |
| F10 | Post-landing tile upload (D-PROJ-2 contract) | C11 (TileUploader), C6, C12 |
Reference `system-flows.md` for the per-flow Mermaid sequence diagrams + flowcharts; `_docs/02_document/diagrams/components.drawio` is the visual companion for component boundaries.
## Risk Summary
| Level | Count | Key Risks |
|-------|-------|-----------|
| Critical | 0 | — |
| High | 3 | R01 (D-PROJ-2 ingest endpoint not yet shipped), R03 (MAVLink-2.0 signing handshake no precedent — IT-3 gated), R11 (AC-NEW-4/AC-NEW-7 multi-flight statistical headroom — D-PROJ-3 deferred) |
| Medium | 8 | R02 (ADR-004 process-isolation regression), R04 (TRT engine SM/JP/TRT mismatch), R05 (iSAM2 silent factor-add failure), R06 (VPR top-1 false positive), R07 (premature spoof re-promotion), R08 (tile freshness drift in active-conflict sectors), R10 (`Marginals` latency under thermal throttle), R12 (single deployment camera) |
| Low | 3 | R09 (per-flight signing key compromise), R13 (FDR queue overrun), R14 (C2.5 ↔ C3 LightGlue circular dependency — resolved via shared helper) |
**Iterations completed**: 1 (initial Step 4 risk pass; R02 enforcement scope extended, R14 resolved via helper ownership).
**All Critical/High risks mitigated**: Yes — R01 has e2e mock-suite-sat-service fixture + leftover tracking; R03 is gated by IT-3 with documented D-C8-2-FALLBACK options (ADR-008); R11 is mitigated by AC-text relaxation 2026-05-09 (Monte-Carlo-with-CI) plus D-PROJ-3 carryforward.
Reference `risk_mitigations.md` for the full register, per-risk trigger conditions, and detailed mitigations.
## Test Coverage
The test suite is organised as scenario specs (no source code yet). Per-component tests live under each component's `tests.md`; cross-component / system-level scenarios live under `_docs/02_document/tests/`.
### Per-component scenario counts (from each `components/*/tests.md`)
| Component | Component-internal tests file |
|-----------|------------------------------|
| C1 | `components/01_c1_vio/tests.md` |
| C2 | `components/02_c2_vpr/tests.md` |
| C2.5 | `components/03_c2_5_rerank/tests.md` |
| C3 | `components/04_c3_matcher/tests.md` |
| C3.5 | `components/05_c3_5_adhop/tests.md` |
| C4 | `components/06_c4_pose/tests.md` |
| C5 | `components/07_c5_state/tests.md` |
| C6 | `components/08_c6_tile_cache/tests.md` |
| C7 | `components/09_c7_inference/tests.md` |
| C8 | `components/10_c8_fc_adapter/tests.md` |
| C10 | `components/11_c10_provisioning/tests.md` |
| C11 | `components/12_c11_tilemanager/tests.md` |
| C12 | `components/13_c12_operator_orchestrator/tests.md` |
| C13 | `components/14_c13_fdr/tests.md` |
### System-level scenario suites (`_docs/02_document/tests/`)
| File | Scenario family |
|------|-----------------|
| `tests/blackbox-tests.md` | FT-P-* (positive functional) + FT-N-* (negative functional) |
| `tests/performance-tests.md` | NFT-PERF-* (Tier-2) |
| `tests/resource-limit-tests.md` | NFT-LIM-* |
| `tests/security-tests.md` | NFT-SEC-* |
| `tests/resilience-tests.md` | NFT-RES-* |
| `tests/test-data.md` | Fixture inventory (Derkachi flight + AerialVL S03 + e2e mock-suite-sat-service) |
| `tests/environment.md` | Test environment + Tier-1/Tier-2 split |
| `tests/traceability-matrix.md` | Single source of truth for AC ↔ scenario coverage |
### Acceptance Criteria + Restrictions coverage (from `tests/traceability-matrix.md`, revised 2026-05-09)
| Category | Total | Covered | PARTIAL | Not Covered | Coverage % (PARTIAL counted half) |
|----------|-------|---------|---------|-------------|------------------------------------|
| Acceptance Criteria | 39 | 35 | 2 | 2 | 92.3 % |
| Restrictions | 20 | 18 | 1 | 1 | 92.5 % |
| **Total** | **59** | **53** | **3** | **3** | **92.4 %** (strict 89.8 %) |
Both the inclusive reading (PARTIAL = covered) and the strict reading clear the 75 % gate with margin. Remaining PARTIAL / NOT COVERED rows: AC-8.6 scene-change subset (labeled change-pair dataset not available), AC-NEW-5 hot-soak chamber (physical hardware), AC-7.1 / AC-7.2 + RESTRICT-CAM-2 (no AI-camera fixture), RESTRICT-HW-2 chamber portion (paired with AC-NEW-5).
## Epic Roadmap
| Order | Epic | Component | T-shirt | Story points | Dependencies |
|-------|------|-----------|---------|--------------|-------------|
| 1 | AZ-244: E-BOOT — Bootstrap & Initial Structure | repo scaffolding | M | 1321 | — |
| 2 | AZ-245: E-CC-LOG — Structured JSON Logging | cross-cutting | S | 58 | E-BOOT |
| 3 | AZ-246: E-CC-CONF — Configuration & Composition Root | cross-cutting | S | 58 | E-BOOT |
| 4 | AZ-247: E-CC-FDR-CLIENT — FDR Producer Client | cross-cutting | M | 813 | E-BOOT, E-CC-LOG |
| 5 | AZ-248: E-C13 — Flight Data Recorder | C13 | L | 2134 | E-BOOT, E-CC-LOG, E-CC-CONF, E-CC-FDR-CLIENT |
| 6 | AZ-249: E-C7 — On-Jetson Inference Runtime | C7 | L | 2134 | E-BOOT, E-CC-CONF, E-CC-FDR-CLIENT |
| 7 | AZ-250: E-C6 — Tile Cache + Spatial Index | C6 | M | 1321 | E-BOOT, E-CC-LOG, E-CC-CONF |
| 8 | AZ-251: E-C11 — Tile Manager | C11 | M | 1321 | E-C6, E-CC-CONF, E-CC-LOG |
| 9 | AZ-252: E-C10 — Pre-flight Cache Provisioning | C10 | M | 1321 | E-C6, E-C7, E-CC-LOG |
| 10 | AZ-253: E-C12 — Operator Pre-flight Orchestrator | C12 | M | 1321 | E-C10, E-C11, E-CC-LOG |
| 11 | AZ-254: E-C1 — Visual / Visual-Inertial Odometry | C1 | XL | 3455 | E-BOOT, E-CC-FDR-CLIENT, E-C7 |
| 12 | AZ-255: E-C2 — Visual Place Recognition | C2 | L | 2134 | E-C6, E-C7, E-CC-FDR-CLIENT |
| 13 | AZ-256: E-C2.5 — Inlier-based Re-rank | C2.5 | S | 58 | E-C2, E-C7, E-C6 (shared LightGlue helper) |
| 14 | AZ-257: E-C3 — Cross-Domain Matcher | C3 | L | 2134 | E-C2.5, E-C7 |
| 15 | AZ-258: E-C3.5 — AdHoP-Conditional Refinement | C3.5 | M | 813 | E-C3, E-C7 |
| 16 | AZ-259: E-C4 — Pose Estimator | C4 | M | 1321 | E-C3.5, E-C5 (shared GTSAM substrate) |
| 17 | AZ-260: E-C5 — State Estimator | C5 | XL | 3455 | E-C1, E-C4 (shared graph), E-CC-FDR-CLIENT |
| 18 | AZ-261: E-C8 — FC + GCS Adapter | C8 | L | 2134 | E-C5, E-CC-CONF, E-CC-LOG |
| 19 | AZ-262: E-BBT — Blackbox Tests (FT/NFT scenarios) | system-level tests | M | 1321 | every component epic |
**Total estimated effort**: 295477 story points across 19 epics (sum of t-shirt-band lower / upper bounds from `epics.md`). The two XL epics (E-C1 = AZ-254 and E-C5 = AZ-260) carry ~22 % of the upper-bound estimate alone.
## Key Decisions Made
| # | Decision | Rationale | Alternatives Rejected |
|---|----------|-----------|----------------------|
| 1 | Single Python+C++ monolith per binary track (ADR-001) | Latency budget (400 ms p95) + GTSAM substrate sharing + Jetson 8 GB shared memory | Multi-process (D-C1-1-SUB-A=(b)) — too much IPC overhead; ROS — adds runtime weight without flight-controller benefit |
| 2 | Build-time exclusion of unused `Strategy` implementations via per-binary CMake `BUILD_*` flags (ADR-002) | Binary size on 8 GB shared Jetson, AC-NEW-1 30 s boot budget, accidental-selection risk | Runtime-only selection — bigger binary, larger attack surface, harder cold-start; component licenses do not drive this decision |
| 3 | Shared GTSAM substrate between C4 (pose) and C5 (state) (ADR-003, D-C5-5 = (c)) | Native posterior covariance via `Marginals.marginalCovariance`; one numerical foundation | Independent EKF in C5 + Jacobian-only covariance — cannot deliver honest 6×6 |
| 4 | Process-level isolation of operator-side Tile Manager (ADR-004) — C11 not linked into airborne image | AC-8.4 in-flight no-write; defeats reflection / config-error attack vectors | Runtime gate alone — reflection / DI bug could re-introduce code path |
| 5 | Two execution tiers (ADR-005): Tier-1 workstation Docker + Tier-2 self-hosted Jetson | Cost (Jetson runner saturated) + AC-NEW-1 must run on real hardware | Single-tier Jetson-only — too slow / expensive for pre-merge CI |
| 6 | D-CROSS-LATENCY-1 hybrid (ADR-006): K=3 baseline auto-degrades to K=2 + Jacobian covariance under thermal throttle | Preserves AC-4.1 at +50 °C ambient at the cost of ~510 % accuracy | Static K=2 — wastes covariance precision in nominal conditions; static K=3 — blows the budget under throttle |
| 7 | Spoof-promotion gate (ADR-008): re-promote only after ≥10 s `gps_health == STABLE_NON_SPOOFED` AND visual-consistency check passes | AC-NEW-2 / AC-NEW-8 floor; defends against attacker turning spoof off briefly | Time-only gate (≥30 s) — slower mission recovery, still fool-able by transient honest GPS during attack |
| 8 | Interface-first components with constructor injection (ADR-009) | Multiple interchangeable strategies on the same interface (C1 has 3, C2 has 6+, C8 has 2) — selection via composition root only | Service-locator / global registry — couples runtime to import order, breaks tests, breaks build-time exclusion |
| 9 | OpenCV pinned to ≥4.12.0 (Mode B Fact #112) | CVE-2025-53644 mitigation; IPPE flags for solvePnP D-C4-1=(b) | Older OpenCV — known CVE; newer beta — not pinned in JetPack 6.2 |
| 10 | DISK + LightGlue replaces SuperPoint+SuperGlue for cross-domain matching (D-C3-1 = (a)) | License — SP+SG is Magic Leap noncommercial canonical; DISK+LightGlue is BSD-3-Clause | SuperPoint+SuperGlue — license incompatibility; XFeat — promising but unproven cross-domain |
| 11 | AC-NEW-4 / AC-NEW-7 text relaxed 2026-05-09 to Monte-Carlo-over-current-data with stated 95 % CI | D-PROJ-3 multi-flight fixture acquisition is out of scope this cycle; literal "≥100 flights" wording cannot be met | Block planning on D-PROJ-3 — cycle would not close; relaxed wording is documented residual risk in R11 |
## Open Questions
| # | Question | Impact | Assigned To |
|---|----------|--------|-------------|
| 1 | D-PROJ-2: parent-suite `satellite-provider` ingest endpoint + multi-flight voting layer not yet implemented service-side | F10 post-landing upload depends on this; R01; e2e mock-suite-sat-service fixture stands in for tests | Parent suite (cross-workspace; tracked in `_docs/_process_leftovers/2026-05-09_satellite-provider-design-tasks.md`) |
| 2 | D-PROJ-3: multi-flight fixture acquisition (Maxar Open Data Ukraine + AerialVL S03 + own multi-flight data) | AC-NEW-4 / AC-NEW-7 statistical headroom; R11 carryforward to next Plan cycle | Project lead |
| 3 | D-C8-2 runtime gate: companion-driven `MAV_CMD_SET_EKF_SOURCE_SET` switch lacks deployed precedent | R03 — IT-3 ArduPilot SITL validation is the lock gate; D-C8-2-FALLBACK options recorded in ADR-008 | Onboard team (gated by IT-3) |
| 4 | D-C2-12: DINOv2-feature-based matcher evaluation as a possible C3 backbone alternative | Could close D-C3-1 retrain cost concern; carryforward to next Plan cycle | Onboard team |
| 5 | AC-NEW-5 hot-soak chamber test (25 W @ +50 °C, 8 h, no throttle) | Physical hardware required; release-tag-blocking gate; out of scope for data-acquisition this cycle | Project lead |
| 6 | AC-7.1 / AC-7.2 / RESTRICT-CAM-2: AI-camera object localization pipeline | Out of scope for this cycle; deferred to a follow-up Plan cycle scoped to AI-camera integration | Future cycle (next Plan) |
| 7 | AC-8.6 scene-change subset: needs labeled change-pair dataset | Stale-tile match in active-conflict sectors — scene-change recall unmeasured (scale-ratio half is covered) | Future cycle |
## Artifact Index
| File | Description |
|------|-------------|
| `architecture.md` | System architecture, ADR set (ADR-001..ADR-009), 12 architectural principles, technology stack |
| `glossary.md` | Canonical project terminology (locked Phase 2a.0) |
| `system-flows.md` | F1F10 Mermaid sequence diagrams + flowcharts + per-flow data flow tables |
| `data_model.md` | PostgreSQL `tiles` (mirrored from `satellite-provider`) + flight + manifest schema; FAISS / TRT artifact layout; FDR record schema |
| `risk_mitigations.md` | 14-row risk register (R01..R14) with per-risk mitigation + contingency |
| `epics.md` | Local plan E-* IDs, t-shirt sizes, story-point ranges, dependencies, child-issue breakdowns; canonical `E-*``AZ-NN` mapping |
| `components/01_c1_vio/description.md``components/14_c13_fdr/description.md` | Per-component spec (interface, implementations, dependencies, ACs, NFRs, risks) |
| `components/01_c1_vio/tests.md``components/14_c13_fdr/tests.md` | Per-component test scenarios |
| `common-helpers/01_helper_imu_preintegrator.md``common-helpers/08_helper_descriptor_normaliser.md` | Shared helpers (IMU preintegrator, SE3 utils, LightGlue runtime, WGS converter, SHA-256 sidecar, engine filename schema, RANSAC filter, descriptor normaliser) |
| `tests/traceability-matrix.md` | AC ↔ scenario coverage; restriction ↔ scenario coverage |
| `tests/blackbox-tests.md`, `tests/performance-tests.md`, `tests/security-tests.md`, `tests/resource-limit-tests.md`, `tests/resilience-tests.md` | System-level FT / NFT scenario specs |
| `tests/test-data.md`, `tests/environment.md` | Fixture inventory + Tier-1/Tier-2 environment definition |
| `deployment/containerization.md`, `deployment/ci_cd_pipeline.md`, `deployment/environment_strategy.md`, `deployment/observability.md`, `deployment/deployment_procedures.md` | Deployment plan |
| `diagrams/components.drawio` | Component-level diagram (visual companion to `components/`) |
| `diagrams/flows/00_index.md` | Per-flow index pointing into `system-flows.md` |
## Quality Checklist Verification
All 8 checklist sections from `.cursor/skills/plan/steps/07_quality-checklist.md` pass for this cycle:
- **Blackbox Tests**: every AC + restriction in `tests/traceability-matrix.md`; restrictions verified by ≥1 scenario each (RESTRICT-CAM-2 deferred with documented mitigation); positive (FT-P) + negative (FT-N) balanced; Tier-1 Docker + Tier-2 Jetson defined in `tests/environment.md`; consumer treats system as black box (FC + GCS contracts only); CI integration in `deployment/ci_cd_pipeline.md`.
- **Architecture**: covers all `solution.md` capabilities; technology choices justified in § 2 of `architecture.md` + ADR-001..ADR-009; deployment model in `deployment/`; blackbox findings F6F10 reflected (Tier split, mock-suite-sat-service, two-binary CI emit).
- **Data Model**: every persistent entity from `architecture.md` § 4 defined in `data_model.md`; relationships have explicit FK cardinality; migration strategy is additive-only with ADR-recorded deprecation requirement; seed data = `satellite-provider` mirror of `tiles`; backward compatibility = `tiles` schema frozen on canonical columns.
- **Deployment**: containerization covers Tier-1 workstation Docker; CI/CD pipeline includes lint, test, security (SBOM diff, ASan), build, deploy stages; environment strategy covers dev / staging / production (Tier-1 + Tier-2 + Jetson production image); observability covers structured JSON logging + FDR + GCS STATUSTEXT; deployment procedures include rollback (per-flight key zeroisation, FDR rollover) and health checks (F2 takeoff verifier).
- **Components**: 14 components each follow SRP; no circular dependencies (R14 resolved via shared LightGlue helper); inter-component interfaces defined as `Protocol`/`ABC` per ADR-009; no orphan components — every component appears in at least one F1F10 flow; every blackbox scenario traceable through the component dependency graph.
- **Risks**: all High risks have mitigations + contingency (R01, R03, R11); mitigations reflected in `architecture.md` (ADR-004 enforcement scope, ADR-008 D-C8-2-FALLBACK), `tests/security-tests.md` (NFT-SEC-02 egress test), and `tests/traceability-matrix.md` (AC-text relaxation).
- **Tests**: every AC + restriction covered by ≥1 test (with PARTIAL/NOT-COVERED items having documented mitigation); 4 test types per component represented where applicable (unit/contract inside per-component `tests.md` + integration/performance/security/resilience at system level); test data management defined in `tests/test-data.md`.
- **Epics**: E-BOOT (AZ-244) "Bootstrap & Initial Structure" present; E-BBT (AZ-262) "Blackbox Tests" present; every component maps to a component epic (C1..C8, C10..C13 → AZ-254, AZ-255, AZ-256, AZ-257, AZ-258, AZ-259, AZ-260, AZ-261, AZ-252, AZ-251, AZ-253, AZ-248); dependency order matches `epics.md` "Implementation order"; acceptance criteria are measurable (per-epic IT/PT/ST IDs trace back to `traceability-matrix.md`).