# Solution Draft (Mode B revision 02)

> Mode B Phase 2 — engine Step 8 (Deliverable Formatting). Revised solution that supersedes [`solution_draft01.md`](solution_draft01.md) by integrating the Mode B Solution Assessment findings F1–F20 (Mode B fact cards #102–#113, Mode B sources #122–#131).
>
> **Research Output Class**: Technical-component selection (per [`../00_research/00_question_decomposition.md`](../00_research/00_question_decomposition.md)).
>
> **Mode**: B (assessment & revision of an existing draft). User chose option A on the Research Decision gate (2026-05-08). solution_draft01 remains on disk as the Mode A audit trail; this file overlays revisions only — it does NOT delete or rewrite solution_draft01.
>
> Backing artifacts (Mode A + Mode B addenda):
> - Question decomposition + scope: [`../00_research/00_question_decomposition.md`](../00_research/00_question_decomposition.md)
> - Source registry: [`../00_research/01_source_registry/00_summary.md`](../00_research/01_source_registry/00_summary.md) (#1–#121 Mode A; **Mode B addendum #122–#131** in [`MODEB_addendum.md`](../00_research/01_source_registry/MODEB_addendum.md))
> - Fact cards: [`../00_research/02_fact_cards/00_summary.md`](../00_research/02_fact_cards/00_summary.md) (#1–#101 Mode A; **Mode B addendum #102–#113** in [`MODEB_addendum.md`](../00_research/02_fact_cards/MODEB_addendum.md))
> - Component fit matrix: [`../00_research/06_component_fit_matrix/00_summary.md`](../00_research/06_component_fit_matrix/00_summary.md) + Mode A row files (`Cx_*.md`) + cross-gates [`99_cross_component_gates.md`](../00_research/06_component_fit_matrix/99_cross_component_gates.md); **Mode B revisions overlay** in [`MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md)
> - Project Constraint Matrix: [`../00_problem/problem.md`](../00_problem/problem.md), [`../00_problem/restrictions.md`](../00_problem/restrictions.md), [`../00_problem/acceptance_criteria.md`](../00_problem/acceptance_criteria.md), [`../00_problem/input_data/data_parameters.md`](../00_problem/input_data/data_parameters.md), [`../00_problem/input_data/expected_results/results_report.md`](../00_problem/input_data/expected_results/results_report.md)
> - Mode A draft (audit trail): [`solution_draft01.md`](solution_draft01.md)
>
> **Note on AC assessment** — same status as solution_draft01: the BLOCKING `00_ac_assessment.md` artifact was not extracted as a standalone file. Per-AC binding evidence remains distributed across per-component fact cards + Restrictions × Candidate-Modes sub-matrix sections in `06_component_fit_matrix/Cx_*.md`. Per `00_question_decomposition.md` line 4 this was a prior user decision and is accepted; Mode B Fact #106 documents the deviation explicitly and offers retroactive extraction on demand.

---

## Assessment Findings

Mode B audited solution_draft01 against the Project Constraint Matrix (PCM) and against 2025-2026 web research. The 20 Mode B findings collapse into 12 actionable revisions catalogued below. Full evidence chain in [`../00_research/02_fact_cards/MODEB_addendum.md`](../00_research/02_fact_cards/MODEB_addendum.md) Facts #102–#113.

| # | Old (solution_draft01) | Weak point (functional / security / performance / process) | New (solution_draft02) |
|---|---|---|---|
| **A1 / Fact #102** | C1 candidate table lists VINS-Mono with cell `Security: BSD permissive clean` and status `Selected (mandatory simple-baseline)` | **Security/license error**: Mode A Fact #28 + canonical github.com LICENCE (Source #122) confirm VINS-Mono is GPL-3.0 (copyleft viral), not BSD. Step-8 deliverable-formatting error in Mode A. | C1 candidate table: VINS-Mono cell corrected to `Security: GPL-3.0 (copyleft viral) — eligible only on D-C1-1 = (a) or (c)`. KLT+RANSAC re-labeled `Selected (mandatory simple-baseline)` per Mode A C1 Fact #35 (was `Selected (project-internal homemade fallback)`). OKVIS2 remains BSD/permissive-track lead per Mode A C1 Fact #31. **NEW (user directive 2026-05-08, see § Architecture C1 note)**: BOTH OKVIS2 + VINS-Mono are implemented behind a pluggable `VioStrategy` interface with config-driven selection, so the project can publish a comparative-study report in official docs and pick the runtime-deployed implementation by measured performance. **NEW sub-decision D-C1-1-SUB-A** (User, hard gate — cannot be deferred to Plan): how to link VINS-Mono GPL-3.0 alongside OKVIS2 BSD without making the entire deployment binary GPL-3.0 by viral license. Options proposed: build-config exclusion (production binary = OKVIS2 only; research/dev build = both); process-isolation (VINS-Mono as separate binary over IPC, viral linkage stops at process boundary); accept D-C1-1 = (a) GPL-3.0 track for entire deployment binary. |
| **A2 / Fact #103** | Component-interaction diagram budgets ~140-420 ms p95 with the upper end **exceeding AC-4.1's 400 ms p95 budget**; no slack reserved for MAVLink serialization, OS scheduling jitter, thermal throttle, FAISS p99, or FC-side IMU pre-integration | **Performance gap**: 420 ms p95 violates AC-4.1 at the upper end with no documented project-side margin. Real production stack overheads (≥40-100 ms in tail conditions per Sources #97 + #115 + AC-NEW-5 thermal envelope) are not budgeted. | NEW Plan-phase decision **D-CROSS-LATENCY-1** added: hybrid K=3 default + auto-degrade to K=2 + Jacobian-covariance under thermal throttle. NEW test **NFT-9 — Hot-soak latency distribution** required to validate p95+p99 distribution under NFT-3 conditions before lock. Component-interaction diagram updated with explicit budget partition. |
| **A3 / Fact #104** | Architecture cites OpenCV `solvePnPRansac(K, dist, ...)` but does NOT inventory that **camera intrinsics `K` and distortion `dist` for the deployed ADTi 20MP 20L V1 nav camera are PROJECT-LEVEL OPEN ITEMS** per `_docs/00_problem/problem.md` last sentence + `flight_derkachi/README.md` + `expected_results/results_report.md` § Known Gaps | **Process / functional gap**: hard prerequisite for AC-1.1/1.2 frame-center accuracy validation is missing from the Plan-phase decision registry. End-to-end accuracy claims cannot be validated without it. | NEW project-level decision **D-PROJ-1** added: camera calibration acquisition strategy. Recommendation **(d) hybrid: factory data sheet + ground-truth checkerboard refinement on each deployed unit**. Surfaced as CRITICAL Plan-phase gate; Test Spec greenfield Step 5 cannot lock end-to-end accuracy fixtures without it. |
| **A4 / Fact #105** | Architecture's AC-NEW-7 cache-poisoning safety story relies on a **Suite Sat Service-side multi-flight ingest voting layer** that is not audited for existence, contract, or build status | **Security gap**: AC-NEW-7 NFT-5 evidence cannot end-to-end pass without the Service contract; cross-flight error compounding is unmitigated if the Service-side voting layer is missing or unimplemented. | NEW project-level decision **D-PROJ-2** added: Suite Sat Service voting-layer contract verification. Recommendation **(a) verify + (b) draft contract from onboard side in parallel**. Surfaced as CRITICAL cross-suite gate requiring coordination with parent-suite Satellite Service team. |
| **A5 / Fact #106** | "Note on AC assessment" (lines 17-18) acknowledges Mode A Phase 1 BLOCKING `00_ac_assessment.md` artifact was not produced | **Process gap (acknowledged)**: per research SKILL.md a BLOCKING gate cannot be silently skipped. Per `00_question_decomposition.md` line 4 it was a prior user decision. | Mode B preserves the deviation as accepted per prior user decision. Adds explicit note that retroactive extraction from the per-component sub-matrix is a low-cost (~1-2 hour) operation if the canonical artifact is wanted before Plan-phase. Recorded in `_docs/_process_leftovers/` if Plan-phase needs the standalone form. |
| **A6 / Fact #107** | Architecture states GTSAM iSAM2 satisfies AC-4.5 (look-back refinement of past estimates) without scoping the FC-consumption pathway; IT-10 validates per-FC unit conversion not AC-4.5 itself | **Functional scope error**: ArduPilot `AP_GPS_MAV` and iNav `mspGPSReceiveNewData()` consume only the latest GPS frame — neither supports retroactive correction of past frames. AC-4.5 satisfied as "internal smoothing + corrected current-frame emission", NOT as "FC retroactively corrects past flight log". | C5 candidate table Pinned Mode/Config column updated: AC-4.5 scope now reads "internal smoothing only, NOT FC retroactive correction". NEW test **IT-11 — Smoothing-loop look-back accuracy** added: validates GTSAM iSAM2's smoothed past-keyframe poses against ground-truth at smoothing convergence (independent of FC-side consumption). FDR (AC-NEW-3) MUST log smoothed past-frame estimates so post-mission analysis can verify AC-4.5. |
| **A7 / Fact #108** | Architecture omits the SQ2 Decision 2 **AdHoP refinement loop** (between matcher and PnP) and SQ2 Decision 3 **Top-N inlier-based re-rank** (between VPR and matcher) sub-stages that question_decomposition.md lines 175-178 explicitly promoted to "explicit named sub-stages" | **Architectural gap**: SQ2 closure committed to two named sub-stages that the architecture diagram and per-component tables do not reflect. | Component-interaction diagram updated with two new sub-stages. NEW C2.5 row "Top-N re-rank by inlier count" (between C2 and C3): thin wrapper around C3 matcher's RANSAC inlier counter; ranks top-K candidates by inlier count from a single-pair LightGlue/XFeat invocation per candidate; outputs top-N ⊆ top-K for full-depth C3 matching. NEW C3.5 row "AdHoP-conditional refinement" (between C3 and C4): OrthoLoC AdHoP method-agnostic perspective preconditioning per Mode A SQ2 Source #40; invoked only when initial reprojection error exceeds a threshold; worst-case 2× C3 latency when triggered. |
| **A8 / Fact #109** | Architecture has **no MAVLink message-signing posture**; CVE-2026-1579 (CVSS 9.8 CRITICAL) flags MAVLink protocol as lacking cryptographic authentication by default | **Security gap (Critical CVSS)**: arbitrary unauthenticated MAVLink commands can be injected, including SERIAL_CONTROL for interactive shell access on the FC. Documented mitigation: enable MAVLink 2.0 message signing (Source #128). iNav has no signing implementation (Source #129) — explicit cross-FC asymmetry. | NEW Plan-phase decision **D-C8-9** added: MAVLink 2.0 message signing posture per FC. Recommendation **(d) hybrid: signing on companion ↔ AP wired channel + per-flight key rotation**. iNav-side documented as accepted residual risk + Plan-phase carryforward to propose iNav firmware feature-request. NEW test **NFT-8 — MAVLink message-signing verification** added: SBOM dump confirms passkey configuration for AP signing channel. |
| **A9 / Fact #110** | C2 candidate table omits MegaLoc + UltraVPR (D-C2-11 deferred MegaLoc evaluation to "post-research session") | **Currency gap**: 2025-2026 SOTA candidates (MegaLoc CVPR 2025 MIT, UltraVPR RAL 2025 / ICRA 2026 MIT) are aerial-validated and Jetson-runtime-documented (UltraVPR 44 Hz on Jetson Orin NX). The deferred recommendation in solution_draft01 is now technically obsolete given Mode B web research. | C2 candidate table extended with **UltraVPR as Documentary Lead PRIMARY** on BSD/permissive C2 axis (rotation-invariant, unsupervised aerial pretrain, MIT, 44 Hz Jetson Orin NX) and **MegaLoc as Documentary Lead SECONDARY** (broader-applicability, MIT, torch.hub install, AirZoo-validated for aerial). Status of D-C2-11 changed from "deferred to post-research session" to "elevate UltraVPR primary + MegaLoc secondary at Plan-phase Jetson MVE under D-C1-2 / D-C2-4 expanded scope". MixVPR demoted from "recommended primary on BSD/permissive track" to "mandatory simple-baseline" only. SelaVPR (DINOv2-L) strengthened as secondary per Fact #113 cross-modal evidence. |
| **A10 / Fact #111** | D-C8-2 = (b) companion-driven `MAV_CMD_SET_EKF_SOURCE_SET` switch is recommended as the production pattern, citing NGPS/Auterion as evidence | **Production-deployment gap**: Source #130 (re-verified 2026-05-08) confirms ArduPilot supports the command at firmware level since August 2021 but **no production-deployed GCS or companion is publicly documented as implementing the companion-driven switch pattern**. Mode A SQ1 Sources #25–#37 document that NGPS/Auterion exist as deployed systems but do NOT confirm their internal source-set switching mechanism. The project will be establishing the canonical pattern itself. | D-C8-2 status downgraded from `Selected` to **`Selected with runtime gate`** per Step 7.5.3 carve-out — runtime gate = ArduPilot Plane SITL validation by IT-3 (Spoofing-promotion latency) before lock. NEW sub-decision **D-C8-2-FALLBACK** added: if SITL validation fails, options (a) operator-manual RC aux switch with relaxed AC-NEW-2 wording; (b) operator-warning STATUSTEXT instead of automated switch; (c) escalate to ArduPilot dev community to characterize firmware-side switch latency. |
| **A11 / Fact #112** | C4 candidate table cites "OpenCV 4.x" without a minimum patch version | **Security gap (Critical CVSS)**: CVE-2025-53644 (CVSS 9.8) — uninitialized stack pointer on crafted JPEG triggers heap buffer write; affects 4.10.0 / 4.11.0; **fixed in 4.12.0**. C4 + C1 + FDR thumbnail re-load + tile cache import are all paths where a crafted JPEG could reach OpenCV's `imread` / `imdecode`. | OpenCV pin tightened to **`≥4.12.0`** in C1 + C4 + C6 candidate rows. NEW Plan-phase decision **D-CROSS-CVE-1** added: dependency security pinning posture. Recommendation **(a) lock to specific patched versions of all CVE-affected dependencies + (b) maintain a project SBOM with monthly CVE re-scan**. |
| **A12 / Fact #113** | C2 + C3 cross-domain story rests on D-C3-1 = (a) DISK+LightGlue retrain on aerial-domain corpus to close UAV→satellite gap | **Currency caveat (Medium confidence)**: 2026 SAR-optical 24-matcher benchmark + XoFTR research (Source #131) found foundation-model features (DINOv2) provide modality invariance even without explicit cross-modal training — this strengthens (does not invalidate) the case for keeping SelaVPR (DINOv2-L) as secondary alongside UltraVPR primary, and suggests a DINOv2-feature-based matcher could potentially close the cross-domain gap without the D-C2-1 ~1-2-week aerial retrain. | NEW Plan-phase decision **D-C2-12** added: DINOv2-backbone feature-extractor evaluation for cross-domain matching. Plan-phase decision: defer to Jetson MVE; potentially closes D-C3-1 retrain cost via DINOv2-feature-based matcher (e.g., DINOv2 + LightGlue or DINOv2 + paired matcher) without requiring D-C2-1 aerial retrain. Carryforward research item. |

**Out-of-scope for Mode B revision** (no changes vs solution_draft01):
- C1 OKVIS2 selection (Mode A C1 Fact #31 confirmed; no Mode B contradicting evidence).
- C3 DISK+LightGlue D-C3-1 = (a) recommendation (Mode B Fact #113 reinforces but does not displace).
- C5 GTSAM iSAM2 + Manual ESKF dual-track (Mode A Facts #88-#91 confirmed; Mode B Fact #107 only revises AC-4.5 scope wording).
- C6 mirror-of-suite-pattern primary (Mode A Fact #92 confirmed; OpenCV pin in C6 row updated per Fact #112).
- C7 TensorRT-native primary (Mode A Fact #94 confirmed).
- C8 pymavlink (AP) + MSP2_SENSOR_GPS (iNav) primary (Mode A Facts #97-#99 confirmed; D-C8-2 status revised per A10; D-C8-9 added per A8).
- C10 D-C6-3 + D-C7-7 confirmation pipelines (Mode A Facts #100-#101 confirmed).
- Existing/Competitor systems analysis (Mode A SQ1 saturated; no Mode B contradicting evidence).

---

## Product Solution Description

A Jetson-Orin-Nano-Super-hosted companion-PC system that produces a GPS-equivalent WGS84 position estimate (with honest 6×6 covariance) for a fixed-wing UAV operating in a GPS-denied or GPS-spoofed environment, by fusing pre-flight-cached satellite tile imagery (from the parent-suite Azaion Satellite Service) with live nav-camera frames and FC-supplied IMU + attitude.

The system implements the canonical hierarchical GPS-denied pipeline `retrieval → re-rank → matching → AdHoP-conditional refinement → pose → fusion` (per SQ2 surveys converging on this pattern + SQ2 Decisions 2+3 promoted to explicit named sub-stages, Sources #38–#42), runs on the pinned Jetson Orin Nano Super hardware (Source #105 hardware-tied constraints honored), and delivers the final pose to the FC via per-FC external-positioning interfaces — MAVLink `GPS_INPUT` for ArduPilot Plane (verified Source #4 + #106 + #107 + Mode B Fact #109 mitigation D-C8-9 = (d) MAVLink-2.0-signing-on-companion↔AP-wired-channel), MSP2 `MSP2_SENSOR_GPS` for iNav (verified Source #111 + #112 + #113; iNav has no signing per Mode B Fact #109 + Source #129 — accepted residual risk). PX4 is explicitly out of scope per `restrictions.md`.

### Component-interaction diagram (pre-flight + runtime, REVISED)

```
PRE-FLIGHT (operator-managed, on-Jetson) ─────────────────────────────────────────
   parent-suite Satellite Service ─→ tile cache (PostgreSQL btree + filesystem)
                                  ─→ C2 VPR backbone (TensorRT engine, INT8+FP16)
                                       └─→ per-tile descriptors → FAISS HNSW index
                                                         (.index file written
                                                          via faiss.write_index +
                                                          atomicwrites + SHA-256
                                                          content-hash gate)
   ONNX models (C2/C2.5/C3/C3.5/C1) ─→ Polygraphy / trtexec / IBuilderConfig hybrid
                              orchestration → TensorRT engines
                              (.engine files, SM 87 / JetPack 6.2 / TRT 10.3)
   Camera calibration         ─→ D-PROJ-1 hybrid: factory K + dist data sheet from
                                  ADTi + ground-truth checkerboard refinement on
                                  each deployed unit (~1 day per unit)

TAKEOFF LOAD (≤5 s, AC-NEW-1) ────────────────────────────────────────────────────
   FAISS read_index(IO_FLAG_MMAP_IFC) + content-hash verify → ready
   IRuntime.deserializeCudaEngine per-engine → ready
   MAVLink 2.0 signing key handshake (companion ↔ AP wired channel) → ready

RUNTIME (3 Hz nav-camera, 100-200 Hz IMU; AC-4.1 <400 ms p95 budget) ──────────────
   nav-camera frame ─→ C1 VioStrategy (config-selected: Okvis2 |
                          VinsMono [research-build only per D-C1-1-SUB-A] |
                          KltRansac) — production-default Okvis2  ~30-50 ms
                   ─→ C2 UltraVPR query → top-K=10 satellite tile retrieval
                                          (D-C2-11 revised; UltraVPR primary)
                                          (~5-10 ms via FAISS HNSW)
                   ─→ C2.5 Top-N re-rank by inlier count (NEW: SQ2 Dec 3)
                          single-pair LightGlue per candidate → top-N=3
                                                                  (~30-60 ms)
                   ─→ C3 DISK+LightGlue × N=3 pairs (D-CROSS-LATENCY-1
                          hybrid: K=3 default, auto-degrade to K=2 under
                          thermal throttle)                       (~90-180 ms FP16)
                   ─→ C3.5 AdHoP-conditional refinement (NEW: SQ2 Dec 2)
                          invoked only if reprojection error exceeds threshold
                                                                  (~+30-90 ms when
                                                                   triggered)
                   ─→ C4 OpenCV ≥4.12.0 solvePnPRansac (D-C4-1 = (b) IPPE
                          flags)                                  (~5-15 ms)
                   ─→ wrap in GTSAM Marginals (D-C4-2 = (b);
                          D-CROSS-LATENCY-1 hybrid auto-degrades to
                          Jacobian-based covariance via D-C4-2 = (a) under
                          thermal throttle)                       (~30-90 ms)
   FC IMU + attitude ─→ C5 GTSAM iSAM2 + CombinedImuFactor + PriorFactorPose3
                              (~2-5 ms per update at D-C5-5 = (c))
                              └─→ posterior 6×6 covariance via Marginals
                              └─→ AC-4.5 internal smoothing (NOT FC-side
                                   retroactive correction per Mode B Fact #107)
                                              ─→ C8 per-FC unit conversion
                                                   ├─→ pymavlink GPS_INPUT (AP)
                                                   │     + MAVLink 2.0 signing
                                                   │     (D-C8-9 = (d))
                                                   └─→ MSP2_SENSOR_GPS (iNav,
                                                       unsigned residual risk)
                                                       (5 Hz periodic)

   total runtime budget: see D-CROSS-LATENCY-1 partition below
```

### AC-4.1 latency budget partition (D-CROSS-LATENCY-1, NEW)

| Stage | K=3 baseline (steady-state) | K=2 + Jacobian-cov (thermal-throttle hybrid) | NFT-9 measurement target |
|---|---|---|---|
| C1 OKVIS2 VIO | 30-50 ms | 30-50 ms | p95 ≤ 60 ms |
| C2 UltraVPR query | 5-10 ms | 5-10 ms | p95 ≤ 15 ms |
| C2.5 Top-N re-rank | 30-60 ms (1 single-pair LightGlue × top-K=10) | 30-60 ms | p95 ≤ 80 ms |
| C3 DISK+LightGlue × N | 90-180 ms (N=3) | 60-120 ms (N=2) | p95 ≤ 200 ms (steady) / ≤ 140 ms (thermal-throttle) |
| C3.5 AdHoP (conditional) | 0-90 ms (worst-case 2×) | 0-60 ms | p99 ≤ 100 ms when triggered |
| C4 solvePnPRansac | 5-15 ms | 5-15 ms | p95 ≤ 25 ms |
| C4 covariance recovery | 30-90 ms (GTSAM Marginals D-C4-2 = (b)) | 5-15 ms (Jacobian D-C4-2 = (a)) | p95 ≤ 100 ms (steady) / ≤ 25 ms (thermal-throttle) |
| C5 iSAM2 update | 2-5 ms | 2-5 ms | p95 ≤ 15 ms |
| MAVLink/MSP2 serialization + UART/USB transmission | 5-20 ms | 5-20 ms | p95 ≤ 30 ms |
| OS scheduling jitter | 10-30 ms | 10-30 ms | p99 ≤ 50 ms |
| **Project budget total** | **207-450 ms** (steady-state) | **152-325 ms** (hybrid degraded) | p95 ≤ **400 ms** (AC-4.1 hard bound) |

The hybrid auto-degrade is triggered by the Jetson's thermal-throttle telemetry crossing a configurable temperature/clock threshold (set per D-C7-9 JetPack 6.2 + TensorRT 10.3 lock); it preserves AC-4.1 satisfaction at +50 °C ambient (AC-NEW-5) at the cost of ~5-10% accuracy loss (NFT-4 false-position safety budget remains satisfied per Plan-phase Jetson MVE validation).

---

## Existing/Competitor Solutions Analysis

(Unchanged from solution_draft01 — Mode B web research did not surface new competitor systems.)

| System | Class | Stack signature | Relation to this project |
|---|---|---|---|
| **Twist Robotics OSCAR** (Source #25) | Deployed peer (Ukraine theater) | Visual navigation companion; closed-source | Closest peer system; deployed in theater the project will operate in. Confirms operational viability of the canonical pipeline shape. |
| **Auterion Artemis / Skynode N** (Sources #31+#32) | Commercial deployed (Ukraine-tested) | Skynode N + Visual Navigation; 1000-mile deep-strike demonstrated; closed-source proprietary stack | Demonstrates Jetson-class hardware can host GPS-denied companion at deployed-mission scale. Validates the pinned hardware target. |
| **NGPS (snktshrma/ngps_flight)** (Source #33) | Open-source (ArduPilot GSoC 2024) | LightGlue + SuperPoint + UKF + VISION_POSITION_ESTIMATE | Closest open-source pipeline-match. Confirms ArduPilot Plane + visual-localization companion is operationally validated. **License gap**: relies on Magic Leap-noncommercial canonical SP weights — same hard disqualifier this project hits in D-C3-1, mitigated by D-C3-1 = (a) DISK+LightGlue swap. |
| **Vantor Raptor** (Source #30) | Commercial deployed | GPS-denied UAV navigation + coordinate extraction | Validates dual-purpose pose + object-localization output. Aligns with project AC-7.x object-localization requirements. |
| **DARPA FLA (T&E review)** (Source #35) | Defense program lineage | GPS-denied autonomy with onboard compute | Provides T&E reference for AC-NEW-4 false-position safety budget validation methodology. |
| **DSMAC / TERCOM lineage** (Source #36) | Defense legacy | Digital Scene Matching Area Correlator + Terrain Contour Matching | Historical proof point that the project's "match against pre-cached imagery" core idea predates modern CV by decades; modern equivalents (this project) trade hand-engineered correlators for learned VPR + matchers. |

**Key delta vs existing systems** (REVISED): this project (a) supports both ArduPilot Plane AND iNav (no other open-source GPS-denied companion targets iNav per SQ6 saturation), (b) enforces an explicit AC-NEW-7 cache-poisoning safety budget across the descriptor cache + tile cache + Suite Sat Service pipeline (with D-PROJ-2 cross-suite contract verification), (c) ships an honest 6×6 posterior covariance per AC-NEW-4 via a GTSAM-shared-substrate hybrid (D-C4-2 + D-C5-5 + D-C8-8 cross-component coupling), and (d) **defends the companion ↔ FC link with MAVLink 2.0 message signing on ArduPilot per D-C8-9 = (d) — an explicit security-posture gain over NGPS / OSCAR / Skynode N which (per published material at time of access) do not document MAVLink message signing on the companion link**.

---

## Architecture

The solution is decomposed into nine components (C1–C8 + C10) plus two new sub-stages (C2.5 + C3.5) promoted from SQ2 closure (Mode B Fact #108). C9 was dropped in the SQ7/C9 restructure 2026-05-08 and deferred to Test Spec greenfield Step 5. Per-component candidate tables follow. **All "Selected" candidates have an MVE link in the Restrictions × Candidate-Modes sub-matrix sections** of [`../00_research/06_component_fit_matrix/Cx_*.md`](../00_research/06_component_fit_matrix/) per Step 7.5.3 decision rules. **Mode B revisions** to candidate-row statuses are catalogued in [`MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md); only the rows with Mode B-revised cells are reproduced below for brevity (unchanged rows mirror solution_draft01 verbatim).

### Component: C1 — Visual / Visual-Inertial Odometry (REVISED per Mode B Fact #102 + 2026-05-08 user directive)

**User directive (2026-05-08 follow-up to A1)**: BOTH OKVIS2 and VINS-Mono are implemented behind a pluggable `VioStrategy` interface with config-driven selection. The motivation is twofold: (a) enable a comparative-study report in official docs that names both implementations and the measured performance delta on real flight data; (b) lock the production-deployed implementation by measured performance on the project's actual operating context (Jetson Orin Nano Super + ADTi 20MP 20L V1 nav camera + Derkachi-class footage). KLT+RANSAC remains the mandatory simple-baseline per the engine's Component Option Breadth rule and is implemented as a third `VioStrategy` so the comparison study covers the engine-required baseline as well.

#### `VioStrategy` interface (Strategy/Adapter pattern)

```python
class VioStrategy(Protocol):
    """Pluggable VIO frontend. Selected at startup via config; not hot-swappable mid-flight."""
    def initialize(self, intrinsics: CameraIntrinsics, imu_calibration: ImuCalibration) -> None: ...
    def process_frame(self, frame: NavCameraFrame, imu_window: ImuWindow) -> VioOutput: ...
    def reset(self) -> None: ...
    def name(self) -> str: ...
    def license(self) -> str: ...                          # for SBOM + AC-NEW-3 FDR
    def is_production_eligible(self, license_track: LicenseTrack) -> bool: ...

class VioOutput(NamedTuple):
    relative_pose: SE3                                     # per-frame relative pose
    relative_pose_covariance_6x6: np.ndarray               # for AC-NEW-4 honesty
    imu_bias_estimate: ImuBias
    feature_quality: FeatureQuality                        # for D-CROSS-LATENCY-1 thermal-throttle decision
```

Three concrete implementations: `Okvis2VioStrategy`, `VinsMonoVioStrategy`, `KltRansacVioStrategy`. Selection is driven by config (`vio.strategy: okvis2 | vins_mono | klt_ransac`). FDR (AC-NEW-3) records the active strategy `name()` + `license()` per flight so the post-mission report can correlate accuracy results with the strategy used. Comparative-study reports (see new test **IT-12** below) replay the same flight footage through all three strategies and emit a single side-by-side accuracy + latency table.

#### Sub-decision D-C1-1-SUB-A — LOCKED 2026-05-08 to option (a) build-config exclusion

**Critical thinking flag** (preserved for audit trail): linking GPL-3.0 (VINS-Mono) and BSD-3 (OKVIS2) into the same deployed static binary makes the entire binary GPL-3.0 by viral license — even if config selects OKVIS2 at runtime. The user's stated intent ("use OKVIS in a real-world application") implies a BSD/permissive deployment binary, which is incompatible with statically linking VINS-Mono. The interface pattern itself does not solve this; an additional build/linkage policy is required.

| Option | Description | Viral-linkage handled? | Comparative-study still possible? | Engineering cost | Verdict |
|---|---|---|---|---|---|
| **(a)** Build-config exclusion | Production binary built with `BUILD_VINS_MONO=OFF` → only `Okvis2VioStrategy` + `KltRansacVioStrategy` linked; research/dev build with `BUILD_VINS_MONO=ON` → all three strategies linked. CI publishes both binaries; production deploys only the BSD-clean one. | ✅ Production binary is BSD/Apache clean | ✅ Research build runs the comparative study; results published to docs | Low (~1 day CMake config + CI pipeline split) | **LOCKED 2026-05-08 (User)** |
| **(b)** Process-isolation IPC | `VinsMonoVioStrategy` lives in a separate binary that talks to the main companion over UNIX domain socket / shared-memory ring buffer; viral linkage stops at process boundary. Both binaries deployable side-by-side; main companion stays Apache/BSD. | ✅ Process boundary breaks viral linkage | ✅ Both run side-by-side at runtime in research mode | High (~1-2 wk IPC design + serialization + IPC latency budget on Jetson + per-frame allocator overhead, conflicts with D-CROSS-LATENCY-1 budget) | Rejected (cost + latency budget conflict) |
| **(c)** Accept D-C1-1 = (a) GPL-3.0 entire deployment binary | Whole companion (including pymavlink LGPL-3.0 + GTSAM BSD + FAISS MIT + OpenCV BSD + ...) ships under GPL-3.0; source disclosure obligation triggered for the entire onboard binary | ❌ Trades off restrictions.md Apache/BSD-track preference | ✅ Single binary, no split | Low at code level, high at policy level | Rejected (policy cost) |

**Locked verdict**: **(a) build-config exclusion**. Production binary stays BSD/permissive clean; research binary published alongside enables the comparative study and docs report. Aligns existing D-C1-1 = (c) "both tracks open" with operational reality by mapping it to "both tracks built; production deploy is permissive-track binary". CMake flag spec: `option(BUILD_VINS_MONO "Include VINS-Mono GPL-3.0 VioStrategy implementation; production builds MUST set OFF" OFF)`. Production CI job builds with `-DBUILD_VINS_MONO=OFF` and asserts via SBOM dump that no GPL-3.0 symbol from `vins_mono` is present. Research CI job builds with `-DBUILD_VINS_MONO=ON` and emits a separate research-binary artifact.

#### Candidate table

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **`Okvis2VioStrategy` → OKVIS2** (modern-competitive-lead, BSD/permissive track) | C++ + ROS wrapper behind VioStrategy; smartroboticslab/okvis2 | Loosely-coupled VIO with stereo+IMU optionable; for this project mono+IMU mode; outputs per-frame relative pose + IMU bias estimates via `VioOutput` | Best modern accuracy on cross-domain tracking; permissive (BSD); **production-eligible on BSD/permissive track AND on GPL-3.0 track** | C++ + ROS dependency; ~30-50 ms per frame on Jetson Orin Nano Super extrapolation | C++17, ROS Noetic optional, IMU at 100-200 Hz | BSD-3-Clause clean | ~1-2 wk integration + ~3 days VioStrategy adapter | MVE: see [`../00_research/02_fact_cards/C1_vio.md`](../00_research/02_fact_cards/C1_vio.md); docs: Sources #47+#48+#56 | **Selected (modern-competitive-lead)** — production-default if IT-12 comparative study confirms material accuracy lead over VINS-Mono |
| **`VinsMonoVioStrategy` → VINS-Mono** (comparative-baseline) ← **REVISED Mode B Fact #102 + 2026-05-08 user directive** | C++ + ROS wrapper behind VioStrategy; HKUST-Aerial-Robotics/VINS-Mono | Mono+IMU loosely-coupled VIO; outputs per-frame relative pose + IMU bias estimates via `VioOutput` | Stable since 2018; widely documented; **canonical academic baseline for the comparative-study docs report** | Older accuracy; **GPL-3.0 viral linkage forces D-C1-1-SUB-A build/link policy decision before any deployed binary including this strategy can ship** | C++17, ROS Noetic optional, IMU at 100-200 Hz | **GPL-3.0 (copyleft viral)** — production-eligible only if D-C1-1-SUB-A = (b) process-isolation OR D-C1-1 = (a) GPL-3.0 track; research/dev build always eligible per D-C1-1-SUB-A = (a) | ~3-5 days adapter + ~3-5 days build-config split (if D-C1-1-SUB-A = (a)) | MVE: see fact card; docs: Sources #43+#55 + Mode B Source #122 (canonical LICENCE) | **Selected via `VioStrategy` interface for comparative study + research/dev builds**; production-deployed only if D-C1-1-SUB-A resolves to a non-(a) option AND IT-12 confirms VINS-Mono outperforms OKVIS2 on project's operating context |
| **`KltRansacVioStrategy` → KLT+RANSAC** (mandatory simple-baseline) ← **REVISED Mode B Fact #102** | OpenCV ≥4.12.0 pure-Python wrapper behind VioStrategy ← OpenCV pin tightened per Mode B Fact #112 | KLT optical flow + 5-point/homography RANSAC essential-matrix → pose decomposition; outputs `VioOutput` (with degraded covariance estimate since no IMU fusion at this layer) | Pure OpenCV; no C++ dependency; pure-VO baseline; engine-rule-required mandatory simple-baseline per Mode A C1 Fact #35 | No IMU fusion (delegated to C5); ~5-10 ms per frame on Jetson | OpenCV ≥4.12.0; IMU bypassed | Apache-2.0 + OpenCV BSD/Apache | ~3-5 days adapter | MVE: see fact card; docs: Source #53 + Mode B Source #127 (CVE-2025-53644 driving pin) | **Selected (mandatory simple-baseline)** — production-eligible on both license tracks; comparative-study reference baseline |

**Exact-fit evidence** (REVISED):
- Project constraints checked: AC-1.3 cumulative drift; AC-2.1a frame-to-frame registration; AC-3.1 outlier tolerance; AC-3.2 sharp-turn behavior; AC-4.1 + AC-4.2 latency + memory; **CVE-2025-53644 mitigation via OpenCV ≥4.12.0 pin**; **D-C1-1-SUB-A build/link policy for GPL-3.0 viral-linkage containment**.
- Evidence: `02_fact_cards/C1_vio.md` (Mode A) + `02_fact_cards/MODEB_addendum.md` Facts #102 + #112 (Mode B); Sources #43+#47+#48+#53+#55+#56 (Mode A) + #122 + #127 (Mode B).
- Disqualifiers: VINS-Fusion + OpenVINS + VINS-Mono GPL-3.0 contingent on D-C1-1 + D-C1-1-SUB-A resolution. Production-deployed VINS-Mono additionally contingent on IT-12 comparative-study verdict.
- Restrictions × Candidate-Modes sub-matrix: see [`../00_research/06_component_fit_matrix/C1_vio.md`](../00_research/06_component_fit_matrix/C1_vio.md) (Mode A) + [`MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md) (Mode B overlay).
- API capability gates: ✅ MVE saved for all 3 implementations behind `VioStrategy` interface.

#### Single-Responsibility check (per coderule.mdc)

The `VioStrategy` interface owns "produce a `VioOutput` from a frame + IMU window per the strategy's algorithm". Per-strategy concerns (OKVIS2's ROS bring-up, VINS-Mono's GPL-3.0 build flag, KLT+RANSAC's degraded-covariance shape) live inside the concrete implementations, not in the interface. The shared coordinator (`VioPipeline`) owns config-driven strategy selection + FDR provenance logging + per-frame metric collection — it does NOT contain strategy-specific branches. License-track filtering (`is_production_eligible`) is delegated to each strategy because the answer depends on the strategy's own license, satisfying the SRP rule "Logic specific to a platform, variant, or environment belongs in the class that owns that variant".

### Component: C2 — Visual Place Recognition (REVISED per Mode B Fact #110)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **UltraVPR** (Documentary Lead PRIMARY, BSD/permissive track) ← **NEW Mode B Fact #110** | PyTorch / ONNX; cbbhuxx/UltraVPR | Unsupervised lightweight rotation-invariant aerial VPR; ONNX export; designed for UAV multi-heading flights | MIT throughout; **44 Hz on Jetson Orin NX** (Orin-Nano-Super-class extrapolation expected ±20%); rotation-invariant (closes multi-heading aerial-flight gap); unsupervised aerial-pretrain (closes D-C2-1 retrain cost); RAL 2025 + ICRA 2026 | New (RAL 2025); requires Plan-phase Jetson Orin Nano Super MVE under expanded D-C1-2 / D-C2-4 scope | PyTorch 2.x; ONNX export | MIT clean | ~3-5 days base + 0 wk D-C2-1 retrain (unsupervised pretrain on UAV data) | MVE: deferred to Jetson MVE phase; docs: Mode B Source #124 | **Documentary Lead PRIMARY on BSD/permissive C2 axis** — strongest fit on project's pinned operating context |
| **MegaLoc** (Documentary Lead SECONDARY, BSD/permissive track, broader-applicability) ← **NEW Mode B Fact #110** | PyTorch / torch.hub; gmberton/megaloc | Unified retrieval model trained on multiple methods + datasets; fine-tunable on aerial via AirZoo benchmark recipe | MIT throughout; SOTA on multiple VPR datasets; CVPR 2025; torch.hub install path; AirZoo aerial validation (Mode B Source #125) | New (Feb 2025); requires Plan-phase Jetson MVE | PyTorch 2.x | MIT clean | ~3-5 days base | MVE: deferred to Jetson MVE phase; docs: Mode B Sources #123 + #125 | **Documentary Lead SECONDARY on BSD/permissive C2 axis** — broader-applicability fallback if UltraVPR fails Jetson MVE |
| **MixVPR** (mandatory simple-baseline, BSD/permissive track) ← **REVISED Mode B Fact #110** | PyTorch; amaralibey/MixVPR | ResNet50 backbone + MLP-Mixer aggregator; output dimension 2048-D float32 (or 512-D / 256-D `cropToDim` per D-C6-1 = halfvec); input 320×320 | MIT throughout; modest descriptor budget (~6.5% of AC-8.3 cache); active maintenance; engine-required mandatory baseline | Street-view-pretrained — D-C2-1 retrain on aerial corpus required | PyTorch 2.x; ONNX export verified | MIT clean | ~3-5 days base + ~1-2 wk D-C2-1 retrain | MVE: see [`../00_research/02_fact_cards/C2_vpr.md`](../00_research/02_fact_cards/C2_vpr.md); docs: Sources #57+#58+#61 | **Selected (mandatory simple-baseline)** — demoted from "recommended primary" (UltraVPR took that slot per Mode B Fact #110) |
| **SelaVPR** (modern-competitive-lead-secondary, BSD/permissive track) ← **STRENGTHENED Mode B Fact #113** | PyTorch; Lu-Feng/SelaVPR | DINOv2 ViT-L two-stage (global + local); 1024-D global + on-demand local features | MIT; lift from two-stage; 1024-D smallest single-stage cache; **DINOv2-L backbone provides modality-invariant features per Mode B Fact #113 cross-modal evidence** | DINOv2 ViT-L is 3.5× larger than ViT-B; D-C2-5 + D-C2-7 re-rank gates | PyTorch 2.x; DINOv2 ViT-L export | MIT clean | ~3-5 days base + ~1-2 wk D-C2-1 retrain | MVE: see fact card; docs: Sources #62+#63 + Mode B Source #131 | **Selected (modern-competitive-lead-secondary)** — strengthened by Mode B cross-modal contrarian evidence |
| **SALAD** (modern-competitive-lead, GPL-3.0 track) | PyTorch; serizba/salad | DINOv2 ViT-B + optimal-transport aggregator; output 8448-D / 2112-D / 544-D per D-C2-6; input 322×322 | +5-7 R@1 over MixVPR-2048 on MSLS Challenge | GPL-3.0; D-C2-5 ViT export risk; descriptor budget at full size 27% of AC-8.3 | PyTorch 2.x; DINOv2 ViT-B export | GPL-3.0 contingent | ~3-5 days base + ~1-2 wk D-C2-1 retrain | MVE: see fact card; docs: Sources #59+#60 | **Selected on GPL-3.0 track only** — eligible if D-C1-1 = (a) or (c) (unchanged) |
| **EigenPlaces** (BSD/permissive sibling) | PyTorch; gmberton/EigenPlaces | ResNet-50 + GeM + FC viewpoint-robust training; 2048-D / 512-D / 256-D / 128-D per D-C2-10 | MIT throughout; viewpoint-robust training paradigm; eleven sibling modes | Older approach (2023); modest accuracy lift over MixVPR | PyTorch 2.x | MIT clean | ~3-5 days | MVE: see fact card; docs: Sources #67+#68 | **Selected (BSD/permissive sibling)** — alternate primary on BSD/permissive track (unchanged) |
| **NetVLAD** (mandatory baseline, BSD/permissive track) | PyTorch port; Relja/netvlad canonical | VGG16 + soft-assignment-VLAD; 4096-D / 512-D / 256-D PCA-whitened per D-C2-9 | MIT canonical; classical-baseline; widely-cited | Largest single-stage descriptor cache at canonical 4096-D; D-C2-8 PyTorch-port-strategy gate | PyTorch port required from canonical MATLAB | MIT canonical (Nanne port has license-uncertainty per D-C2-8) | ~1 wk re-port from canonical OR ~3 days Nanne port + license-clearance | MVE: see fact card; docs: Sources #64+#65+#66 | **Selected (mandatory simple-baseline)** — classical reference (unchanged) |

**Exact-fit evidence** (REVISED):
- Project constraints checked: AC-2.1b satellite-anchor registration; AC-2.2 cross-domain MRE; AC-8.3 cache budget; AC-8.6 retrieval robustness; AC-4.1 latency; **multi-heading rotation-invariance gap closed by UltraVPR (Mode B Fact #110)**.
- Evidence: `02_fact_cards/C2_vpr.md` (Mode A) + `02_fact_cards/MODEB_addendum.md` Facts #110 + #113 (Mode B); Sources #57–#68 (Mode A) + #123 + #124 + #125 + #131 (Mode B).
- Disqualifiers: SALAD GPL-3.0 contingent on D-C1-1 = (a) or (c); conditional candidates (AnyLoc/BoQ/DINOv2-VLAD) pending D-C2-5 INT8 quantization survey prerequisite.
- Restrictions × Candidate-Modes sub-matrix: see [`../00_research/06_component_fit_matrix/C2_vpr.md`](../00_research/06_component_fit_matrix/C2_vpr.md) + [`MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md).
- API capability gates: ✅ MVE saved for 5 mandatory pre-screen Mode A candidates; UltraVPR + MegaLoc Documentary-Lead-only pending Plan-phase Jetson MVE.

### Component: C2.5 — Top-N inlier-based re-rank (NEW per Mode B Fact #108)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **Top-N re-rank by inlier count** (NEW sub-stage per SQ2 Decision 3) | Project-internal Python wrapper around C3 matcher's RANSAC inlier counter | Inputs: top-K=10 VPR retrieval candidates from C2; per-candidate single-pair LightGlue/XFeat invocation; rank by inlier count; output top-N=3 ⊆ top-K | Promotes SQ2 Decision 3 from implicit to explicit named sub-stage; carves explicit latency budget per D-CROSS-LATENCY-1 partition; reuses C3 matcher infrastructure (no new dependency) | Adds ~30-60 ms p95 per frame at K=10 (single-pair LightGlue at FP16) | LightGlue / XFeat already deployed for C3 | Apache-2.0 throughout (inherits C3 matcher license) | ~3-5 days project-internal wrapper | MVE: thin wrapper, MVE deferred to integration phase; docs: SQ2 Source #38–#42 (Mode A) + Mode B Fact #108 | **Selected (NEW sub-stage)** — operationalizes SQ2 Decision 3 |

### Component: C3 — Cross-domain matchers (UNCHANGED from solution_draft01)

(Verbatim from solution_draft01 § Component: C3. DISK+LightGlue D-C3-1 = (a) recommended-primary-mitigation, ALIKED+LightGlue secondary, XFeat alternate-modern-competitive-lead, SuperGlue+SuperPoint canonical Rejected. See [`solution_draft01.md`](solution_draft01.md#component-c3--cross-domain-matchers) for the full table.)

### Component: C3.5 — AdHoP-conditional refinement (NEW per Mode B Fact #108)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **AdHoP-conditional refinement** (NEW sub-stage per SQ2 Decision 2) | Project-internal Python wrapper implementing OrthoLoC AdHoP method-agnostic perspective preconditioning per Mode A SQ2 Source #40 | Invoked only when initial reprojection error (from C3 matcher RANSAC residuals) exceeds a threshold; worst-case 2× C3 latency when triggered; bypassed otherwise; +63% translation accuracy reported in source paper at the cost of 2× matcher latency on triggered frames | Promotes SQ2 Decision 2 from implicit to explicit named sub-stage; preserves AC-4.1 latency at p95 by gating activation; carves explicit latency budget per D-CROSS-LATENCY-1 partition | Adds 0-90 ms p99 latency only when triggered (~10-30% of frames in challenging cross-domain conditions) | LightGlue / XFeat already deployed for C3 | Apache-2.0 throughout (inherits C3 matcher license) | ~1 wk project-internal wrapper + threshold tuning | MVE: thin wrapper, MVE deferred to integration phase; docs: Mode A SQ2 Source #40 (OrthoLoC AdHoP) + Mode B Fact #108 | **Selected (NEW sub-stage)** — operationalizes SQ2 Decision 2 |

### Component: C4 — Pose estimation (REVISED per Mode B Fact #112)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **OpenCV ≥4.12.0 `cv::solvePnPRansac`** (mandatory simple-baseline) wrapped in **GTSAM `Marginals`** (D-C4-2 = (b) covariance recovery) ← **REVISED Mode B Fact #112: OpenCV pin tightened to ≥4.12.0** | OpenCV ≥4.12.0 calib3d + GTSAM Python | `solvePnPRansac(objectPoints, imagePoints, K, dist, ..., flags=SOLVEPNP_IPPE)` (planar-scene IPPE per D-C4-1 = (b) 4-DoF flat-earth); wrap result in GTSAM `BetweenFactor<Pose3>` prior + per-inlier `GenericProjectionFactorCal3_S2` factors → `LevenbergMarquardtOptimizer` → `Marginals.marginalCovariance(pose_key)` 6×6 | OpenCV simplest-baseline + 7 USAC RANSAC variants; GTSAM provides NATIVE 6×6 covariance recovery; couples C4 + C5 via shared GTSAM substrate per D-C5-5 = (c); **D-CROSS-LATENCY-1 hybrid auto-degrades to D-C4-2 = (a) Jacobian-based covariance under thermal throttle** | GTSAM `Marginals` ~30-90 ms per pose recovery (Plan-phase Jetson MVE confirms tail); auto-degrade to ~5-15 ms Jacobian-based covariance under thermal throttle per D-CROSS-LATENCY-1 | OpenCV ≥4.12.0 (CVE-2025-53644 mitigation per Mode B Fact #112); GTSAM Python | Apache-2.0 + BSD-3-Clause; **OpenCV pinned to ≥4.12.0 per CVE-2025-53644 (CVSS 9.8 CRITICAL)** | ~3-5 days OpenCV + ~3-5 days GTSAM wrapper | MVE: see [`../00_research/02_fact_cards/C4_pose_estimation.md`](../00_research/02_fact_cards/C4_pose_estimation.md); docs: Sources #82+#83+#86+#87 + Mode B Source #127 | **Selected (mandatory simple-baseline + recommended-primary covariance recovery via GTSAM)** — OpenCV pin tightened |
| **OpenGV** (modern-competitive-lead-richer-minimal-solver) | C++ + Python bindings; laurentkneip/opengv | (Unchanged from solution_draft01) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | **Selected with runtime gate** (unchanged) |

**Exact-fit evidence** (REVISED): Project constraints checked: AC-1.1/1.2 frame-center accuracy; AC-2.2 reprojection error <2.5 px cross-domain; AC-NEW-4 covariance honesty (P(error >500 m) <0.1 %); AC-4.1 latency (D-CROSS-LATENCY-1 hybrid); **CVE-2025-53644 mitigation via OpenCV ≥4.12.0 pin (Mode B Fact #112)**. **Camera intrinsics K + distortion `dist` are PROJECT-LEVEL OPEN ITEM per D-PROJ-1 (Mode B Fact #104)** — Plan-phase MUST close D-PROJ-1 before any AC-1.1/1.2 fixture validation.

### Component: C5 — State estimator (REVISED per Mode B Fact #107 — AC-4.5 scope clarification)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **Manual ESKF (Solà 2017)** (mandatory simple-baseline) | (Unchanged from solution_draft01) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | **Selected (mandatory simple-baseline)** (unchanged) |
| **GTSAM iSAM2 + CombinedImuFactor + smart factors + Marginals + IncrementalFixedLagSmoother** (modern-competitive-lead-factor-graph) ← **REVISED Mode B Fact #107: AC-4.5 scope clarification** | GTSAM Python; borglab/gtsam | iSAM2 incremental smoothing + `CombinedImuFactor` 6-key per-keyframe-pair factor with bias evolution + `BetweenFactorPose3` + `GenericProjectionFactorCal3DS2` per D-C5-5 = (c) `PriorFactorPose3` only + `gtsam_unstable.IncrementalFixedLagSmoother` K=10-20 keyframes per D-C5-3. **AC-4.5 scope: internal smoothing + corrected current-frame emission only — NOT FC retroactive correction** (FC log is forward-time only per Mode B Fact #107; ArduPilot `AP_GPS_MAV` and iNav `mspGPSReceiveNewData()` consume only the latest frame). FDR (AC-NEW-3) MUST log smoothed past-frame estimates so post-mission analysis can verify AC-4.5. | NATIVE 6×6 posterior covariance via `Marginals`; NATIVE AC-4.5 internal look-back refinement; couples C4 + C5 via shared GTSAM substrate per D-C5-5 = (c) | GTSAM ~50-200 MB footprint; per-update latency ~5-100 ms depending on factor density (D-C5-5 = (c) gives ~2-5 ms); **AC-4.5 ≠ FC retroactive correction — internal smoothing only** | GTSAM Python; daily-active maintenance | BSD-3-Clause clean | ~2-3 wk full factor-graph design | MVE: see fact card; docs: Sources #90+#91 + Mode B Fact #107 | **Selected (modern-competitive-lead-factor-graph + recommended primary path)** — couples NATIVELY with C4 GTSAM Marginals via D-C5-5 = (c); AC-4.5 scope clarified |

### Components C6, C7 — UNCHANGED from solution_draft01

(See [`solution_draft01.md`](solution_draft01.md#component-c6--tile-cache--spatial-index) for C6 mirror-of-suite-pattern primary + PostGIS+pgvector deferred secondary, and [`solution_draft01.md`](solution_draft01.md#component-c7--on-jetson-inference-runtime) for C7 TensorRT-native primary + ONNX Runtime+TRT EP secondary + pure PyTorch FP16 baseline. Mode B web research surfaced no contradicting evidence.)

### Component: C8 — MAVLink / MSP2 FC adapter (REVISED per Mode B Fact #109 + #111)

| Solution | Tools | Pinned Mode/Config | Advantages | Limitations | Requirements | Security | Cost | API Capability Evidence | Fit |
|----------|-------|--------------------|------------|-------------|--------------|----------|------|-------------------------|-----|
| **pymavlink → MAVLink `GPS_INPUT`** (recommended-primary for ArduPilot Plane) **+ MAVLink 2.0 message signing on companion ↔ AP wired channel per D-C8-9 = (d)** ← **REVISED Mode B Fact #109** | ardupilot/pymavlink + MAVLink 2.0 signing key handshake | `master.mav.gps_input_send(...)` 5 Hz periodic per D-C8-5 over UART/USB/UDP per D-C8-1; FC-side `GPS1_TYPE=14` MAVLink + `EK3_SRC1_POSXY=3` GPS source-set; per-FC unit conversion `horiz_accuracy` (m) per D-C8-8 = (b); **MAVLink 2.0 message signing enabled with per-flight key rotation per D-C8-9 = (d)** | Cooperative-path; FC-side ingestion via `AP_GPS_MAV` (verified Source #4); LGPL-3.0 linkable from Apache-2.0 app per LGPL §6 (D-C8-3 mitigation); **defends against CVE-2026-1579 unauthenticated MAVLink command injection per Mode B Fact #109** | LGPL-3.0 license-posture verification (D-C8-3 mitigation = bundle unmodified); **MAVLink 2.0 signing key management adds Plan-phase complexity (D-C8-9)** | pymavlink + ArduPilot Plane firmware (any) + MAVLink 2.0 signing-capable firmware (ArduPilot canonical per Mode B Source #128) | LGPL-3.0 linkable; **CVE-2026-1579 mitigated by MAVLink 2.0 signing per D-C8-9 = (d)** | ~3-5 days base + ~3-5 days signing key management implementation | MVE: see [`../00_research/02_fact_cards/C8_fc_adapter.md`](../00_research/02_fact_cards/C8_fc_adapter.md); docs: Sources #106+#107 + Mode B Source #128 | **Selected (recommended-primary)** for ArduPilot Plane + MAVLink-2.0-signing posture |
| **MSP2_SENSOR_GPS via Python MSP V2** (recommended-primary for iNav) ← **REVISED Mode B Fact #109 — iNav has no signing implementation; accepted residual risk** | YAMSPy + INAV-Toolkit `msp_v2_encode` | (Unchanged from solution_draft01) | YAMSPy + INAV-Toolkit MIT throughout; covariance fields aligned; **iNav has no MSP2 signing equivalent and no MAVLink message-signing implementation per Mode B Source #129 — accepted residual risk on iNav GCS link** | D-C8-4 implementation choice gate; **iNav MAVLink GCS link unsigned per Mode B Fact #109 — Plan-phase carryforward to propose iNav firmware feature-request** | YAMSPy or INAV-Toolkit; iNav firmware 8.0+ | MIT throughout; **iNav signing-gap = accepted residual risk per D-C8-9 + Mode B Source #129** | ~3-5 days | MVE: see fact card; docs: Sources #111+#112+#113 + Mode B Source #129 | **Selected (recommended-primary)** for iNav + signing-gap accepted residual risk |
| **D-C8-2 = (b) companion-driven `MAV_CMD_SET_EKF_SOURCE_SET` switch** (cross-cutting on AP path) ← **REVISED Mode B Fact #111** | pymavlink command channel | Companion publishes to source-set 2 + auto-switches FC to set 2 on first valid fix + switches back to set 1 when companion is unavailable | Mirrors NGPS/Auterion deployment pattern (Mode A SQ1) | **Pattern is firmware-supported but no production-deployed precedent — project will be establishing the canonical pattern itself per Mode B Fact #111**; SITL validation gate REQUIRED before lock per D-C8-2 carve-out | ArduPilot Plane firmware ≥ Aug 2021 (PR #18345) | n/a | ~3-5 days | MVE: see fact card; docs: Sources #4 + Mode B Source #130 | **Selected with runtime gate** (downgraded from `Selected`) — runtime gate = ArduPilot Plane SITL validation by IT-3 (Spoofing-promotion latency) before lock per Step 7.5.3 carve-out |
| **UBX impersonation via pyubx2 NAV-PVT** (deferred secondary for iNav) | (Unchanged from solution_draft01) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | (Unchanged) | **Deferred secondary** (unchanged) |

**Exact-fit evidence** (REVISED): Project constraints checked: AC-4.3 per-FC external-positioning interface; AC-NEW-2 spoofing-promotion latency; AC-NEW-4 covariance honesty (per-FC unit conversion); AC-NEW-7 forgery posture for UBX path; **CVE-2026-1579 MAVLink-no-default-auth mitigation via D-C8-9 = (d) per Mode B Fact #109; D-C8-2 companion-driven switch downgraded to "Selected with runtime gate" per Mode B Fact #111**.

### Component: C10 — Pre-flight cache provisioning (UNCHANGED from solution_draft01)

(See [`solution_draft01.md`](solution_draft01.md#component-c10--pre-flight-cache-provisioning--sector-classification--freshness-pipeline) for D-C6-3 + D-C7-7 confirmation pipelines. Mode B web research surfaced no contradicting evidence on C10 internals; cross-component coupling with D-PROJ-2 Suite Sat Service voting-layer contract is added at the project-level decision registry but does not change C10's onboard scope.)

### Out-of-research-scope items (deferred to Plan-phase) (REVISED per Mode B Facts #104 + #105)

Per the C10 scope restructure 2026-05-08 (`c10_scope=C` cross-coupling minimal), the following are deferred to Plan-phase as `operator tooling design`:
- Operator-side CLI/desktop tool design (Plan-phase architect + UX)
- Sector classification (active-conflict vs stable rear) heuristics + interface (Plan-phase architect + operations team)
- Tile age-stamping schema beyond restrictions.md mandate (Plan-phase architect)
- Freshness pipeline workflow (Plan-phase architect + operations team)

**NEW Mode B Plan-phase prerequisites (Mode B Facts #104 + #105)**:
- **D-PROJ-1 — Camera calibration acquisition strategy** (User + project bring-up team): hard prerequisite for AC-1.1/1.2 frame-center-accuracy validation; recommendation **(d) hybrid: factory data sheet + ground-truth checkerboard refinement on each deployed unit**.
- **D-PROJ-2 — Suite Sat Service voting-layer contract verification** (User + parent-suite Satellite Service team): hard prerequisite for AC-NEW-7 NFT-5 end-to-end evidence; recommendation **(a) verify + (b) draft contract from onboard side in parallel**.

---

## Testing Strategy (REVISED per Mode B Facts #103, #107, #109)

> **Note**: full test specifications are produced by the Test Spec skill (greenfield Step 5). What follows is the research-level test envelope, named so the Test Spec skill can elaborate against it.

### Integration / Functional Tests

- **IT-1 — Pipeline smoke** (REVISED): feed `_docs/00_problem/input_data/flight_derkachi/` (cropped nadir flight footage + synchronized `SCALED_IMU2` + `GLOBAL_POSITION_INT`) into the full C1+C2+C2.5+C3+C3.5+C4+C5+C8 pipeline; assert that the emitted `GPS_INPUT` (ArduPilot SITL) and `MSP2_SENSOR_GPS` (iNav SITL) frames stay within AC-1.1/1.2 frame-center-accuracy bounds vs the tlog GPS path. **Note per `expected_results/results_report.md` § Known Gaps**: still-image set is for AC-1.1/1.2 frame-center geolocation accuracy ONLY; Derkachi video is for runtime cadence + VIO + replay; neither is sufficient by itself for end-to-end AC-4.1 latency validation under production cadence + altitude + calibration — full validation requires D-PROJ-1 calibration + production-altitude footage.
- **IT-2 — Cold-boot TTFF**: cold-boot the companion 50× with a simulated FC pose; measure boot → first valid emitted external-position MAVLink frame; pass = 95th percentile <30 s per AC-NEW-1.
- **IT-3 — Spoofing-promotion latency** (REVISED per Mode B Fact #111): SITL on each supported FC (ArduPilot Plane + iNav, production param sets); inject false GPS; measure spoof onset → companion estimate becoming primary FC source via D-C8-2 = (b) `MAV_CMD_SET_EKF_SOURCE_SET` companion-driven switch; pass = 95th percentile <3 s on both per AC-NEW-2. **NEW gate: IT-3 functions as the runtime gate for D-C8-2's `Selected with runtime gate` status — must pass before D-C8-2 = (b) is locked; failure triggers D-C8-2-FALLBACK selection at Plan-phase.**
- **IT-4 — Sharp-turn recovery**: synthetic UAV trajectory with ±20° bank turns + <5% inter-frame overlap; assert C2/C3 satellite-anchor recovery within 1-2 frames per AC-3.2 + AC-3.3.
- **IT-5 — Visual blackout + GPS spoofing degraded mode**: SITL/replay on each FC; inject 5 s / 15 s / 35 s blackouts while spoofing GPS; assert mode transition ≤400 ms, spoofed GPS ignored, covariance grows monotonically, MAVLink fields degrade at AC-NEW-8 thresholds (>100 m → "2D fix or worse"; >500 m or >30 s → "no fix" + `VISUAL_BLACKOUT_FAILSAFE` STATUSTEXT), recovery only via trusted anchor or 10-s GPS-health + visual-consistency gate.
- **IT-6 — Stale tile rejection (AC-NEW-6)**: inject synthetic-age tiles into C6 cache; verify rejection or downgrade-to-non-`satellite_anchored` per AC-8.2 freshness threshold.
- **IT-7 — Cache-poisoning verification (AC-NEW-7)**: tamper with `/var/lib/onboard/cache/faiss/v_2048_M32.index` post-write but pre-takeoff; verify D-C10-3 SHA-256 content-hash gate triggers reject + STATUSTEXT + refuse takeoff.
- **IT-8 — Pre-flight cache rebuild idempotence**: invoke C10 pre-flight provisioning twice consecutively without input changes; verify D-C10-1 manifest-hash-driven trigger correctly skips rebuild on second invocation; verify atomic-write integrity holds across simulated power-loss mid-rebuild.
- **IT-9 — TensorRT engine cache reuse**: invoke C10 pre-flight provisioning with same model + same calibration corpus twice; verify D-C10-6 calibration-cache reuse triggers <30 sec rebuild on second invocation; verify D-C10-7 self-describing filename schema correctly identifies SM/JP/TRT/precision tuple.
- **IT-10 — AC-NEW-4 covariance-honesty cross-FC**: verify D-C8-8 = (b) per-FC unit conversion correctly extracts 2×2 horizontal sub-matrix from C5 GTSAM `Marginals.marginalCovariance`, computes 95% confidence ellipse semi-major axis `sqrt(2.0 * 5.991 * λ_max)`, emits as `horiz_accuracy` (m) for ArduPilot AND `hPosAccuracy` (mm) for iNav with mathematically equivalent values.
- **IT-11 — Smoothing-loop look-back accuracy** (NEW per Mode B Fact #107): validate GTSAM iSAM2's smoothed past-keyframe poses against ground-truth at smoothing convergence (independent of FC-side consumption). Assert that smoothed past-frame estimates (logged to FDR per AC-NEW-3) converge within X m of ground-truth at smoothing horizon K=10-20 keyframes per D-C5-3. **AC-4.5 satisfied as "internal smoothing + corrected current-frame emission" per Mode B Fact #107 scope clarification — NOT as "FC retroactive correction".**
- **IT-12 — VIO comparative study** (NEW per 2026-05-08 user directive on A1): replay the same flight footage (Derkachi cropped + IT-1 fixtures + when available D-PROJ-1-acquired full-altitude footage) through all three `VioStrategy` implementations (`Okvis2VioStrategy`, `VinsMonoVioStrategy`, `KltRansacVioStrategy`) using the research/dev build (D-C1-1-SUB-A = (a)). Emit a single side-by-side report: per-strategy AC-1.3 cumulative drift over 8 h replay; AC-2.1a frame-to-frame registration error; per-frame `VioOutput.relative_pose_covariance_6x6` honesty (AC-NEW-4); per-strategy NFT-1 latency p95+p99 (AC-4.1); per-strategy NFT-2 memory peak (AC-4.2); per-strategy SBOM impact + binary-size delta. **Deliverable**: `_docs/02_document/vio-comparative-study.md` published to official docs. **Production-selection gate**: if OKVIS2 leads VINS-Mono by >X% on AC-1.3 cumulative drift on the project's operating context, production binary builds with `BUILD_VINS_MONO=OFF` per D-C1-1-SUB-A = (a); otherwise D-C1-1-SUB-A is re-evaluated. Threshold X is a Plan-phase decision tied to AC-NEW-4 false-position safety budget headroom.

### Non-Functional Tests

- **NFT-1 — End-to-end latency p95 (AC-4.1)** (REVISED per Mode B Fact #103): 8 h synthetic load (3 Hz nav frames replayed); measure end-to-end latency distribution per D-CROSS-LATENCY-1 partition; pass = 95th percentile <400 ms; up to ~10% frames may drop under sustained load per AC-4.1. **Plan-phase Jetson MVE MUST close D-CROSS-LATENCY-1 hybrid degradation behavior before lock — see NFT-9.**
- **NFT-2 — Memory cap (AC-4.2)**: same 8 h load; assert peak shared CPU+GPU memory <8 GB per AC-4.2.
- **NFT-3 — Thermal envelope (AC-NEW-5)**: hot-soak 25 W @ +50 °C for 8 h; assert no Jetson thermal throttling. Cold-soak −20 °C cold-start within AC-NEW-1 30 s p95 budget.
- **NFT-4 — False-position safety budget (AC-NEW-4)**: Monte Carlo over public aerial-localization dataset (e.g., AerialVL S03) + own recorded flights; report error CDF; pass = `P(>500 m) <0.1 %` AND `P(>1 km) <0.01 %` across ≥100 flights.
- **NFT-5 — Cache-poisoning safety budget (AC-NEW-7)** (REVISED per Mode B Fact #105): multi-flight Monte Carlo replay over public datasets + own flights with synthetic over-confidence injection (deflate covariance ×1.5–3); assert `P(geo-misalign >30 m) <1 %` AND `P(>100 m) <0.1 %` across ≥100 flights. **End-to-end Service-side validation requires D-PROJ-2 Suite Sat Service voting-layer contract verification — onboard NFT-5 alone is best-effort without Service-side voting per Mode B Fact #105.**
- **NFT-6 — FDR storage cap (AC-NEW-3)**: 8 h synthetic load; assert FDR ≤64 GB; verify no payload class silently dropped without a logged rollover. **NEW per Mode B Fact #107: FDR MUST log smoothed past-frame estimates so post-mission analysis can verify AC-4.5 internal-smoothing scope.**
- **NFT-7 — License posture verification** (REVISED per Mode B Fact #102): SBOM dump of the deployed companion; verify D-C1-1 license-track is honored (no GPL-3.0 candidate loaded if D-C1-1 = (b); pymavlink LGPL-3.0 bundled-unmodified per D-C8-3); **VINS-Mono GPL-3.0 verified per Mode B Source #122 — NOT a BSD/permissive baseline if D-C1-1 = (b)**; verify Magic Leap noncommercial canonical SP weights are NOT loaded; verify all selected candidates' LICENSE files are bundled in `LICENSE/`.
- **NFT-8 — MAVLink message-signing verification** (NEW per Mode B Fact #109): SBOM dump confirms MAVLink 2.0 signing passkey configuration for ArduPilot companion ↔ AP wired channel per D-C8-9 = (d); per-flight key rotation logged to FDR; iNav side documents the unsignable-link as accepted residual risk per Mode B Source #129. Verify CVE-2026-1579 mitigation through end-to-end signed-message round-trip in SITL.
- **NFT-9 — Hot-soak latency distribution** (NEW per Mode B Fact #103): extends NFT-3 conditions (25 W @ +50 °C for 8 h) with end-to-end p95 + p99 latency distribution measurement per D-CROSS-LATENCY-1 partition; validate hybrid degradation behaves correctly (K=3 → K=2 + Jacobian-covariance under thermal throttle); pass = p95 ≤ 400 ms in steady-state AND in thermal-throttle hybrid mode; pass = p99 ≤ 600 ms (allows occasional AdHoP-triggered frames).
- **NFT-10 — Dependency CVE pinning audit** (NEW per Mode B Fact #112): SBOM dump confirms OpenCV ≥4.12.0 (CVE-2025-53644 mitigation), FAISS / GTSAM / TensorRT / pymavlink at versions with no published CVEs at audit time; monthly CVE re-scan trigger logged per D-CROSS-CVE-1 = (a) + (b).

---

## References

> Full per-source descriptions in `_docs/00_research/01_source_registry/` (organized by category file). Mode B addendum sources #122–#131 in [`MODEB_addendum.md`](../00_research/01_source_registry/MODEB_addendum.md).

(Mode A categories SQ6 / SQ1 / SQ2 / C1 / C2 / C3 / C4 / C5 / C6 / C7 / C8 / C10 references remain as in [`solution_draft01.md`](solution_draft01.md#references). Below are the Mode B additions only.)

### Mode B addendum (2026-05-08)

Sources #122–#131. See [`MODEB_addendum.md`](../00_research/01_source_registry/MODEB_addendum.md).

| # | Title | Tier | Mode B Binding |
|---|-------|------|---------------|
| 122 | HKUST-Aerial-Robotics/VINS-Mono LICENCE file (canonical) — GNU GPL Version 3 | L1 | C1 license-correction (Fact #102) |
| 123 | MegaLoc — "One Retrieval to Place Them All" (CVPR 2025; gmberton/megaloc, MIT) | L1 | C2 D-C2-11 candidate (Fact #110) |
| 124 | UltraVPR — "Unsupervised Lightweight Rotation-Invariant Aerial VPR" (RAL 2025 / ICRA 2026; cbbhuxx/UltraVPR, MIT) | L1 | C2 D-C2-11 alternative (Fact #110) — Documentary Lead PRIMARY on BSD/permissive C2 axis |
| 125 | AirZoo — "Unified Large-Scale Dataset for Grounding Aerial Geometric 3D Vision" (arXiv:2604.26567, 2026) | L1 | C2 evidence base for MegaLoc on aerial domain (Fact #110) |
| 126 | NVD CVE-2026-1579 — MAVLink protocol Missing Authentication (CVSS 9.8 CRITICAL) | L1 | New cross-cutting security gate D-C8-9 (Fact #109) |
| 127 | NVD CVE-2025-53644 — OpenCV uninitialized stack pointer on crafted JPEG (CVSS 9.8 CRITICAL); fixed in 4.12.0 | L1 | C4 OpenCV pin update (Fact #112) |
| 128 | ArduPilot MAVLink2 Signing — Plane documentation + Issue #28736 + PR #29546 (March 2025) channel-specific signing | L1 | D-C8-9 mitigation evidence (Fact #109) |
| 129 | iNav MAVLink Wiki | L1 | D-C8-9 cross-FC asymmetry (Fact #109) — iNav has no signing implementation |
| 130 | ArduPilot common-ekf-sources.rst + PR #18345 (`MAV_CMD_SET_EKF_SOURCE_SET`) — explicit "no GCSs are currently known to implement this" (verified 2026-05-08) | L1 | D-C8-2 evidence (Fact #111) cross-confirms Mode A SQ6 Fact #3 |
| 131 | XoFTR — "Cross-modal Feature Matching Transformer" (arXiv:2404.09692) + 2026 SAR-optical satellite registration benchmark (arXiv:2604.10217) | L2 | F20 contrarian-evidence reference (Fact #113) |

---

## Open decisions for Plan-phase (D-Cx-y registry, REVISED per Mode B Facts #103, #109, #110, #111, #112, #113 + new D-PROJ-1, D-PROJ-2)

The 27 Plan-phase-architect-owned decisions and 8 cross-component-owner decisions raised across all components in Mode A are catalogued in [`../00_research/06_component_fit_matrix/99_cross_component_gates.md`](../00_research/06_component_fit_matrix/99_cross_component_gates.md). Mode B revisions + new gates are catalogued in [`../00_research/06_component_fit_matrix/MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md). The most architecturally significant **user-decision** gates (Mode A + Mode B combined):

- **D-C1-1 license-track posture** (User + Plan-phase architect, Mode A). Recommendation: D-C1-1 = (c) both tracks open; preserves modular swap pathway. **Mode B Fact #102 evidence**: VINS-Mono is GPL-3.0 (not BSD); BSD/permissive-track lead remains OKVIS2.
- **D-C1-1-SUB-A (LOCKED 2026-05-08 by User to option (a))** VINS-Mono GPL-3.0 viral-linkage containment policy. Production binary `BUILD_VINS_MONO=OFF` (BSD-clean — only `Okvis2VioStrategy` + `KltRansacVioStrategy` linked). Research/dev binary `BUILD_VINS_MONO=ON` for IT-12 comparative study (all three strategies linked). Plan-phase MUST implement the CMake `option(BUILD_VINS_MONO ...)` flag + CI pipeline split + production-binary SBOM verification (no `vins_mono` GPL-3.0 symbol present). See § Architecture C1 D-C1-1-SUB-A table for option trade-offs and locked-verdict rationale.
- **D-C2-1 VPR canonical-weights vs aerial-retrain vs aerial-community-checkpoint** (User + Plan-phase architect, Mode A). Recommendation: aerial-retrain on real UAV nadir flight footage corpus per D-C7-1 closure. **Mode B Fact #110 update**: UltraVPR is unsupervised aerial-pretrain, closing D-C2-1 retrain cost on the BSD/permissive C2 axis if UltraVPR is selected.
- **D-C3-1 SuperPoint-replacement-strategy** (User + Plan-phase architect + license-posture decision-maker, Mode A). Recommendation: D-C3-1 = (a) DISK+LightGlue. **Mode B Fact #113 reinforcement**: foundation-model features (DINOv2) provide modality invariance — strengthens SelaVPR (DINOv2-L) as secondary alongside UltraVPR primary.
- **D-C2-11 (REVISED Mode B Fact #110) MegaLoc + UltraVPR successor evaluation** (User + Plan-phase architect). Recommendation REVISED from "defer to post-research session" to **(a) elevate UltraVPR to Documentary Lead PRIMARY on BSD/permissive C2 axis + (b) elevate MegaLoc to Documentary Lead SECONDARY (broader-applicability) + (c) preserve closed pre-screen as fallback**; mandatory Jetson MVE under D-C1-2 / D-C2-4 expanded scope.
- **D-C2-12 (NEW Mode B Fact #113) DINOv2-backbone feature-extractor evaluation for cross-domain matching** (Plan-phase architect + C3 owner). Plan-phase decision: defer to Jetson MVE; potentially closes D-C3-1 retrain cost via DINOv2-feature-based matcher without requiring D-C2-1 aerial retrain. Carryforward research item.
- **D-C8-2 (REVISED Mode B Fact #111) companion-driven `MAV_CMD_SET_EKF_SOURCE_SET` switch ownership pattern** (Plan-phase architect + AC-NEW-2 owner). Recommendation unchanged ((b) companion publishes to source-set 2 + auto-switches FC), but **status downgraded to `Selected with runtime gate`** per Step 7.5.3 carve-out — runtime gate = ArduPilot Plane SITL validation by IT-3 (Spoofing-promotion latency) before lock. **NEW sub-decision D-C8-2-FALLBACK** if SITL validation fails: (a) operator-manual RC aux switch with relaxed AC-NEW-2 wording; (b) operator-warning STATUSTEXT instead of automated switch; (c) escalate to ArduPilot dev community.
- **D-C8-9 (NEW Mode B Fact #109) MAVLink 2.0 message signing posture per FC** (Plan-phase architect + security owner). Recommendation **(d) hybrid: signing on companion ↔ AP wired channel + per-flight key rotation**. iNav-side signing-gap accepted as residual risk + Plan-phase carryforward to propose iNav firmware feature-request.
- **D-CROSS-LATENCY-1 (NEW Mode B Fact #103) AC-4.1 latency budget partition strategy** (Plan-phase architect + project bring-up team). Recommendation **(d) hybrid: K=3 default + auto-degrade to K=2 + Jacobian-covariance under thermal throttle**. Validation gate: NFT-9 hot-soak latency distribution measurement before lock.
- **D-CROSS-CVE-1 (NEW Mode B Fact #112) dependency security pinning posture** (Plan-phase architect + security owner). Recommendation **(a) lock to specific patched versions of all CVE-affected dependencies (OpenCV ≥4.12.0; FAISS no CVEs; GTSAM no CVEs; TensorRT 10.3 no CVE-applicable; pymavlink no CVEs at audit time) + (b) maintain a project SBOM with monthly CVE re-scan**.
- **D-PROJ-1 (NEW Mode B Fact #104) Camera calibration acquisition strategy** (User + project bring-up team). Recommendation **(d) hybrid: factory data sheet from ADTi + ground-truth checkerboard refinement on each deployed unit**. **CRITICAL Plan-phase gate** — hard prerequisite for AC-1.1/1.2 frame-center-accuracy validation; Test Spec greenfield Step 5 cannot lock end-to-end accuracy fixtures without it.
- **D-PROJ-2 (NEW Mode B Fact #105) Suite Sat Service voting-layer contract verification** (User + parent-suite Satellite Service team). Recommendation **(a) verify Suite Service voting layer is documented + scheduled + (b) draft contract from onboard side and propose to Suite Service team in parallel**. **CRITICAL cross-suite gate** — requires coordination with parent-suite Satellite Service team before AC-NEW-7 NFT-5 can pass with end-to-end evidence.

---

## Related Artifacts

- Tech stack evaluation (`tech_stack.md`): NOT PRODUCED in this Mode B run. Recommendation set is embedded in the per-component candidate tables above and the Mode B revisions overlay [`MODEB_revisions.md`](../00_research/06_component_fit_matrix/MODEB_revisions.md). Full extraction into `tech_stack.md` is a low-cost task if the user requests it before Plan-phase.
- Security analysis (`security_analysis.md`): NOT PRODUCED in this Mode B run. AC-NEW-7 cache-poisoning safety + AC-NEW-2 spoofing-promotion + AC-NEW-8 visual blackout failsafe + AC-NEW-4 covariance honesty + **CVE-2026-1579 MAVLink-no-default-auth (Mode B) + CVE-2025-53644 OpenCV crafted-JPEG (Mode B)** are addressed component-by-component above and cross-referenced in [`../00_research/05_validation_log.md`](../00_research/05_validation_log.md). Full extraction into `security_analysis.md` is a low-cost task if the user requests it before Plan-phase — **with Mode B scope, this artifact would now also include the D-C8-9 MAVLink-2.0-signing posture + D-CROSS-CVE-1 dependency-pinning posture as named sub-sections**.
- AC assessment (`_docs/00_research/00_ac_assessment.md`): NOT PRODUCED as standalone artifact in either Mode A or Mode B; per-AC binding evidence remains distributed across per-component fact cards + Restrictions × Candidate-Modes sub-matrix sections + Mode B addendum facts. Per Mode B Fact #106, retroactive extraction is a ~1-2 hour operation if the canonical artifact is wanted before Plan-phase.

---

## Mode B summary

solution_draft02 supersedes solution_draft01 with 13 actionable revisions:
1. **C1**: VINS-Mono license corrected from BSD to GPL-3.0; KLT+RANSAC re-labeled mandatory simple-baseline (Fact #102). **NEW per 2026-05-08 user directive**: all three implementations (OKVIS2 + VINS-Mono + KLT+RANSAC) are wrapped behind a `VioStrategy` interface with config-driven selection, enabling a comparative-study report (IT-12) that picks the production-deployed implementation by measured performance. **NEW sub-decision D-C1-1-SUB-A** (User hard gate): how to contain VINS-Mono GPL-3.0 viral linkage so the production deployment binary stays BSD/permissive clean. Recommendation **(a) build-config exclusion**: production binary `BUILD_VINS_MONO=OFF`; research/dev binary `BUILD_VINS_MONO=ON` for the comparative study.
2. **C2**: UltraVPR + MegaLoc elevated as new Documentary-Lead candidates on BSD/permissive axis; D-C2-11 status changed from "deferred" to "elevate" (Fact #110); SelaVPR strengthened (Fact #113).
3. **C2.5 + C3.5**: two new sub-stages added (Top-N inlier re-rank + AdHoP-conditional refinement) per SQ2 Decisions 2+3 closure (Fact #108).
4. **C4**: OpenCV pin tightened to ≥4.12.0 (Fact #112); D-CROSS-LATENCY-1 hybrid degradation path documented (Fact #103).
5. **C5**: AC-4.5 scope clarified as internal-smoothing-only — NOT FC retroactive correction (Fact #107); IT-11 added.
6. **C8**: D-C8-9 MAVLink 2.0 message signing posture added per FC (Fact #109); D-C8-2 status downgraded to `Selected with runtime gate` (Fact #111); iNav signing-gap documented as accepted residual risk.
7. **Plan-phase**: D-PROJ-1 (camera calibration) + D-PROJ-2 (Suite Sat Service voting-layer contract) + D-CROSS-CVE-1 (dependency pinning) + D-CROSS-LATENCY-1 (AC-4.1 partition) + D-C2-12 (DINOv2-feature matcher) added as new gates (Facts #103, #104, #105, #112, #113).
8. **Tests**: IT-11 (smoothing look-back), NFT-8 (signing verification), NFT-9 (hot-soak latency), NFT-10 (CVE pinning audit) added; IT-1 + IT-3 + NFT-1 + NFT-5 + NFT-6 + NFT-7 revised.

The Mode B audit found NO architectural component that needed wholesale replacement — the Mode A solution_draft01 architecture survives with revisions, additions, and three corrections (license error, latency budget, scope clarification). The revised draft is suitable as the input to Plan-phase.
