mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-21 10:11:12 +00:00
Compare commits
336 Commits
try02
..
9dc04cc677
| Author | SHA1 | Date | |
|---|---|---|---|
| 9dc04cc677 | |||
| ade0c86f2b | |||
| 8c4be9ace0 | |||
| bfcac2cb9f | |||
| 0ed1a5d988 | |||
| 7eed4d6e76 | |||
| c3a1ebc754 | |||
| c7cd9b414d | |||
| 55a6e8ce12 | |||
| 5e52779056 | |||
| 63c0217e3d | |||
| b15454b9a9 | |||
| 811b04e605 | |||
| 544b37fdc9 | |||
| 3c2b63ce22 | |||
| 1198890b74 | |||
| 2b53168142 | |||
| 8de2716500 | |||
| 6044a33197 | |||
| 9bc170ffe0 | |||
| 21a7784682 | |||
| 1b65619524 | |||
| 06a1359e6a | |||
| 7d53cef0cf | |||
| b66b68ff76 | |||
| dcde602f61 | |||
| f5366bbca1 | |||
| 87fe98858f | |||
| 64d961f60c | |||
| a12638dd92 | |||
| a7b3e60716 | |||
| bf13549b32 | |||
| ab92946833 | |||
| 4fdf1968af | |||
| 12aba8139f | |||
| 76f460c88a | |||
| a680146193 | |||
| 39a7267a23 | |||
| c1f27e4681 | |||
| 4fd88655a4 | |||
| bb9c408597 | |||
| 1ca9a59b0b | |||
| 4f122b604d | |||
| eb77f04495 | |||
| 3d3b53ac6f | |||
| 2551829b98 | |||
| 9bdc868dfd | |||
| 376f3db12c | |||
| 2be1b5101e | |||
| c3639a5d1c | |||
| 2b8ef52f66 | |||
| 02208c577e | |||
| 5c4d129f80 | |||
| eaf2f47f69 | |||
| 680ba29ae6 | |||
| 1ab93fe0c7 | |||
| 7dc38fdd3e | |||
| dbae0cad5b | |||
| 8abfb020fe | |||
| 8cee532516 | |||
| d066a23cb1 | |||
| 94c3e04e31 | |||
| cb444c4f8a | |||
| bcdc17bd74 | |||
| e054a55804 | |||
| b7012d2787 | |||
| 324bbd6367 | |||
| bd41956164 | |||
| e114bfd9b8 | |||
| 8e563efd4c | |||
| 58a1678417 | |||
| d62df9ad15 | |||
| 662327ce32 | |||
| 6586208f83 | |||
| 9c13ab3bd0 | |||
| c2934b8686 | |||
| 5c1c35da9a | |||
| c4e4063650 | |||
| 6ce31587d4 | |||
| eb6dc17880 | |||
| c64e492aa5 | |||
| 33e683dc0f | |||
| 6e4a575221 | |||
| d1e30f818f | |||
| c56d4584e6 | |||
| de19e716d8 | |||
| 330893be5c | |||
| 23640a784f | |||
| 73cd632e95 | |||
| f25cae4a82 | |||
| a22028087f | |||
| 5def1a3eb3 | |||
| 1ee54b414b | |||
| 7d1288e4ba | |||
| b0296da911 | |||
| bb744d9078 | |||
| 7fb3cb3f34 | |||
| 4e0717e543 | |||
| 2f1fb4d0d0 | |||
| 47ad43f913 | |||
| f49d803252 | |||
| 6554d568f1 | |||
| 43fdef1aac | |||
| 1d260f7e41 | |||
| 2d6d44af5d | |||
| a644debdb7 | |||
| c6e6cba237 | |||
| 29ac16cfcb | |||
| 702a0c0ff3 | |||
| ff1b00200c | |||
| 6599d828d2 | |||
| e9e6e32097 | |||
| 59d9116d36 | |||
| d7a17a8248 | |||
| fa38bfe608 | |||
| 7a71579428 | |||
| 55ddcb70d3 | |||
| f7a99282fb | |||
| 6d51e06886 | |||
| be5c6d20aa | |||
| c5ffc14fe9 | |||
| 811ddc8aa7 | |||
| 2b19b8b90b | |||
| d7e6b0959e | |||
| 4f10fd230f | |||
| 2c31cc094f | |||
| 17a0d074af | |||
| 8149083cac | |||
| f9b4241d3a | |||
| 5adf3dd04f | |||
| fa3742d582 | |||
| 4eac24f37a | |||
| 360aece7a6 | |||
| abe8c5cd2c | |||
| a1185d0a28 | |||
| 06f655d8fb | |||
| f12789ebf0 | |||
| ac3e288dbd | |||
| 21cef8bdce | |||
| ceb24b5a62 | |||
| 4815dd6aa1 | |||
| 6a5954bdae | |||
| 2ce300ddb1 | |||
| 235eb4549e | |||
| f6a180e5df | |||
| 87909cce9f | |||
| e81616a09d | |||
| 0d65ff4705 | |||
| 5dfd9a577e | |||
| fbeeab60b3 | |||
| 5441ea2017 | |||
| f29897cb3a | |||
| cfe3d357f4 | |||
| b64f3a1b93 | |||
| 3c4fd272f1 | |||
| 773d589d34 | |||
| af0dbe863a | |||
| dd2f1cbae6 | |||
| 1682dc354b | |||
| 88f6ae6dce | |||
| 25836925c9 | |||
| a92e5ee482 | |||
| 9116e304fd | |||
| 5fe67023b2 | |||
| 2d88d3d674 | |||
| 7644b25e8c | |||
| 099c75c6f8 | |||
| 91ce1c2047 | |||
| a06b107fc3 | |||
| 90f4ac78f4 | |||
| 3a61a4f5bf | |||
| 610e8a743c | |||
| cde237e236 | |||
| ca0430a44d | |||
| a9c8d60087 | |||
| f7b2e70085 | |||
| 684ec2601c | |||
| 38cba7c86e | |||
| f01a5058ab | |||
| 3b7265757b | |||
| ecf76d762d | |||
| 9b6e0b81f5 | |||
| acfdc8cbdf | |||
| b88cff185c | |||
| e2bebefdfc | |||
| 6ca8d78190 | |||
| 08e657d433 | |||
| 692bbdb7a0 | |||
| defe80dc75 | |||
| 0dfe7c5301 | |||
| 0ad3278b12 | |||
| 18a69022b3 | |||
| 54942f3052 | |||
| afe42f451c | |||
| d571ca25f9 | |||
| 39ff47087f | |||
| d1c1cd9ab4 | |||
| bf33b94260 | |||
| 16a4582c3f | |||
| 1141d17769 | |||
| dde838d2cc | |||
| 21f5a30d09 | |||
| ca37f8849d | |||
| 49a67f770d | |||
| 59f56c032f | |||
| 65ad2168ed | |||
| fce80290bc | |||
| 1ebab29a4f | |||
| 9c35776bcb | |||
| 48ea1e2fc2 | |||
| 9a605c8514 | |||
| 89c223882b | |||
| d6756f1855 | |||
| 3665acef66 | |||
| 823c0f1b2e | |||
| 6c7d24f7e0 | |||
| daff5d4d1c | |||
| f925af9de3 | |||
| 48281db9e9 | |||
| 8a83166261 | |||
| 72a06edab0 | |||
| e0be591b06 | |||
| db27e25630 | |||
| c0bdb57957 | |||
| 098aabac0c | |||
| 7cbd17ee83 | |||
| 31a300f8a2 | |||
| b3ad94c155 | |||
| fd848266d1 | |||
| 8b394a98c6 | |||
| beed43724f | |||
| 8a9cf88a46 | |||
| 1e0be08e8a | |||
| a61d2d3f4b | |||
| 362e93c626 | |||
| e4ecdaf619 | |||
| b5dd6031d2 | |||
| 33486588de | |||
| ba20c2d195 | |||
| 3acc7f33dd | |||
| 8e71f6c002 | |||
| b12db61444 | |||
| 880eabcb3f | |||
| 8171fcb29e | |||
| 64542d32fc | |||
| 723f574b14 | |||
| c19c76481c | |||
| 846670a5c5 | |||
| e0a6f0d9d5 | |||
| 48dd81ee0f | |||
| 12cc5a4e4b | |||
| 8382cdae10 | |||
| ee6606a9c2 | |||
| a8e7199f30 | |||
| 2425f8e6fd | |||
| 3d2c22d8ba | |||
| cab7b5d020 | |||
| 2485763d09 | |||
| 2ba44a33c5 | |||
| 5acd14b792 | |||
| c30fd4f67d | |||
| 9812503abd | |||
| 0d94999d95 | |||
| 6869aed602 | |||
| 70f786f2d1 | |||
| 44c19ed117 | |||
| a7a73c01ce | |||
| a39e1863fd | |||
| 2cea5a3a2c | |||
| fd05a7d2f6 | |||
| 55f1e42401 | |||
| 963bc07e68 | |||
| 4c97311393 | |||
| 481cef92d0 | |||
| 3522e07d88 | |||
| 1b356e2bba | |||
| 9cc6ab1dc7 | |||
| 24b1f14ef6 | |||
| 54a8b7c27e | |||
| 9aaa6fcda0 | |||
| 6bb03c75d1 | |||
| e7cf716347 | |||
| ef5b8cf3b7 | |||
| 52433fd586 | |||
| 97631ce6d9 | |||
| e55a35118c | |||
| a56380b1d7 | |||
| 39c38762ca | |||
| a96a6bf843 | |||
| 6927a6a647 | |||
| 0297c94a62 | |||
| 5ad3af15c3 | |||
| b6669bbf03 | |||
| f84bbaeb13 | |||
| 778aff22a6 | |||
| 0c8f186598 | |||
| e5f9f66ea4 | |||
| 5851f171e6 | |||
| df7d380213 | |||
| a45ade3536 | |||
| 1f1ab719fb | |||
| 7426d2dcdd | |||
| e93b5ec22b | |||
| b765879bf6 | |||
| 5490f9ca0f | |||
| d7d9a9282c | |||
| 363fe9502f | |||
| a444e819e6 | |||
| 46d3e314a0 | |||
| 6dcad4c3c1 | |||
| 026e4c1b7f | |||
| 15f6e749bb | |||
| 282766c04c | |||
| ad1dadf37d | |||
| 9cc4ae0693 | |||
| 3927e813ad | |||
| a9e5bbf024 | |||
| 02281032c4 | |||
| eef8bf31ca | |||
| 91d42bc358 | |||
| 71d55e0e8d | |||
| 0131b958bc | |||
| 14205921ed | |||
| 276a50e26d | |||
| f48170c48e | |||
| 68e2119307 | |||
| 0ab9284bc0 | |||
| b373f941f3 | |||
| cc46047559 | |||
| c886c0045c | |||
| bcaac188c4 | |||
| 0af125cac0 | |||
| 6de80aed9a | |||
| 3ff1daeb85 | |||
| 829aae2255 | |||
| 3e3ab12621 |
@@ -0,0 +1,18 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 100
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
AccessModifierOffset: -4
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Attach
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: true
|
||||
Standard: c++17
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
---
|
||||
Checks: >
|
||||
-*,
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
cppcoreguidelines-*,
|
||||
modernize-*,
|
||||
performance-*,
|
||||
readability-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||
-modernize-use-trailing-return-type,
|
||||
-readability-identifier-length,
|
||||
-readability-magic-numbers
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: '.*'
|
||||
FormatStyle: file
|
||||
@@ -0,0 +1,7 @@
|
||||
format:
|
||||
line_width: 100
|
||||
tab_size: 2
|
||||
use_tabchars: false
|
||||
separate_ctrl_name_with_space: false
|
||||
separate_fn_name_with_space: false
|
||||
dangle_parens: false
|
||||
+136
-72
@@ -11,10 +11,20 @@ If you want to run a specific skill directly (without the orchestrator), use the
|
||||
```
|
||||
/problem — interactive problem gathering → _docs/00_problem/
|
||||
/research — solution drafts → _docs/01_solution/
|
||||
/plan — architecture, components, tests → _docs/02_document/
|
||||
/decompose — atomic task specs → _docs/02_tasks/todo/
|
||||
/implement — batched parallel implementation → _docs/03_implementation/
|
||||
/deploy — containerization, CI/CD, observability → _docs/04_deploy/
|
||||
/plan — architecture, ADRs, components, tests, epics → _docs/02_document/
|
||||
/test-spec — blackbox/perf/resilience/security test specs → _docs/02_document/tests/
|
||||
/decompose — atomic task specs (multi-mode) → _docs/02_tasks/todo/
|
||||
/implement — sequential dependency-aware batches with code review and completeness gates → _docs/03_implementation/
|
||||
/test-run — runs the test suite (functional / perf modes) with gating
|
||||
/code-review — multi-phase review used by /implement
|
||||
/refactor — 8-phase structured refactoring (incl. testability sub-mode) → _docs/04_refactoring/
|
||||
/security — OWASP-driven audit → _docs/05_security/
|
||||
/deploy — containerization, CI/CD, environments, observability, procedures, scripts → _docs/04_deploy/
|
||||
/release — execute deploy artifacts in prod, smoke-test, watch, decide rollback → _docs/04_release/
|
||||
/document — bottom-up reverse-engineering of an existing codebase → _docs/02_document/
|
||||
/new-task — interactive feature planning for an existing codebase → _docs/02_tasks/todo/
|
||||
/ui-design — HTML+CSS mockups + design system → _docs/02_document/ui_mockups/
|
||||
/retrospective — metrics + lessons log → _docs/06_metrics/ + _docs/LESSONS.md
|
||||
```
|
||||
|
||||
## How It Works
|
||||
@@ -41,148 +51,201 @@ The state file tracks completed steps, key decisions, blockers, and session cont
|
||||
|
||||
Skills auto-chain without pausing between them. The only pauses are:
|
||||
- **BLOCKING gates** inside each skill (user must confirm before proceeding)
|
||||
- **Session boundary** after decompose (suggests new conversation before implement)
|
||||
- **Session boundaries** declared in each flow's auto-chain rules (e.g., after `decompose`, after `decompose tests`) — suggested new-conversation breakpoints to keep context fresh
|
||||
|
||||
A typical project runs in 2-4 conversations:
|
||||
- Session 1: Problem → Research → Research decision
|
||||
- Session 2: Plan → Decompose
|
||||
- Session 3: Implement (may span multiple sessions)
|
||||
- Session 4: Deploy
|
||||
There are three flows, resolved on every invocation (see `skills/autodev/SKILL.md` § Flow Resolution):
|
||||
|
||||
Re-entry is seamless: type `/autodev` in a new conversation and the orchestrator reads the state file to pick up exactly where you left off.
|
||||
| Flow | When | Steps |
|
||||
|------|------|-------|
|
||||
| **greenfield** | empty workspace, no source yet | 17 steps: Problem → Research → Plan → UI Design → Test Spec → Decompose → Implement → Code Testability Revision → Decompose Tests → Implement Tests → Run Tests → Test-Spec Sync → Update Docs → Security Audit (opt) → Performance Test (opt) → Deploy → Release → Retrospective |
|
||||
| **existing-code** | source files present | one-time baseline (Document → Architecture Baseline Scan → Test Spec → Code Testability Revision → Decompose Tests → Implement Tests → Run Tests → optional Refactor) then a feature-cycle loop (New Task → Implement → Run Tests → Test-Spec Sync → Update Docs → Security Audit (opt) → Performance Test (opt) → Deploy → Release → Retrospective → loops back to New Task) |
|
||||
| **meta-repo** | `.gitmodules`, workspace manifest, or multi-component aggregator | uses `monorepo-*` skills + `_docs/_repo-config.yaml` instead of per-component BUILD-SHIP folders |
|
||||
|
||||
A typical greenfield project spans several conversations because of session boundaries. Re-entry is seamless: type `/autodev` in a new conversation and the orchestrator reads `_docs/_autodev_state.md` to pick up exactly where you left off.
|
||||
|
||||
## Skill Descriptions
|
||||
|
||||
### autodev (meta-orchestrator)
|
||||
|
||||
Auto-chaining engine that sequences the full BUILD → SHIP workflow. Persists state to `_docs/_autodev_state.md`, tracks key decisions and session context, and flows through problem → research → plan → decompose → implement → deploy without manual skill invocation. Maximizes work per conversation with seamless cross-session re-entry.
|
||||
Auto-chaining engine that sequences the full BUILD → SHIP → EVOLVE workflow. Persists state to `_docs/_autodev_state.md`, surfaces top-3 lessons from `_docs/LESSONS.md` at every invocation, replays any `_docs/_process_leftovers/` entries, tracks key decisions and session context, and flows through the active flow's steps without manual skill invocation. Maximizes work per conversation with seamless cross-session re-entry.
|
||||
|
||||
### problem
|
||||
|
||||
Interactive interview that builds `_docs/00_problem/`. Asks probing questions across 8 dimensions (problem, scope, hardware, software, acceptance criteria, input data, security, operations) until all required files can be written with concrete, measurable content.
|
||||
Interactive 4-phase interview that builds `_docs/00_problem/`. Asks probing questions across 8 dimensions (problem & goals, scope, hardware & environment, software & tech, acceptance criteria, input data, security, operational) until all required files can be written with concrete, measurable, quantifiable content. Acceptance criteria must include numeric targets; input data must include `expected_results/` mappings.
|
||||
|
||||
### research
|
||||
|
||||
8-step deep research methodology. Mode A produces initial solution drafts. Mode B assesses and revises existing drafts. Includes AC assessment, source tiering, fact extraction, comparison frameworks, and validation. Run multiple rounds until the solution is solid.
|
||||
8-step deep research methodology. Mode A produces initial solution drafts. Mode B assesses and revises existing drafts. Classifies output as **Technical-component selection** (full per-mode API verification gates apply) or **Non-technical investigation** (gates relaxed). Source tiering, fact extraction, comparison frameworks, validation, exact-fit component selection. Run multiple rounds until the solution is solid.
|
||||
|
||||
### plan
|
||||
|
||||
6-step planning workflow. Produces integration test specs, architecture, system flows, data model, deployment plan, component specs with interfaces, risk assessment, test specifications, and work item epics. Heavy interaction at BLOCKING gates.
|
||||
6-step planning workflow with one half-step (4.5: Architecture Decision Records). Produces blackbox test specs (delegated to test-spec), glossary, architecture vision, architecture document, data model, deployment plan, component specs with interfaces, risk assessment, ADRs, test specifications, and work item epics. Heavy interaction at BLOCKING gates (glossary+vision, architecture, components, mitigations, ADRs).
|
||||
|
||||
### test-spec
|
||||
|
||||
4-phase test specification workflow. Phase 1 analyzes input data + expected-results completeness. Phase 2 emits 8 test artifacts (environment, test-data, blackbox, performance, resilience, security, resource-limit, traceability matrix). Phase 3 is the hard gate that requires every test to have quantifiable expected results. Phase 4 emits runner scripts. Cycle-update mode for incremental refresh.
|
||||
|
||||
### decompose
|
||||
|
||||
4-step task decomposition. Produces a bootstrap structure plan, atomic task specs per component, integration test tasks, and a cross-task dependency table. Each task gets a work item ticket and is capped at 8 complexity points.
|
||||
Multi-mode task decomposition with 6 internal step files. Implementation mode runs Step 1 (Bootstrap), 1.5 (Module Layout), 1.7 (System-Pipeline owner tasks), 2 (per-component tasks), 4 (Cross-Verification). Tests-only mode runs Step 1t (Test Infrastructure), 3 (Blackbox tasks), 4. Single-component mode runs Step 2 only. Each task is tracker-prefixed and capped at 5 complexity points. The 1.7 step exists specifically to prevent the GPS-passthrough class of failure (see `meta-rule.mdc`).
|
||||
|
||||
### implement
|
||||
|
||||
Orchestrator that reads task specs, computes dependency-aware execution batches, launches up to 4 parallel implementer subagents, runs code review after each batch, and commits per batch. Does not write code itself.
|
||||
|
||||
### deploy
|
||||
|
||||
7-step deployment planning. Status check, containerization, CI/CD pipeline, environment strategy, observability, deployment procedures, and deployment scripts. Produces documents for steps 1-6 and executable scripts in step 7.
|
||||
Orchestrator that reads task specs, computes dependency-aware execution batches via topological sort, **implements tasks sequentially within each batch** (no subagents, no parallel execution — see `.cursor/rules/no-subagents.mdc`), runs code review after each batch, runs cumulative code review every K batches, and commits per batch. Has a Product Implementation Completeness Gate (Step 15) that compares promises in task specs / architecture against actual production code, plus a System-Pipeline Audit (Step 15.b) that walks architecture-named pipelines and verifies a real production caller wires each adjacent component pair. Either gate's FAIL stops the cycle until remediation tasks are created.
|
||||
|
||||
### code-review
|
||||
|
||||
Multi-phase code review against task specs. Produces structured findings with verdict: PASS, FAIL, or PASS_WITH_WARNINGS.
|
||||
7-phase code review against task specs (Phase 7 is Architecture Compliance against `module-layout.md` and `architecture.md`). Produces structured findings with verdict: PASS, PASS_WITH_WARNINGS, or FAIL. Three modes: full (per batch), baseline (one-time architecture scan of an existing codebase), cumulative (mid-implementation across batches with `## Baseline Delta`).
|
||||
|
||||
### test-run
|
||||
|
||||
Runs the test suite. Functional mode (default): detects pytest/dotnet/cargo/npm or `scripts/run-tests.sh`, applies a System-Under-Test Reality Gate to refuse passes where internal product modules were stubbed, classifies failures and skips, gates on outcome. Perf mode: detects `scripts/run-performance-tests.sh` or k6/locust/artillery/wrk, captures latency/throughput/error metrics, compares against thresholds.
|
||||
|
||||
### refactor
|
||||
|
||||
6-phase structured refactoring: baseline, discovery, analysis, safety net, execution, hardening.
|
||||
8-phase structured refactoring: baseline → discovery → analysis → safety net → execution → test sync → verification → documentation. Two input modes (Automatic / Guided). Testability sub-mode skips Phase 3 by design and emits a `testability_changes_summary.md` for user review. Each run lives in its own `RUN_DIR` under `_docs/04_refactoring/NN-<run-name>/`.
|
||||
|
||||
### security
|
||||
|
||||
OWASP-based security testing and audit.
|
||||
5-phase OWASP-based audit: dependency scan → static analysis → OWASP Top 10 review → infrastructure review → consolidated security report. Severity-ranked, evidence-based, actionable. Complementary to `code-review` Phase 4 (lightweight security quick-scan).
|
||||
|
||||
### deploy
|
||||
|
||||
7-step deployment planning. Produces documents for steps 1–6 (status & env, containerization, CI/CD pipeline, environment strategy, observability, deployment procedures) and executable scripts in step 7 (`deploy.sh`, `pull-images.sh`, `start-services.sh`, `stop-services.sh`, `health-check.sh`).
|
||||
|
||||
### release
|
||||
|
||||
Executes the deployment plan produced by `/deploy` against a target environment. 6 phases: pre-release gate (AC + risk + rollback readiness), strategy select (all-at-once / blue-green / canary / manual), execute (run scripts, monitor exit codes), smoke test (delegate to test-run prod-smoke), watch window (read observability for the configured duration), commit-or-rollback. Outputs `_docs/04_release/release_<version>.md`. Produces a definitive Released / Rolled-Back / Aborted verdict; failure of any phase auto-triggers rollback unless the user opts to investigate.
|
||||
|
||||
### retrospective
|
||||
|
||||
Collects metrics from implementation batch reports, analyzes trends, produces improvement reports.
|
||||
4-step workflow: collect metrics → analyze trends → produce report → update lessons log (`_docs/LESSONS.md`, ring buffer of last 15 entries consumed by `new-task`, `plan`, `decompose`, and `autodev`). Cycle-end (default) and incident modes; incident mode is auto-invoked after a 3-strike failure.
|
||||
|
||||
### document
|
||||
|
||||
Bottom-up codebase documentation. Analyzes existing code from modules through components to architecture, then retrospectively derives problem/restrictions/acceptance criteria. Alternative entry point for existing codebases — produces the same `_docs/` artifacts as problem + plan, but from code analysis instead of user interview.
|
||||
Bottom-up codebase documentation. Analyzes existing code from modules through components to architecture, then retrospectively derives problem/restrictions/acceptance criteria. Alternative entry point for existing codebases — produces the same `_docs/` artifacts as problem + plan, but from code analysis instead of user interview. Two workflow files: `workflows/full.md` (full / focus-area / resume) and `workflows/task.md` (incremental update for a single task).
|
||||
|
||||
### new-task
|
||||
|
||||
Existing-code feature planning loop. Walks the user through Step 1 (description) → Step 2 (complexity assessment, consults `LESSONS.md`) → Step 3 (research if needed) → Step 4 (codebase analysis incl. test-coverage gap) → Step 4.5 (contract & layout check) → Step 5 (validate assumptions) → Step 6 (write task spec) → Step 7 (tracker ticket) → Step 8 (loop or finalize).
|
||||
|
||||
### ui-design
|
||||
|
||||
End-to-end UI workflow. Phase 0 (complexity detection: full vs quick) → Phase 1 (context check) → Phase 2 (requirements) → Phase 3 (direction exploration) → Phase 4 (design system synthesis: `DESIGN.md`) → Phase 5 (HTML+Tailwind code generation) → Phase 6 (visual verification, optional MCP enhancements) → Phase 7 (user review) → Phase 8 (iteration). Has Applicability Check that refuses to run on non-UI projects.
|
||||
|
||||
### monorepo-* (suite-level)
|
||||
|
||||
Six skills for meta-repos: `monorepo-discover` (write/refresh `_docs/_repo-config.yaml`), `monorepo-document` (sync unified docs), `monorepo-cicd` (sync CI/compose/env templates), `monorepo-onboard` (atomic add-component), `monorepo-status` (read-only drift report), `monorepo-e2e` (sync suite-level integration harness). They never cross domains; each touches exactly one artifact class.
|
||||
|
||||
## Developer TODO (Project Mode)
|
||||
|
||||
### BUILD
|
||||
The numbered list below mirrors greenfield-flow ordering. Existing-code projects start at `/document`, then enter the feature-cycle loop at `/new-task`. See `skills/autodev/flows/{greenfield,existing-code,meta-repo}.md` for the authoritative step tables.
|
||||
|
||||
### BUILD (greenfield)
|
||||
|
||||
```
|
||||
0. /problem — interactive interview → _docs/00_problem/
|
||||
- problem.md (required)
|
||||
- restrictions.md (required)
|
||||
- acceptance_criteria.md (required)
|
||||
- input_data/ (required)
|
||||
- security_approach.md (optional)
|
||||
|
||||
1. /research — solution drafts → _docs/01_solution/
|
||||
Run multiple times: Mode A → draft, Mode B → assess & revise
|
||||
|
||||
2. /plan — architecture, data model, deployment, components, risks, tests, epics → _docs/02_document/
|
||||
|
||||
3. /decompose — atomic task specs + dependency table → _docs/02_tasks/todo/
|
||||
|
||||
4. /implement — batched parallel agents, code review, commit per batch → _docs/03_implementation/
|
||||
1. /problem — interactive 4-phase interview → _docs/00_problem/
|
||||
required: problem.md, restrictions.md, acceptance_criteria.md, input_data/
|
||||
optional: security_approach.md
|
||||
2. /research — solution drafts (Mode A draft, Mode B assess) → _docs/01_solution/
|
||||
3. /plan — glossary, architecture vision, architecture, data model, deployment, components,
|
||||
risks, ADRs (Step 4.5), test specs, epics → _docs/02_document/
|
||||
(Step 1 invokes /test-spec internally)
|
||||
4. /ui-design — HTML+Tailwind mockups (UI projects only) → _docs/02_document/ui_mockups/
|
||||
5. /test-spec — produces 8 test-spec artifacts + traceability matrix → _docs/02_document/tests/
|
||||
(already invoked from /plan Step 1; Step 5 here is the explicit autodev step)
|
||||
6. /decompose — implementation tasks + module-layout + system-pipeline owner tasks →
|
||||
_docs/02_tasks/todo/
|
||||
7. /implement — sequential dependency-aware batches; per-batch code-review;
|
||||
Product Completeness Gate + System-Pipeline Audit → _docs/03_implementation/
|
||||
8. (auto) Code Testability Revision — surgical refactor to make code runnable under tests
|
||||
9. /decompose tests — test-only decomposition mode → _docs/02_tasks/todo/
|
||||
10. /implement (tests) — implements test tasks
|
||||
11. /test-run — full functional suite gate
|
||||
12. /test-spec --cycle-update — append implementation-learned scenarios
|
||||
13. /document --task — update affected component / module / architecture docs
|
||||
14. /security — OWASP-based audit (optional gate)
|
||||
15. /test-run --perf — perf/load tests (optional gate)
|
||||
```
|
||||
|
||||
### SHIP
|
||||
|
||||
```
|
||||
5. /deploy — containerization, CI/CD, environments, observability, procedures → _docs/04_deploy/
|
||||
16. /deploy — containerization, CI/CD, environments, observability, procedures, scripts → _docs/04_deploy/
|
||||
17. /release — execute deploy artifacts in prod, smoke-test, watch, decide rollback → _docs/04_release/
|
||||
```
|
||||
|
||||
### EVOLVE
|
||||
|
||||
```
|
||||
6. /refactor — structured refactoring → _docs/04_refactoring/
|
||||
7. /retrospective — metrics, trends, improvement actions → _docs/06_metrics/
|
||||
18. /retrospective — metrics + trends + lessons-log update → _docs/06_metrics/ + _docs/LESSONS.md
|
||||
(cycle-end mode after release; incident mode auto-fires after 3-strike failure)
|
||||
|
||||
After greenfield completes, the state file is rewritten to point at the existing-code flow's
|
||||
feature-cycle loop, which begins with /new-task and ends with /retrospective. The loop runs once
|
||||
per feature with state.cycle incremented.
|
||||
|
||||
Off-cycle:
|
||||
/refactor — full 8-phase refactor → _docs/04_refactoring/NN-<run-name>/
|
||||
/document — full reverse-engineering of an unfamiliar codebase
|
||||
```
|
||||
|
||||
Or just use `/autodev` to run steps 0-5 automatically.
|
||||
Or just use `/autodev` to run all the above automatically — the orchestrator chooses the right flow, sequences steps, surfaces lessons, processes leftovers, and pauses only at BLOCKING gates and declared session boundaries.
|
||||
|
||||
## Available Skills
|
||||
|
||||
| Skill | Triggers | Output |
|
||||
|-------|----------|--------|
|
||||
| **autodev** | "autodev", "auto", "start", "continue", "what's next" | Orchestrates full workflow |
|
||||
| **autodev** | "autodev", "auto", "start", "continue", "what's next" | Orchestrates full workflow (3 flows) |
|
||||
| **problem** | "problem", "define problem", "new project" | `_docs/00_problem/` |
|
||||
| **research** | "research", "investigate" | `_docs/01_solution/` |
|
||||
| **plan** | "plan", "decompose solution" | `_docs/02_document/` |
|
||||
| **plan** | "plan", "decompose solution" | `_docs/02_document/` (incl. ADRs) |
|
||||
| **test-spec** | "test spec", "blackbox tests", "test scenarios" | `_docs/02_document/tests/` + `scripts/` |
|
||||
| **decompose** | "decompose", "task decomposition" | `_docs/02_tasks/todo/` |
|
||||
| **implement** | "implement", "start implementation" | `_docs/03_implementation/` |
|
||||
| **test-run** | "run tests", "test suite", "verify tests" | Test results + verdict |
|
||||
| **code-review** | "code review", "review code" | Verdict: PASS / FAIL / PASS_WITH_WARNINGS |
|
||||
| **decompose** | "decompose", "task decomposition", "decompose tests" | `_docs/02_tasks/todo/` + `_docs/02_document/module-layout.md` |
|
||||
| **implement** | "implement", "start implementation" | `_docs/03_implementation/` (sequential — see `no-subagents.mdc`) |
|
||||
| **test-run** | "run tests", "test suite", "verify tests", "perf test" | Test results + verdict |
|
||||
| **code-review** | "code review", "review code" | Verdict: PASS / FAIL / PASS_WITH_WARNINGS (7 phases) |
|
||||
| **new-task** | "new task", "add feature", "new functionality" | `_docs/02_tasks/todo/` |
|
||||
| **ui-design** | "design a UI", "mockup", "design system" | `_docs/02_document/ui_mockups/` |
|
||||
| **refactor** | "refactor", "improve code" | `_docs/04_refactoring/` |
|
||||
| **security** | "security audit", "OWASP" | `_docs/05_security/` |
|
||||
| **refactor** | "refactor", "improve code", "testability" | `_docs/04_refactoring/NN-<run-name>/` |
|
||||
| **security** | "security audit", "OWASP", "vulnerability scan" | `_docs/05_security/` |
|
||||
| **document** | "document", "document codebase", "reverse-engineer docs" | `_docs/02_document/` + `_docs/00_problem/` + `_docs/01_solution/` |
|
||||
| **deploy** | "deploy", "CI/CD", "observability" | `_docs/04_deploy/` |
|
||||
| **retrospective** | "retrospective", "retro" | `_docs/06_metrics/` |
|
||||
| **deploy** | "deploy", "CI/CD", "observability", "containerize" | `_docs/04_deploy/` (plans + scripts) |
|
||||
| **release** | "release", "ship", "go live", "rollback" | `_docs/04_release/` (executed deploy + verdict) |
|
||||
| **retrospective** | "retrospective", "retro", "metrics review" | `_docs/06_metrics/` + `_docs/LESSONS.md` |
|
||||
| **monorepo-discover** | "discover monorepo", "scan submodules" | `_docs/_repo-config.yaml` |
|
||||
| **monorepo-document** | "sync monorepo docs" | unified `_docs/*.md` |
|
||||
| **monorepo-cicd** | "sync compose", "sync ci" | suite-level CI/compose/env templates |
|
||||
| **monorepo-onboard** | "onboard component", "register submodule" | atomic component addition |
|
||||
| **monorepo-status** | "monorepo status", "drift report" | read-only drift report |
|
||||
| **monorepo-e2e** | "suite e2e", "integration harness" | `e2e/docker-compose.suite-e2e.yml` and fixtures |
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | Type | Purpose |
|
||||
|------|------|---------|
|
||||
| `implementer` | Subagent | Implements a single task. Launched by `/implement`. |
|
||||
> The `.cursor/agents/` directory is intentionally empty. Per `.cursor/rules/no-subagents.mdc` the main agent does not delegate to subagents in this workspace; `/implement` runs tasks sequentially.
|
||||
|
||||
## Project Folder Structure
|
||||
|
||||
```
|
||||
_project.md — project-specific config (tracker type, project key, etc.)
|
||||
_docs/
|
||||
├── _autodev_state.md — autodev orchestrator state (progress, decisions, session context)
|
||||
├── 00_problem/ — problem definition, restrictions, AC, input data
|
||||
├── _autodev_state.md — autodev orchestrator state (≤30 lines; pointer only)
|
||||
├── _process_leftovers/ — deferred tracker writes replayed at next /autodev (per tracker.mdc)
|
||||
├── _repo-config.yaml — meta-repo only; produced by monorepo-discover
|
||||
├── LESSONS.md — ring buffer of last 15 actionable lessons (consumed by autodev/new-task/plan/decompose)
|
||||
├── 00_problem/ — problem definition, restrictions, AC, input data + expected_results/
|
||||
├── 00_research/ — intermediate research artifacts
|
||||
├── 01_solution/ — solution drafts, tech stack, security analysis
|
||||
├── 02_document/
|
||||
│ ├── architecture.md
|
||||
│ ├── architecture.md — includes ## Architecture Vision (user-confirmed)
|
||||
│ ├── glossary.md — user-confirmed terminology
|
||||
│ ├── system-flows.md
|
||||
│ ├── data_model.md
|
||||
│ ├── module-layout.md — per-component Owns/Imports-from/Public API (decompose Step 1.5)
|
||||
│ ├── architecture_compliance_baseline.md — existing-code baseline scan output
|
||||
│ ├── risk_mitigations.md
|
||||
│ ├── adr/[NNN]_[decision_slug].md — Architectural Decision Records (plan Step 4.5)
|
||||
│ ├── components/[##]_[name]/ — description.md + tests.md per component
|
||||
│ ├── contracts/<component>/<name>.md — versioned public-API contracts
|
||||
│ ├── common-helpers/
|
||||
│ ├── tests/ — environment, test data, blackbox, performance, resilience, security, traceability
|
||||
│ ├── deployment/ — containerization, CI/CD, environments, observability, procedures
|
||||
│ ├── tests/ — environment, test-data, blackbox, performance, resilience, security, resource-limit, traceability matrix
|
||||
│ ├── ui_mockups/ — HTML+CSS mockups, DESIGN.md (ui-design skill)
|
||||
│ ├── diagrams/
|
||||
│ └── FINAL_report.md
|
||||
@@ -192,12 +255,13 @@ _docs/
|
||||
│ ├── backlog/ — parked tasks (not scheduled yet)
|
||||
│ └── done/ — completed/archived tasks
|
||||
├── 02_task_plans/ — per-task research artifacts (new-task skill)
|
||||
├── 03_implementation/ — batch reports, implementation_report_*.md
|
||||
├── 03_implementation/ — batch_*_cycle*.md, implementation_report_*.md, implementation_completeness_cycle*.md, cumulative_review_*.md
|
||||
│ └── reviews/ — code review reports per batch
|
||||
├── 04_deploy/ — containerization, CI/CD, environments, observability, procedures, scripts
|
||||
├── 04_refactoring/ — baseline, discovery, analysis, execution, hardening
|
||||
├── 05_security/ — dependency scan, SAST, OWASP review, security report
|
||||
└── 06_metrics/ — retro_[YYYY-MM-DD].md
|
||||
├── 04_deploy/ — containerization, CI/CD, environments, observability, procedures, deploy_scripts.md, reports/
|
||||
├── 04_refactoring/NN-<run-name>/ — baseline_metrics, discovery, analysis, test_specs, execution_log, test_sync, verification, FINAL_report (one folder per refactor run)
|
||||
├── 04_release/ — release_<version>.md (one per /release invocation), rollback_<version>.md
|
||||
├── 05_security/ — dependency_scan, static_analysis, owasp_review, infrastructure_review, security_report
|
||||
└── 06_metrics/ — retro_<YYYY-MM-DD>.md, structure_<YYYY-MM-DD>.md, perf_<YYYY-MM-DD>_<run-label>.md, incident_<YYYY-MM-DD>_<skill>.md
|
||||
```
|
||||
|
||||
## Standalone Mode
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
---
|
||||
name: implementer
|
||||
description: |
|
||||
Implements a single task from its spec file. Use when implementing tasks from _docs/02_tasks/todo/.
|
||||
Reads the task spec, analyzes the codebase, implements the feature with tests, and verifies acceptance criteria.
|
||||
Launched by the /implement skill as a subagent.
|
||||
---
|
||||
|
||||
You are a professional software developer implementing a single task.
|
||||
|
||||
## Input
|
||||
|
||||
You receive from the `/implement` orchestrator:
|
||||
- Path to a task spec file (e.g., `_docs/02_tasks/todo/[TRACKER-ID]_[short_name].md`)
|
||||
- Files OWNED (exclusive write access — only you may modify these)
|
||||
- Files READ-ONLY (shared interfaces, types — read but do not modify)
|
||||
- Files FORBIDDEN (other agents' owned files — do not touch)
|
||||
|
||||
## Context (progressive loading)
|
||||
|
||||
Load context in this order, stopping when you have enough:
|
||||
|
||||
1. Read the task spec thoroughly — acceptance criteria, scope, constraints, dependencies
|
||||
2. Read `_docs/02_tasks/_dependencies_table.md` to understand where this task fits
|
||||
3. Read project-level context:
|
||||
- `_docs/00_problem/problem.md`
|
||||
- `_docs/00_problem/restrictions.md`
|
||||
- `_docs/01_solution/solution.md`
|
||||
4. Analyze the specific codebase areas related to your OWNED files and task dependencies
|
||||
|
||||
## Boundaries
|
||||
|
||||
**Always:**
|
||||
- Run tests before reporting done
|
||||
- Follow existing code conventions and patterns
|
||||
- Implement error handling per the project's strategy
|
||||
- Stay within the task spec's Scope/Included section
|
||||
|
||||
**Ask first:**
|
||||
- Adding new dependencies or libraries
|
||||
- Creating files outside your OWNED directories
|
||||
- Changing shared interfaces that other tasks depend on
|
||||
|
||||
**Never:**
|
||||
- Modify files in the FORBIDDEN list
|
||||
- Skip writing tests
|
||||
- Change database schema unless the task spec explicitly requires it
|
||||
- Commit secrets, API keys, or passwords
|
||||
- Modify CI/CD configuration unless the task spec explicitly requires it
|
||||
|
||||
## Process
|
||||
|
||||
1. Read the task spec thoroughly — understand every acceptance criterion
|
||||
2. Analyze the existing codebase: conventions, patterns, related code, shared interfaces
|
||||
3. Research best implementation approaches for the tech stack if needed
|
||||
4. If the task has a dependency on an unimplemented component, create a minimal interface mock
|
||||
5. Implement the feature following existing code conventions
|
||||
6. Implement error handling per the project's defined strategy
|
||||
7. Implement unit tests (use Arrange / Act / Assert section comments in language-appropriate syntax)
|
||||
8. Implement integration tests — analyze existing tests, add to them or create new
|
||||
9. Run all tests, fix any failures
|
||||
10. Verify every acceptance criterion is satisfied — trace each AC with evidence
|
||||
|
||||
## Stop Conditions
|
||||
|
||||
- If the same fix fails 3+ times with different approaches, stop and report as blocker
|
||||
- If blocked on an unimplemented dependency, create a minimal interface mock and document it
|
||||
- If the task scope is unclear, stop and ask rather than assume
|
||||
|
||||
## Completion Report
|
||||
|
||||
Report using this exact structure:
|
||||
|
||||
```
|
||||
## Implementer Report: [task_name]
|
||||
|
||||
**Status**: Done | Blocked | Partial
|
||||
**Task**: [TRACKER-ID]_[short_name]
|
||||
|
||||
### Acceptance Criteria
|
||||
| AC | Satisfied | Evidence |
|
||||
|----|-----------|----------|
|
||||
| AC-1 | Yes/No | [test name or description] |
|
||||
| AC-2 | Yes/No | [test name or description] |
|
||||
|
||||
### Files Modified
|
||||
- [path] (new/modified)
|
||||
|
||||
### Test Results
|
||||
- Unit: [X/Y] passed
|
||||
- Integration: [X/Y] passed
|
||||
|
||||
### Mocks Created
|
||||
- [path and reason, or "None"]
|
||||
|
||||
### Blockers
|
||||
- [description, or "None"]
|
||||
```
|
||||
|
||||
## Principles
|
||||
|
||||
- Follow SOLID, KISS, DRY
|
||||
- Dumb code, smart data
|
||||
- No unnecessary comments or logs (only exceptions)
|
||||
- Ask if requirements are ambiguous — do not assume
|
||||
@@ -39,8 +39,11 @@ alwaysApply: true
|
||||
- When you think you are done with changes, run the full test suite. Every failure in tests that cover code you modified or that depend on code you modified is a **blocking gate**. For pre-existing failures in unrelated areas, report them to the user but do not block on them. Never silently ignore or skip a failure without reporting it. On any blocking failure, stop and ask the user to choose one of:
|
||||
- **Investigate and fix** the failing test or source code
|
||||
- **Remove the test** if it is obsolete or no longer relevant
|
||||
- **Iterative-skill exception**: when an iterative loop skill is active (e.g. autodev / `implement/SKILL.md` batch loop, `refactor/SKILL.md` batch loop), the skill governs full-suite cadence — typically focused tests per task/batch and a single full-suite gate at the very end of the implementation phase, NOT after each batch. "Done with changes" means done with the entire implementation phase the skill is running, not done with one batch. Do not run the full suite per batch unless the skill explicitly says to.
|
||||
- Do not rename any databases or tables or table columns without confirmation. Avoid such renaming if possible.
|
||||
|
||||
- Make sure we don't commit binaries, create and keep .gitignore up to date and delete binaries after you are done with the task
|
||||
- Never force-push to main or dev branches
|
||||
- For new projects, place source code under `src/` (this works for all stacks including .NET). For existing projects, follow the established directory structure. Keep project-level config, tests, and tooling at the repo root.
|
||||
- **Never run e2e or CI tests in quiet mode (`-q`).** Always use `-v --tb=short` (or equivalent verbosity flags) in all Dockerfiles, compose files, and scripts that invoke pytest. Full test output must be visible so failures can be diagnosed without re-running. This applies to both Tier-1 (Colima) and Tier-2 (Jetson) harnesses.
|
||||
- **Never substitute real algorithm execution with a data passthrough to make tests pass.** If a test is designed to validate output from a specific pipeline (e.g. VIO estimation, sensor fusion, inference), the implementation MUST actually run that pipeline — not bypass it by returning the input data directly as output. Tests that pass by skipping the component they are supposed to exercise create false confidence and hide the fact that the component is not integrated. If the real integration cannot be completed in this session, STOP and report the blocker to the user explicitly. A failing test with an honest explanation is always better than a passing test that proves nothing.
|
||||
|
||||
@@ -19,7 +19,7 @@ globs: [".cursor/**"]
|
||||
- Kebab-case filenames
|
||||
|
||||
## Agent Files (.cursor/agents/)
|
||||
- Must have `name` and `description` in frontmatter
|
||||
- The `.cursor/agents/` directory is intentionally empty. Per `.cursor/rules/no-subagents.mdc`, the main agent does not delegate to subagents in this workspace. Do not add agent files here without a corresponding rule change.
|
||||
|
||||
## Security
|
||||
- All `.cursor/` files must be scanned for hidden Unicode before committing (see cursor-security.mdc)
|
||||
@@ -30,10 +30,11 @@ All rules and skills must reference the single source of truth below. Do NOT res
|
||||
|
||||
| Concern | Threshold | Enforcement |
|
||||
|---------|-----------|-------------|
|
||||
| Test coverage on business logic | 75% | Aim (warn below); 100% on critical paths |
|
||||
| Test coverage on business logic | 75% | Aim (warn below); critical-path floor enforced separately (next row) |
|
||||
| Test coverage on critical paths | 90% floor / 100% aim | **90% is the enforcement floor** in CI gates, refactor verification, and release pre-flight. **100% is the aim** — drift below 100% but at-or-above 90% is acceptable; drift below 90% blocks. Critical paths = code paths where a bug would cause data loss, security breach, financial error, or system outage; identify from `acceptance_criteria.md` (must-have) and `_docs/00_problem/security_approach.md`. |
|
||||
| Test scenario coverage (vs AC + restrictions) | 75% | Blocking in test-spec Phase 1 and Phase 3 |
|
||||
| CI coverage gate | 75% | Fail build below |
|
||||
| CI coverage gate | 75% overall, 90% critical-path | Fail build below either threshold |
|
||||
| Lint errors (Critical/High) | 0 | Blocking pre-commit |
|
||||
| Code-review auto-fix | Low + Medium (Style/Maint/Perf) + High (Style/Scope) | Critical and Security always escalate |
|
||||
| Code-review auto-fix | Low + Medium (Style/Maint/Perf) + High (Style/Scope) | Critical and Security always escalate. Full categorization: see `.cursor/skills/implement/SKILL.md` § "Auto-Fix eligibility matrix" |
|
||||
|
||||
When a skill or rule needs to cite a threshold, link to this table instead of hardcoding a different number.
|
||||
When a skill or rule needs to cite a threshold, link to this table instead of hardcoding a different number. The full auto-fix eligibility matrix (severity × category) lives in `implement/SKILL.md`; cite that file rather than re-tabulating the matrix.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
description: "Use chunked writes (Write + StrReplace marker pattern) for large generated files, especially after a monolithic Write fails"
|
||||
alwaysApply: true
|
||||
---
|
||||
# Large File Writes — Chunk on Failure
|
||||
|
||||
When a `Write` call to a single file fails (timeout, payload limit, "Invalid arguments", or any tool error) and the intended content is large (>~500 lines or >~50 KB), do NOT retry the same monolithic Write. Switch to chunked writes:
|
||||
|
||||
1. **First Write** — create the file with header + table of contents (if applicable) + an explicit append marker, e.g.
|
||||
|
||||
```
|
||||
<!-- INSERTION_POINT do-not-remove-until-final-chunk -->
|
||||
```
|
||||
|
||||
2. **Each subsequent chunk** — use `StrReplace` to replace the marker with `<new content>\n<marker>` so the marker stays at the end. This is idempotent: if a chunk fails, retry it without losing earlier chunks.
|
||||
|
||||
3. **Final chunk** — `StrReplace` removes the marker.
|
||||
|
||||
## Why
|
||||
|
||||
- Tool argument size limits and transient failures hit large monolithic writes hardest. Retrying the same large payload typically fails for the same reason.
|
||||
- Chunked writes are recoverable per chunk. The earlier chunks are durable on disk.
|
||||
- A unique marker is greppable, visible in diffs, and stops accidental insertion in the wrong place.
|
||||
|
||||
## Triggers
|
||||
|
||||
- Generated documentation that aggregates per-component content (epics, design docs, multi-section architecture summaries, traceability dumps).
|
||||
- Large fixture or test-data files written from a template.
|
||||
- Any single-file artifact you can pre-estimate at >~500 lines.
|
||||
|
||||
## Do NOT chunk
|
||||
|
||||
- Files under ~200 lines — a single `Write` is faster, clearer, and easier to review.
|
||||
- Source code files where appending breaks module structure (functions, classes, imports). Split into multiple files instead.
|
||||
- Files where ordering of sections is computed late and inserting in the middle is required — use a single `Write` once the full content is known.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Retrying the same failed monolithic `Write` more than once. Twice is the limit; on the second failure, switch strategies.
|
||||
- Using `Shell` with heredoc (`cat <<EOF`) or `echo >>` to append — these bypass the editor diff view and break the StrReplace contract for the next chunk.
|
||||
- Embedding the marker so deep inside structured content that a chunk's `StrReplace` becomes ambiguous. Place the marker on its own line at the very end of the file.
|
||||
@@ -4,6 +4,26 @@ alwaysApply: true
|
||||
---
|
||||
# Agent Meta Rules
|
||||
|
||||
## Real Results, Not Simulated Ones
|
||||
|
||||
**The goal is a working product, not the appearance of one.**
|
||||
|
||||
- If something does not work, STOP and report it honestly. Do not find a way around it.
|
||||
- Never produce results by bypassing, faking, stubbing, or passthrough-ing the component that is supposed to produce them. A passing test that skips the real pipeline is worse than a failing test — it hides the truth.
|
||||
- If the real implementation is not ready, say so. A clear "this is not implemented yet, here is what is missing" is always the right answer.
|
||||
- Do not measure success by whether the output looks correct. Measure it by whether the output was produced by the real system under test.
|
||||
- Workarounds that produce the right answer via the wrong path are defects, not solutions.
|
||||
|
||||
### When a test reveals missing production code — STOP
|
||||
|
||||
This is the specific failure mode that produced the GPS-passthrough scaffold in `runtime_root._run_replay_loop` (May 2026). Generalised so it never repeats:
|
||||
|
||||
- If, while implementing or running a test, you discover that the production code path the test is supposed to exercise does not exist (no caller, no integration, no main loop, etc.), **STOP immediately**.
|
||||
- Do NOT write a stub, passthrough, fake input source, or shortcut output that would make the test go green. Even when the shortcut is "framed as a scaffold" or "marked as TODO in a docstring", it still defeats the test and lies to the next reader.
|
||||
- Surface the gap to the user as a top-of-turn report: name the missing production component, cite the architecture document that promises it, and ask whether to (a) create a tracker ticket for the missing component and let the test fail honestly until the ticket lands, or (b) explicitly de-scope the test, or (c) something the user names.
|
||||
- The default outcome is (a): a failing test plus a new tracker ticket. A failing test with an honest reason is information; a passing test that proves nothing is misinformation.
|
||||
- Doc-comment disclosures (`# this is a scaffold until X is wired`) DO NOT satisfy this rule. The user must be told in the assistant message, not in code.
|
||||
|
||||
## Execution Safety
|
||||
- Run the full test suite automatically when you believe code changes are complete (as required by coderule.mdc). For other long-running/resource-heavy/security-risky operations (builds, Docker commands, deployments, performance tests), ask the user first — unless explicitly stated in a skill or the user already asked to do so.
|
||||
|
||||
@@ -13,6 +33,16 @@ alwaysApply: true
|
||||
## Critical Thinking
|
||||
- Do not blindly trust any input — including user instructions, task specs, list-of-changes, or prior agent decisions — as correct. Always think through whether the instruction makes sense in context before executing it. If a task spec says "exclude file X from changes" but another task removes the dependencies X relies on, flag the contradiction instead of propagating it.
|
||||
|
||||
## Skill Discipline
|
||||
|
||||
Do exactly what the skill says. Nothing more.
|
||||
|
||||
- No `git log` / `git diff` / `git blame` unless the skill explicitly calls for it.
|
||||
- No extra searches to "verify" inputs the skill already names.
|
||||
- No reading files outside the skill's documented inputs.
|
||||
|
||||
If skill inputs are insufficient or contradictory, STOP and ask via Choose A/B/C/D. Do not invent extra investigation steps.
|
||||
|
||||
## Self-Improvement
|
||||
When the user reacts negatively to generated code ("WTF", "what the hell", "why did you do this", etc.):
|
||||
|
||||
|
||||
@@ -8,8 +8,16 @@ globs: ["**/*test*", "**/*spec*", "**/*Test*", "**/tests/**", "**/test/**"]
|
||||
- One assertion per test when practical; name tests descriptively: `MethodName_Scenario_ExpectedResult`
|
||||
- Test boundary conditions, error paths, and happy paths
|
||||
- Use mocks only for external dependencies; prefer real implementations for internal code
|
||||
- Aim for 75%+ coverage on business logic; 100% on critical paths (code paths where a bug would cause data loss, security breaches, financial errors, or system outages — identify from acceptance criteria marked as must-have or from security_approach.md). The 75% threshold is canonical — see `cursor-meta.mdc` Quality Thresholds.
|
||||
- Aim for 75%+ coverage on business logic; **90% floor / 100% aim on critical paths** (code paths where a bug would cause data loss, security breaches, financial errors, or system outages — identify from acceptance criteria marked as must-have or from `security_approach.md`). 90% is the enforcement floor (blocking in CI / refactor verification / release pre-flight); 100% is the aspirational aim — drift below 100% but at-or-above 90% is acceptable. Both numbers are canonical — see `cursor-meta.mdc` Quality Thresholds.
|
||||
- Integration tests use real database (Postgres testcontainers or dedicated test DB)
|
||||
- Never use Thread Sleep or fixed delays in tests; use polling or async waits
|
||||
- Keep test data factories/builders for reusable test setup
|
||||
- Tests must be independent: no shared mutable state between tests
|
||||
|
||||
## Test environment (this project)
|
||||
|
||||
- **Unit tests** (`tests/unit/`): may run locally on the dev workstation (`pytest tests/unit/` in the project venv). Local PASS is equivalent to Jetson PASS for this tier because the suite is fully synthetic.
|
||||
- **Blackbox / e2e / performance / resilience / security / resource-limit** tests (`tests/e2e/`, `e2e/tests/`, `tests/perf/`, …): MUST run on the Jetson Orin Nano Super (or a Jetson-equivalent arm64 agent). Use `scripts/run-tests-jetson.sh` for local dev; CI runs `.woodpecker/01-test.yml` on the colocated arm64 Jetson Woodpecker agent.
|
||||
- Do NOT run e2e tests on the local workstation and report the result. If the Jetson is unreachable, the e2e verdict is "not run" — record the gap in `_docs/_process_leftovers/` rather than substituting a local result.
|
||||
- Tests gated by `RUN_REPLAY_E2E` or `@pytest.mark.tier2` are expected to SKIP locally; that is correct behaviour, not a failure to investigate.
|
||||
- Canonical source for this policy: `_docs/02_document/tests/environment.md` § Where each tier runs (active policy).
|
||||
|
||||
@@ -14,11 +14,14 @@ alwaysApply: true
|
||||
- Issue types: Epic, Story, Task, Bug, Subtask
|
||||
|
||||
## Tracker Availability Gate
|
||||
- If Jira MCP returns **Unauthorized**, **errored**, **connection refused**, or any non-success response: **STOP** tracker operations and notify the user via the Choose A/B/C/D format documented in `.cursor/skills/autodev/protocols.md`.
|
||||
- If Jira MCP returns **Unauthorized**, **errored**, **connection refused**, **timeout**, a non-2xx status code, an empty body, or any response shape that does not clearly confirm the requested change: **STOP IMMEDIATELY** — no automatic retry, no silent continuation. Surface the full raw error/response to the user verbatim and notify via the Choose A/B/C/D format documented in `.cursor/skills/autodev/protocols.md`.
|
||||
- A minimal `{"success": true}` body with no echoed issue state is NOT a confirmed transition. When a transition's success matters (status moves, ticket creation, blocking link), follow it with a read-back call (`getJiraIssue` or equivalent) and confirm the new state matches what you asked for. If the read-back disagrees → STOP and ASK.
|
||||
- Do NOT loop "retry up to N times before asking". One call, one verification. On failure, the user decides whether to retry.
|
||||
- The user may choose to:
|
||||
- **Retry authentication** — preferred; the tracker remains the source of truth.
|
||||
- **Retry the same operation** — once, after the user authorizes it. If it fails again, surface both responses.
|
||||
- **Retry authentication** — preferred when the failure looks like an auth/credentials problem; the tracker remains the source of truth.
|
||||
- **Continue in `tracker: local` mode** — only when the user explicitly accepts this option. In that mode all tasks keep numeric prefixes and a `Tracker: pending` marker is written into each task header. The state file records `tracker: local`. The mode is NOT silent — the user has been asked and has acknowledged the trade-off.
|
||||
- Do NOT auto-fall-back to `tracker: local` without a user decision. Do not pretend a write succeeded. If the user is unreachable (e.g., non-interactive run), stop and wait.
|
||||
- Do NOT auto-fall-back to `tracker: local` without a user decision. Do not pretend a write succeeded. Do not paper over an opaque response by moving on. If the user is unreachable (e.g., non-interactive run), stop and wait.
|
||||
- When the tracker becomes available again, any `Tracker: pending` tasks should be synced — this is done at the start of the next `/autodev` invocation via the Leftovers Mechanism below.
|
||||
|
||||
## Leftovers Mechanism (non-user-input blockers only)
|
||||
|
||||
@@ -5,3 +5,40 @@
|
||||
- When a task requires changes in another repository (e.g., admin API, flights, UI), **document** the required changes in the task's implementation notes or a dedicated cross-repo doc — do not implement them.
|
||||
- The mock API at `e2e/mocks/mock_api/` may be updated to reflect the expected contract of external services, but this is a test mock — not the real implementation.
|
||||
- If a task is entirely scoped to another repository, mark it as out-of-scope for this workspace and note the target repository.
|
||||
|
||||
## Exception — Adding Task Specs to Sibling Repos
|
||||
|
||||
The ONLY permitted form of writing into a sibling repository is **creating task-spec markdown files** (and updating the matching `_dependencies_table.md`) in that repo's `_docs/02_tasks/todo/` directory, and ONLY when the user explicitly asks for it in the current turn.
|
||||
|
||||
- "Explicit" means the user names the action (e.g. "add the md files to satellite-provider", "create the task spec there", "mirror it into their repo"). Inference from context is NOT enough — ask first.
|
||||
- Mirror the sibling repo's existing template (read ONE of their `done/` task files to learn the format — this is process documentation, not source code).
|
||||
- NEVER commit or push in the sibling repo unless the user separately and explicitly authorizes it. Default is "write to disk, leave for their review".
|
||||
- Update `_dependencies_table.md` to keep it consistent with the new task files.
|
||||
- The exception covers task specs ONLY. It does NOT extend to source code, CI/compose files, README, design docs, scripts, env templates, or any other file type in the sibling repo.
|
||||
- Each task-spec md must point back to the Jira ticket (which is the source of truth) and reference where the work was discovered (originating ticket in this repo).
|
||||
|
||||
## External Systems Are Black Boxes
|
||||
|
||||
External systems (sibling repos, third-party services, parent-suite services like `satellite-provider`) are treated as **black boxes** governed by their published **contract** (OpenAPI spec, contracts/*.md, public schemas, env-var docs).
|
||||
|
||||
- Treat the contract as the ONLY source of truth about an external system. The contract is what you may rely on; the implementation is what you may NOT rely on.
|
||||
- Do NOT investigate, grep, read, browse, or reason about an external system's internal source, internal directory layout, internal database schema, internal config files, persistent volumes, cache contents, log formats, deployment scripts, or any other implementation detail — even when the sibling repo is right there on disk and you could.
|
||||
- The ONE acceptable use of an external repo's source files is to READ ITS CONTRACT (e.g., `../satellite-provider/_docs/02_document/contracts/api/*.md`, an `openapi.yaml`, a `.proto`, a published schema). The contract may live in the sibling repo because that's where the producer documents it — that's fine. Anything OUTSIDE the contract directory is off-limits.
|
||||
- When the external system fails (returns errors, returns malformed data, is unreachable, contradicts its contract): STOP and report it to the user with the exact symptom (status code, error message, missing field, timeout). Do NOT diagnose why by reading the external system's internals. The producer team owns its own diagnosis. The signal is the symptom.
|
||||
- "It works" / "it doesn't work" is the only thing you may conclude about an external system. "It works this way because of X internal mechanism" is forbidden.
|
||||
|
||||
## Why
|
||||
|
||||
- Internals drift; contracts are stable. Reasoning that depends on internals breaks when the producer refactors.
|
||||
- Investigating internals trains the wrong mental model — agents start "fixing" cross-repo bugs by adapting consumer code to producer quirks instead of flagging the contract gap.
|
||||
- The producer team is the authority on its own system. Bypassing them creates two competing diagnoses and erodes the contract boundary.
|
||||
- Time spent reading external internals is time NOT spent on the actual scope.
|
||||
|
||||
## Concrete examples
|
||||
|
||||
- ✅ Reading `../satellite-provider/_docs/02_document/contracts/api/tile-inventory.md` to learn the inventory POST schema.
|
||||
- ❌ Reading `../satellite-provider/SatelliteProvider.Api/Program.cs` to learn what the inventory endpoint does internally.
|
||||
- ❌ Listing `../satellite-provider/tiles/` to see what tiles are cached.
|
||||
- ❌ Reading `../satellite-provider/.env` to figure out what env vars it expects (read the producer's published `.env.example` or contract doc instead).
|
||||
- ✅ Reporting "satellite-provider returns 500 when I POST a 1-tile inventory for (z=15, x=19308, y=11420)".
|
||||
- ❌ Reporting "satellite-provider returns 500 because its `TileService.GetInventoryAsync` throws when the Postgres `tiles` table is empty".
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: autodev
|
||||
description: |
|
||||
Auto-chaining orchestrator that drives the full BUILD-SHIP workflow from problem gathering through deployment.
|
||||
Auto-chaining orchestrator that drives the full BUILD → SHIP → EVOLVE workflow from problem gathering through release and retrospective.
|
||||
Detects current project state from _docs/ folder, resumes from where it left off, and flows through
|
||||
problem → research → plan → test specs → decompose → implement → tests → docs sync → deploy without manual skill invocation.
|
||||
problem → research → plan (incl. ADRs) → test specs → decompose → implement → tests → docs sync → deploy → release → retrospective without manual skill invocation.
|
||||
Maximizes work per conversation by auto-transitioning between skills.
|
||||
Trigger phrases:
|
||||
- "autodev", "auto", "start", "continue"
|
||||
@@ -15,7 +15,7 @@ disable-model-invocation: true
|
||||
|
||||
# Autodev Orchestrator
|
||||
|
||||
Auto-chaining execution engine that drives the full BUILD → SHIP workflow. Detects project state from `_docs/`, resumes from where work stopped, and flows through skills automatically. The user invokes `/autodev` once — the engine handles sequencing, transitions, and re-entry.
|
||||
Auto-chaining execution engine that drives the full BUILD → SHIP → EVOLVE workflow. Detects project state from `_docs/`, resumes from where work stopped, and flows through skills automatically. The user invokes `/autodev` once — the engine handles sequencing, transitions, and re-entry.
|
||||
|
||||
## File Index
|
||||
|
||||
@@ -67,8 +67,9 @@ B3. Read state — `_docs/_autodev_state.md` (if it exists).
|
||||
B4. Read File Index — `state.md`, `protocols.md`, and the active flow file.
|
||||
|
||||
### Resolve (once per invocation, after Bootstrap)
|
||||
R1. Reconcile state — verify state file against `_docs/` contents; on disagreement, trust the folders
|
||||
and update the state file (rules: `state.md` → "State File Rules" #4).
|
||||
R1. Reconcile state — verify state file against `_docs/` contents; probe `<workspace-root>/../docs`
|
||||
(parent suite `docs/` — see `state.md` → "State File Rules" #4); on disagreement,
|
||||
trust the folders and update the state file (rules: `state.md` → "State File Rules" #4).
|
||||
After this step, `state.step` / `state.status` are authoritative.
|
||||
R2. Resolve flow — see §Flow Resolution above.
|
||||
R3. Resolve current step — when a state file exists, `state.step` drives detection.
|
||||
@@ -112,6 +113,15 @@ Do NOT modify, skip, or abbreviate any part of the sub-skill's workflow. The aut
|
||||
|
||||
The state file (`_docs/_autodev_state.md`) is a minimal pointer — only the current step. See `state.md` for the authoritative template, field semantics, update rules, and worked examples. Do not restate the schema here — `state.md` is the single source of truth.
|
||||
|
||||
**Conciseness rule (authoritative).** The state file MUST stay short. Acceptable content per field:
|
||||
|
||||
- `name` — the step title from the active flow's Step Reference Table. That's it.
|
||||
- `sub_step.name` — kebab-case identifier from the active sub-skill. That's it.
|
||||
- `sub_step.detail` — **leave empty (`""`) by default.** Add a one-line note ONLY when the next-session resumer cannot infer where to pick up from `phase` + `name` + on-disk artifacts alone (e.g. `"batch 2 of 4"`, `"blocked on D-PROJ-2 reply"`, `"variant 1b"`). NEVER use `detail` as a changelog, recap, or summary of completed work — those facts belong in the relevant `_docs/` artifact (glossary, traceability matrix, leftovers folder, retro report, etc.) and in git history.
|
||||
- **Total file size target: <30 lines.** If you're tempted to write more, you're using the wrong artifact — write in `_docs/` instead.
|
||||
|
||||
Multi-line `detail` blobs that recap what was just completed are a smell. The state file is a *pointer*, not a logbook.
|
||||
|
||||
## Trigger Conditions
|
||||
|
||||
This skill activates when the user wants to:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Workflow for projects with an existing codebase. Structurally it has **two phases**:
|
||||
|
||||
- **Phase A — One-time baseline setup (Steps 1–8)**: runs exactly once per codebase. Documents the code, produces test specs, makes the code testable, writes and runs the initial test suite, optionally refactors with that safety net.
|
||||
- **Phase B — Feature cycle (Steps 9–17, loops)**: runs once per new feature. After Step 17 (Retrospective), the flow loops back to Step 9 (New Task) with `state.cycle` incremented.
|
||||
- **Phase B — Feature cycle (Steps 9–17, loops)**: runs once per new feature. After Step 17 (Retrospective), the flow loops back to Step 9 (New Task) with `state.cycle` incremented. Step 16.5 (Release) sits between Deploy (16) and Retrospective (17).
|
||||
|
||||
A first-time run executes Phase A then Phase B; every subsequent invocation re-enters Phase B.
|
||||
|
||||
@@ -34,6 +34,7 @@ A first-time run executes Phase A then Phase B; every subsequent invocation re-e
|
||||
| 14 | Security Audit | security/SKILL.md | Phase 1–5 (optional) |
|
||||
| 15 | Performance Test | test-run/SKILL.md (perf mode) | Steps 1–5 (optional) |
|
||||
| 16 | Deploy | deploy/SKILL.md | Step 1–7 |
|
||||
| 16.5 | Release | release/SKILL.md | Phase 1–6 |
|
||||
| 17 | Retrospective | retrospective/SKILL.md (cycle-end mode) | Steps 1–4 |
|
||||
|
||||
After Step 17, the feature cycle completes and the flow loops back to Step 9 with `state.cycle + 1` — see "Re-Entry After Completion" below.
|
||||
@@ -287,21 +288,43 @@ State-driven: reached by auto-chain from Step 15 (completed or skipped).
|
||||
|
||||
Action: Read and execute `.cursor/skills/deploy/SKILL.md`.
|
||||
|
||||
After the deploy skill completes successfully, mark Step 16 as `completed` and auto-chain to Step 17 (Retrospective).
|
||||
After the deploy skill completes successfully, mark Step 16 as `completed` and auto-chain to Step 16.5 (Release).
|
||||
|
||||
---
|
||||
|
||||
**Step 16.5 — Release**
|
||||
State-driven: reached by auto-chain from Step 16, for the current `state.cycle`.
|
||||
|
||||
Action: Read and execute `.cursor/skills/release/SKILL.md`. The release skill owns its own user interaction (Phase 1 pre-release gate, Phase 2 strategy select, Phase 6 escalation). Autodev does NOT add a wrapping A/B/C gate. Pass cycle context (`cycle: state.cycle`).
|
||||
|
||||
After the release skill exits, route on the verdict:
|
||||
|
||||
- **Verdict `Released`** → mark Step 16.5 `completed` and auto-chain to Step 17 (Retrospective in cycle-end mode).
|
||||
- **Verdict `Released-with-override`** → mark Step 16.5 `completed` AND auto-chain to Step 17 (Retrospective in **incident mode**).
|
||||
- **Verdict `Rolled-Back`** → mark Step 16.5 `failed`. Auto-chain to Step 17 (Retrospective in **incident mode**). The cycle does NOT loop back to Step 9.
|
||||
- **Verdict `Aborted`** → mark Step 16.5 `not_started` (no live-system change) OR `failed` (live-system touched before abort). Surface the abort reason and STOP. Next `/autodev` invocation re-evaluates Phase B from the failed step.
|
||||
|
||||
---
|
||||
|
||||
**Step 17 — Retrospective**
|
||||
State-driven: reached by auto-chain from Step 16, for the current `state.cycle`.
|
||||
State-driven: reached by auto-chain from Step 16.5 with a `Released`, `Released-with-override`, or `Rolled-Back` verdict, for the current `state.cycle`.
|
||||
|
||||
Action: Read and execute `.cursor/skills/retrospective/SKILL.md` in **cycle-end mode**. Pass cycle context (`cycle: state.cycle`) so the retro report and LESSONS.md entries record which feature cycle they came from.
|
||||
Action: Read and execute `.cursor/skills/retrospective/SKILL.md`. Mode selection:
|
||||
|
||||
After retrospective completes, mark Step 17 as `completed` and enter "Re-Entry After Completion" evaluation.
|
||||
- Step 16.5 verdict `Released` → cycle-end mode
|
||||
- Step 16.5 verdict `Released-with-override` or `Rolled-Back` → incident mode
|
||||
|
||||
Pass cycle context (`cycle: state.cycle`) so the retro report and LESSONS.md entries record which feature cycle they came from.
|
||||
|
||||
After retrospective completes:
|
||||
|
||||
- If Step 16.5 verdict was `Released` or `Released-with-override` → mark Step 17 as `completed` and enter "Re-Entry After Completion" evaluation (loop back to Step 9 for cycle N+1).
|
||||
- If Step 16.5 verdict was `Rolled-Back` → mark Step 17 as `completed` but do NOT loop back. Surface the incident retro path and STOP.
|
||||
|
||||
---
|
||||
|
||||
**Re-Entry After Completion**
|
||||
State-driven: `state.step == done` OR Step 17 (Retrospective) is completed for `state.cycle`.
|
||||
State-driven: `state.step == done` OR Step 17 (Retrospective) is completed for `state.cycle` AND Step 16.5 verdict was `Released` or `Released-with-override`. A `Rolled-Back` cycle does NOT trigger Re-Entry — the user must explicitly invoke `/autodev` again.
|
||||
|
||||
Action: The project completed a full cycle. Print the status banner and automatically loop back to New Task — do NOT ask the user for confirmation:
|
||||
|
||||
@@ -316,7 +339,7 @@ Action: The project completed a full cycle. Print the status banner and automati
|
||||
|
||||
Set `step: 9`, `status: not_started`, and **increment `cycle`** (`cycle: state.cycle + 1`) in the state file, then auto-chain to Step 9 (New Task). Reset `sub_step` to `phase: 0, name: awaiting-invocation, detail: ""` and `retry_count: 0`.
|
||||
|
||||
Note: the loop (Steps 9 → 17 → 9) ensures every feature cycle includes: New Task → Implement → Run Tests → Test-Spec Sync → Update Docs → Security → Performance → Deploy → Retrospective.
|
||||
Note: the loop (Steps 9 → 17 → 9) ensures every feature cycle includes: New Task → Implement → Run Tests → Test-Spec Sync → Update Docs → Security → Performance → Deploy → Release → Retrospective. The cycle only completes (and loops back to Step 9) on a `Released` or `Released-with-override` verdict; rolled-back or aborted releases stop the cycle.
|
||||
|
||||
## Auto-Chain Rules
|
||||
|
||||
@@ -344,8 +367,13 @@ Note: the loop (Steps 9 → 17 → 9) ensures every feature cycle includes: New
|
||||
| Update Docs (13) | Auto-chain → Security Audit choice (14) |
|
||||
| Security Audit (14, done or skipped) | Auto-chain → Performance Test choice (15) |
|
||||
| Performance Test (15, done or skipped) | Auto-chain → Deploy (16) |
|
||||
| Deploy (16) | Auto-chain → Retrospective (17) |
|
||||
| Retrospective (17) | **Cycle complete** — loop back to New Task (9) with incremented cycle counter |
|
||||
| Deploy (16) | Auto-chain → Release (16.5) |
|
||||
| Release (16.5, verdict Released) | Auto-chain → Retrospective (17, cycle-end mode) |
|
||||
| Release (16.5, verdict Released-with-override) | Auto-chain → Retrospective (17, **incident mode**) |
|
||||
| Release (16.5, verdict Rolled-Back) | Auto-chain → Retrospective (17, **incident mode**); cycle does NOT loop back |
|
||||
| Release (16.5, verdict Aborted) | STOP — surface abort reason; do not auto-chain |
|
||||
| Retrospective (17, after Released / Released-with-override) | **Cycle complete** — loop back to New Task (9) with incremented cycle counter |
|
||||
| Retrospective (17, after Rolled-Back) | Cycle remains incomplete — STOP and surface incident retro path |
|
||||
|
||||
## Status Summary — Step List
|
||||
|
||||
@@ -381,6 +409,7 @@ Flow-specific slot values:
|
||||
| 14 | Security Audit | — |
|
||||
| 15 | Performance Test | — |
|
||||
| 16 | Deploy | — |
|
||||
| 16.5 | Release | `DONE (Released | Released-with-override | Rolled-Back | Aborted)` |
|
||||
| 17 | Retrospective | — |
|
||||
|
||||
All rows accept the shared state tokens (`DONE`, `IN PROGRESS`, `NOT STARTED`, `FAILED (retry N/3)`); rows 2, 4, 8, 12, 13, 14, 15 additionally accept `SKIPPED`.
|
||||
@@ -406,5 +435,6 @@ Row rendering format (renders with a phase separator between Step 8 and Step 9):
|
||||
Step 14 Security Audit [<state token>]
|
||||
Step 15 Performance Test [<state token>]
|
||||
Step 16 Deploy [<state token>]
|
||||
Step 16.5 Release [<state token>]
|
||||
Step 17 Retrospective [<state token>]
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Greenfield Workflow
|
||||
|
||||
Workflow for new projects built from scratch. Flows linearly: Problem → Research → Plan → UI Design (if applicable) → Test Spec → Decompose → Implement + Product Completeness Gate → Code Testability Revision → Decompose Tests → Implement Tests → Run Tests → Test-Spec Sync → Update Docs → Security Audit (optional) → Performance Test (optional) → Deploy → Retrospective.
|
||||
Workflow for new projects built from scratch. Flows linearly: Problem → Research → Plan → UI Design (if applicable) → Test Spec → Decompose → Implement + Product Completeness Gate → Code Testability Revision → Decompose Tests → Implement Tests → Run Tests → Test-Spec Sync → Update Docs → Security Audit (optional) → Performance Test (optional) → Deploy → Release → Retrospective.
|
||||
|
||||
## Step Reference Table
|
||||
|
||||
@@ -8,7 +8,7 @@ Workflow for new projects built from scratch. Flows linearly: Problem → Resear
|
||||
|------|------|-----------|-------------------|
|
||||
| 1 | Problem | problem/SKILL.md | Phase 1–4 |
|
||||
| 2 | Research | research/SKILL.md | Mode A: Phase 1–4 · Mode B: Step 0–8 |
|
||||
| 3 | Plan | plan/SKILL.md | Step 1–6 + Final |
|
||||
| 3 | Plan | plan/SKILL.md | Step 1, 2, 3, 4, 4.5 (ADR Capture), 5, 6 + Final |
|
||||
| 4 | UI Design | ui-design/SKILL.md | Phase 0–8 (conditional — UI projects only) |
|
||||
| 5 | Test Spec | test-spec/SKILL.md | Phases 1–4 |
|
||||
| 6 | Decompose | decompose/SKILL.md (implementation task decomposition) | Step 1 + Step 1.5 + Step 2 + Step 4 |
|
||||
@@ -22,6 +22,7 @@ Workflow for new projects built from scratch. Flows linearly: Problem → Resear
|
||||
| 14 | Security Audit | security/SKILL.md | Phase 1–5 (optional) |
|
||||
| 15 | Performance Test | test-run/SKILL.md (perf mode) | Steps 1–5 (optional) |
|
||||
| 16 | Deploy | deploy/SKILL.md | Step 1–7 |
|
||||
| 16.5 | Release | release/SKILL.md | Phase 1–6 |
|
||||
| 17 | Retrospective | retrospective/SKILL.md (cycle-end mode) | Steps 1–4 |
|
||||
|
||||
## Detection Rules
|
||||
@@ -225,7 +226,7 @@ State-driven: reached by auto-chain from Step 10.
|
||||
|
||||
Action: Read and execute `.cursor/skills/test-run/SKILL.md`
|
||||
|
||||
Verifies the implemented unit, integration, blackbox, and e2e tests pass before proceeding to spec and documentation sync.
|
||||
Verifies the implemented unit, integration, blackbox, and e2e tests pass before proceeding to spec and documentation sync. This is a hard product gate, not a harness-smoke gate: e2e/blackbox tests must exercise the actual implemented system through public runtime boundaries and compare actual outputs against `_docs/00_problem/input_data/expected_results/results_report.md` or referenced machine-readable expected-result files. Stubs are allowed only for external systems outside the product boundary; missing internal product implementation must fail or block the gate and send the flow back to Implement.
|
||||
|
||||
---
|
||||
|
||||
@@ -284,21 +285,42 @@ State-driven: reached by auto-chain from Step 15 (after Step 15 is completed or
|
||||
|
||||
Action: Read and execute `.cursor/skills/deploy/SKILL.md`.
|
||||
|
||||
After the deploy skill completes successfully, mark Step 16 as `completed` and auto-chain to Step 17 (Retrospective).
|
||||
After the deploy skill completes successfully, mark Step 16 as `completed` and auto-chain to Step 16.5 (Release).
|
||||
|
||||
---
|
||||
|
||||
**Step 16.5 — Release**
|
||||
State-driven: reached by auto-chain from Step 16.
|
||||
|
||||
Action: Read and execute `.cursor/skills/release/SKILL.md`. The release skill is responsible for selecting the target environment, executing the deploy artifacts, smoke-testing, watching the rollout, and producing a definitive verdict (`Released`, `Released-with-override`, `Rolled-Back`, or `Aborted`).
|
||||
|
||||
The release skill has its own internal BLOCKING gates (Phase 1 pre-release gate, Phase 2 strategy select, Phase 6 user confirmation when soft regression escalates). Autodev does NOT add a wrapping A/B/C gate — the release skill owns its own user interaction.
|
||||
|
||||
After the release skill exits:
|
||||
|
||||
- **Verdict `Released`** → mark Step 16.5 `completed` and auto-chain to Step 17 (Retrospective in cycle-end mode).
|
||||
- **Verdict `Released-with-override`** → mark Step 16.5 `completed` AND auto-chain to Step 17 (Retrospective in **incident mode**) — the override is itself an incident the retrospective must analyze.
|
||||
- **Verdict `Rolled-Back`** → mark Step 16.5 `failed`. Auto-chain to Step 17 (Retrospective in **incident mode**). Do NOT consider the project "Done" — the user owns the next move (re-run /implement on a fix branch, re-run /deploy, re-run /release).
|
||||
- **Verdict `Aborted`** → mark Step 16.5 `not_started` (the release was never started) OR `failed` if the abort came after Phase 3 had already touched the live system. Surface the abort reason and STOP — do not auto-chain to retrospective.
|
||||
|
||||
---
|
||||
|
||||
**Step 17 — Retrospective**
|
||||
State-driven: reached by auto-chain from Step 16.
|
||||
State-driven: reached by auto-chain from Step 16.5 with a `Released` or `Released-with-override` verdict, OR from a `Rolled-Back` verdict (in incident mode).
|
||||
|
||||
Action: Read and execute `.cursor/skills/retrospective/SKILL.md` in **cycle-end mode**. This closes the cycle's feedback loop by folding metrics into `_docs/06_metrics/retro_<date>.md` and appending the top-3 lessons to `_docs/LESSONS.md`.
|
||||
Action: Read and execute `.cursor/skills/retrospective/SKILL.md`. Mode selection:
|
||||
|
||||
- Step 16.5 verdict `Released` → cycle-end mode
|
||||
- Step 16.5 verdict `Released-with-override` or `Rolled-Back` → incident mode
|
||||
|
||||
The retrospective closes the cycle's feedback loop by folding metrics into `_docs/06_metrics/retro_<date>.md` (or `incident_<date>_release.md` in incident mode) and appending the top-3 lessons to `_docs/LESSONS.md`.
|
||||
|
||||
After retrospective completes, mark Step 17 as `completed` and enter "Done" evaluation.
|
||||
|
||||
---
|
||||
|
||||
**Done**
|
||||
State-driven: reached by auto-chain from Step 17. (Sanity check: `_docs/04_deploy/` should contain all expected artifacts — containerization.md, ci_cd_pipeline.md, environment_strategy.md, observability.md, deployment_procedures.md, deploy_scripts.md.)
|
||||
State-driven: reached by auto-chain from Step 17. (Sanity check: `_docs/04_deploy/` should contain all expected artifacts — containerization.md, ci_cd_pipeline.md, environment_strategy.md, observability.md, deployment_procedures.md, deploy_scripts.md. `_docs/04_release/` should contain at least one `release_<version>_<env>_<timestamp>.md` with a `Released` verdict — or the user has explicitly chosen to handle release outside autodev.)
|
||||
|
||||
Action: Report project completion with summary. Then **rewrite the state file** so the next `/autodev` invocation enters the feature-cycle loop in the existing-code flow:
|
||||
|
||||
@@ -337,7 +359,11 @@ On the next invocation, Flow Resolution rule 1 reads `flow: existing-code` and r
|
||||
| Update Docs (13, done or skipped) | Auto-chain → Security Audit choice (14) |
|
||||
| Security Audit (14, done or skipped) | Auto-chain → Performance Test choice (15) |
|
||||
| Performance Test (15, done or skipped) | Auto-chain → Deploy (16) |
|
||||
| Deploy (16) | Auto-chain → Retrospective (17) |
|
||||
| Deploy (16) | Auto-chain → Release (16.5) |
|
||||
| Release (16.5, verdict Released) | Auto-chain → Retrospective (17, cycle-end mode) |
|
||||
| Release (16.5, verdict Released-with-override) | Auto-chain → Retrospective (17, **incident mode**) |
|
||||
| Release (16.5, verdict Rolled-Back) | Auto-chain → Retrospective (17, **incident mode**); do NOT enter Done |
|
||||
| Release (16.5, verdict Aborted) | STOP — surface abort reason; do not auto-chain |
|
||||
| Retrospective (17) | Report completion; rewrite state to existing-code flow, step 9 |
|
||||
|
||||
## Status Summary — Step List
|
||||
@@ -362,6 +388,7 @@ Flow name: `greenfield`. Render using the banner template in `protocols.md` →
|
||||
| 14 | Security Audit | — |
|
||||
| 15 | Performance Test | — |
|
||||
| 16 | Deploy | — |
|
||||
| 16.5 | Release | `DONE (Released | Released-with-override | Rolled-Back | Aborted)` |
|
||||
| 17 | Retrospective | — |
|
||||
|
||||
All rows also accept the shared state tokens (`DONE`, `IN PROGRESS`, `NOT STARTED`, `FAILED (retry N/3)`); rows 4, 12, 13, 14, 15 additionally accept `SKIPPED`.
|
||||
@@ -385,5 +412,6 @@ Row rendering format (step-number column is right-padded to 2 characters for ali
|
||||
Step 14 Security Audit [<state token>]
|
||||
Step 15 Performance Test [<state token>]
|
||||
Step 16 Deploy [<state token>]
|
||||
Step 16.5 Release [<state token>]
|
||||
Step 17 Retrospective [<state token>]
|
||||
```
|
||||
|
||||
@@ -5,7 +5,8 @@ Workflow for **meta-repositories** — repos that aggregate multiple components
|
||||
This flow differs fundamentally from `greenfield` and `existing-code`:
|
||||
|
||||
- **No problem/research/plan phases** — meta-repos don't build features, they coordinate existing ones
|
||||
- **No test spec / implement / run tests** — the meta-repo has no code to test
|
||||
- **No test spec / run tests** — the meta-repo has no code to test
|
||||
- **`implement` is scoped to suite-level work only** — cross-repo concerns, repo/folder renames, suite-root infra additions (e.g., `.gitmodules`, `_infra/`, suite `e2e/`). Per-component implementation lives in each component's own workspace `/autodev` cycle. The meta-repo's implement step (Step 3.5) executes only when `_docs/tasks/todo/` is non-empty AND the user explicitly opts in; placement is **before** the sync skills so subsequent Doc/E2E/CICD sync propagates the post-implementation state.
|
||||
- **No `_docs/00_problem/` artifacts** — documentation target is `_docs/*.md` unified docs, not per-feature `_docs/NN_feature/` folders
|
||||
- **Primary artifact is `_docs/_repo-config.yaml`** — generated by `monorepo-discover`, read by every other step
|
||||
|
||||
@@ -17,6 +18,7 @@ This flow differs fundamentally from `greenfield` and `existing-code`:
|
||||
| 2 | Config Review | (human checkpoint, no sub-skill) | — |
|
||||
| 2.5 | Glossary & Architecture Vision | (inline, no sub-skill) | Steps 1–5 |
|
||||
| 3 | Status | monorepo-status/SKILL.md | Sections 1–5 |
|
||||
| 3.5 | Suite Implement | implement/SKILL.md (suite-level invocation context) | Steps 1–14 + 16 (Step 14.5 + Step 15 skipped); conditional on `_docs/tasks/todo/` non-empty AND user opt-in |
|
||||
| 4 | Document Sync | monorepo-document/SKILL.md | Phase 1–7 (conditional on doc drift) |
|
||||
| 4.5 | Integration Test Sync | monorepo-e2e/SKILL.md | Phase 1–6 (conditional on suite-e2e drift; skipped if `suite_e2e:` block absent in config) |
|
||||
| 5 | CICD Sync | monorepo-cicd/SKILL.md | Phase 1–7 (conditional on CI drift) |
|
||||
@@ -184,11 +186,16 @@ The status report identifies:
|
||||
- Registry/config mismatches
|
||||
- Unresolved questions
|
||||
|
||||
Based on the report, auto-chain branches:
|
||||
Based on the report, auto-chain branches in this evaluation order (first match wins):
|
||||
|
||||
- If **doc drift** found → auto-chain to **Step 4 (Document Sync)**
|
||||
- Else if **CI drift** (only) found → auto-chain to **Step 5 (CICD Sync)**
|
||||
- Else if **registry mismatch** found (new components not in config) → present Choose format:
|
||||
1. **Registry mismatch** (new components not in config, or config component not in registry) → present the Choose format below FIRST. After the user resolves it (A: refresh discover, B: onboard, C: continue with mismatch acknowledged), proceed to the next rule. This rule has priority because a stale config would mislead Step 3.5's ownership-envelope synthesis and any sync skill's component scope.
|
||||
2. **Pre-routing gate (Step 3.5 detection)** — check `_docs/tasks/todo/` for suite-level task files (`*.md` excluding files starting with `_`). If ≥1 task is present, auto-chain to **Step 3.5 (Suite Implement)**. After Step 3.5 returns (regardless of A/B outcome), the post-implement re-status applies rules 3–6 below to the post-implementation state.
|
||||
3. If **doc drift** found → auto-chain to **Step 4 (Document Sync)**
|
||||
4. Else if **CI drift** (only) found → auto-chain to **Step 5 (CICD Sync)**
|
||||
5. Else if **suite-e2e drift** (only) found → auto-chain to **Step 4.5 (Integration Test Sync)** (only when `suite_e2e:` block exists in config)
|
||||
6. Else → **workflow done for this cycle**.
|
||||
|
||||
**Registry mismatch Choose format** (rule 1):
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
@@ -205,7 +212,134 @@ Based on the report, auto-chain branches:
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
- Else → **workflow done for this cycle**. Report "No drift. Meta-repo is in sync." Loop waits for next invocation.
|
||||
When rule 6 fires (no drift, no todo tasks), report "No drift. Meta-repo is in sync." and end the cycle. Loop waits for next invocation.
|
||||
|
||||
---
|
||||
|
||||
**Step 3.5 — Suite Implement**
|
||||
|
||||
Condition (folder fallback): `_docs/tasks/todo/` exists AND contains ≥1 file matching `*.md` excluding files starting with `_` (e.g., `_dependencies_table.md` is excluded by convention).
|
||||
|
||||
State-driven: reached by auto-chain from Step 3 when the pre-routing gate detected todo tasks. Inserted **before** the sync skills (Step 4 / 4.5 / 5) by deliberate design: implementing renames + cross-repo edits first means the subsequent sync skills propagate the actual landed state rather than the pre-change state, avoiding a second cycle to fix downstream drift.
|
||||
|
||||
**Skip condition**: `_docs/tasks/todo/` is empty, missing, or contains only `_*` files. In that case Step 3.5 is skipped entirely and the cycle proceeds with Step 3's existing drift-based routing.
|
||||
|
||||
**Goal**: Execute suite-level implementation tasks — cross-repo concerns (e.g., `autopilot` + `ui` + suite `e2e/` cutover in a coordinated change-set), folder renames (e.g., `git mv flights missions` + `.gitmodules` edit + `_infra/` path refs), and suite-root infrastructure additions (e.g., `_infra/dev/docker-compose.dev.yml`). Per-component implementation work stays in each component's own workspace `/autodev` cycle.
|
||||
|
||||
**Why this exists**: the meta-repo's existing sync skills (`monorepo-document`, `monorepo-cicd`, `monorepo-e2e`) only **propagate** changes that already landed. They cannot **execute** a task spec. Without Step 3.5, suite-level tickets like AZ-543 (B4 repo rename) or AZ-506 (new dev compose) have no flow path forward — they require operator action outside autodev.
|
||||
|
||||
**Inputs**:
|
||||
|
||||
- `_docs/tasks/todo/*.md` (excluding `_*`) — task specs in the existing format (`Task` / `Component` / `Dependencies` / `Acceptance criteria` headers)
|
||||
- `_docs/_repo-config.yaml` — `components[].path` list, used to compute the suite-level OWNED envelope (workspace root EXCLUDING any path under a component's folder)
|
||||
- `_docs/tasks/_dependencies_table.md` — synthesized by this step if missing (see Procedure)
|
||||
- `_docs/tasks/_suite_module_layout.md` — synthesized by this step if missing (see Procedure)
|
||||
|
||||
**Procedure**:
|
||||
|
||||
1. **Detection (already done by Step 3 pre-routing gate)**. List task files in `_docs/tasks/todo/` (excluding `_*`). If 0 → skip Step 3.5. If ≥1 → continue.
|
||||
|
||||
2. **Present Choose**:
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
DECISION REQUIRED: <N> suite-level task(s) in _docs/tasks/todo/
|
||||
══════════════════════════════════════
|
||||
Task(s) detected:
|
||||
- AZ-XXX: <title> (deps: <list or "—">)
|
||||
- AZ-YYY: <title> (deps: <list or "—">)
|
||||
...
|
||||
|
||||
A) Run implement skill on these task(s) now (then continue to Doc / E2E / CICD sync)
|
||||
B) Skip implement this cycle — continue to Doc / E2E / CICD sync without executing tasks
|
||||
C) Pause — review the tasks before deciding (end session, no state changes)
|
||||
══════════════════════════════════════
|
||||
Recommendation: A — running implement BEFORE syncs means subsequent
|
||||
sync skills propagate the post-implementation state.
|
||||
B is appropriate when tasks are blocked on user input
|
||||
or external coordination. C when the tasks themselves
|
||||
need owner clarification before execution.
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
3. **On user A — Pre-flight**:
|
||||
|
||||
a. **Working tree clean check**. Run `git status --porcelain`. If non-empty, surface to the user with a Choose A/B/C identical to the implement skill's prerequisite gate (commit/stash manually; agent commits as `chore: WIP pre-implement`; abort).
|
||||
|
||||
b. **Synthesize `_docs/tasks/_dependencies_table.md`** if missing. Parse each in-scope task's `Dependencies:` field. Write a minimal table of the form:
|
||||
|
||||
```markdown
|
||||
# Suite-Level Task Dependencies
|
||||
|
||||
| Task ID | Depends on | Notes |
|
||||
|---------|------------|-------|
|
||||
| AZ-XXX | (none) | — |
|
||||
| AZ-YYY | AZ-XXX | — |
|
||||
```
|
||||
|
||||
If a task lists a dependency that is neither in `todo/` nor `done/`, log a warning in the synthesized file but do not block — implement skill's Step 1 (Parse) will surface the issue if it actually blocks execution.
|
||||
|
||||
c. **Synthesize `_docs/tasks/_suite_module_layout.md`** if missing. Default content:
|
||||
|
||||
```markdown
|
||||
# Suite-Level Module Layout (synthetic)
|
||||
|
||||
Generated by autodev meta-repo Step 3.5. The suite root has no per-feature decomposition; ownership is defined at the component-boundary level only.
|
||||
|
||||
## Per-Component Mapping
|
||||
|
||||
| Component | Owns | Imports from |
|
||||
|-----------|----------------------------------|--------------|
|
||||
| suite | (workspace root) excluding any path listed under `_repo-config.yaml.components[].path` | (read-only) every component's primary doc + `_docs/*.md` |
|
||||
|
||||
Suite-level tasks operate on: `.gitmodules`, `_infra/**`, `_docs/**` (excluding `_docs/tasks/_*` regenerated files), root `README.md`, `e2e/**` (suite e2e harness only).
|
||||
|
||||
Forbidden paths for suite-level tasks: `<component>/**` for every component listed in `_repo-config.yaml.components[].path` — those edits live in the component's own workspace `/autodev` cycle.
|
||||
```
|
||||
|
||||
d. **Prepare invocation context**:
|
||||
|
||||
```
|
||||
suite_level: true
|
||||
TASKS_DIR: _docs/tasks/
|
||||
module_layout_path: _docs/tasks/_suite_module_layout.md
|
||||
```
|
||||
|
||||
4. **Invoke implement skill**. Read and execute `.cursor/skills/implement/SKILL.md` with the prepared context. The skill's "Suite-level invocation context" subsection (added in tandem with this flow change) honors the three flags above and skips:
|
||||
|
||||
- Step 14.5 (cumulative code review) — no `architecture_compliance_baseline.md` exists at the suite level; cross-task drift is captured by the next `monorepo-status` cycle instead.
|
||||
- Step 15 (Product Implementation Completeness Gate) — the gate's inputs (`_docs/02_document/architecture.md`, `system-flows.md`, `components/*/description.md`) do not exist in the meta-repo artifact layout. Suite tasks are infrastructure / coordination work, not feature implementation.
|
||||
|
||||
All other implement skill steps (1–14, 16) execute unchanged. Tracker integration (Step 5: In Progress, Step 12: In Testing) runs normally.
|
||||
|
||||
5. **Post-implement re-status**. After the implement skill completes (last batch committed, all originally-todo tasks moved to `_docs/tasks/done/`), silently re-run Step 3's drift detection logic — do NOT re-render the full Status report; just re-evaluate the drift signals against the post-implementation tree. Then auto-chain per the post-implementation drift findings:
|
||||
|
||||
- Doc drift → Step 4 (Document Sync)
|
||||
- Suite-e2e drift only → Step 4.5
|
||||
- CI drift only → Step 5
|
||||
- No drift → cycle complete
|
||||
|
||||
Note: the post-implement re-status is exactly why Step 3.5 is placed before sync. A repo rename will typically introduce doc + CI drift; the next invocation of Step 4 / Step 5 catches it on the same cycle.
|
||||
|
||||
6. **On user B (skip)** → mark Step 3.5 `skipped` in state file. Apply Step 3's original drift-based routing (compute from the pre-Step-3.5 Status report).
|
||||
|
||||
7. **On user C (pause)** → end session. Update state to `step: 3.5, status: in_progress, sub_step: {phase: 0, name: awaiting-task-review, detail: "<N> tasks pending review"}`. Tell the user to invoke `/autodev` again after deciding. **Do NOT modify any files** — pre-flight has not run yet.
|
||||
|
||||
**Self-verification** (executed before invoking implement):
|
||||
|
||||
- [ ] Working tree is clean (or user explicitly chose B in the WIP-stash sub-Choose)
|
||||
- [ ] `_docs/tasks/_dependencies_table.md` exists (synthesized if it didn't)
|
||||
- [ ] `_docs/tasks/_suite_module_layout.md` exists (synthesized if it didn't)
|
||||
- [ ] All in-scope task files have a `Component:` field (skip + report any that don't — don't guess ownership)
|
||||
- [ ] Tracker availability gate satisfied per `protocols.md` (or `tracker: local` previously chosen)
|
||||
|
||||
**Failure handling**:
|
||||
|
||||
- If implement returns FAILED → standard Failure Handling (`protocols.md`): retry up to 3 times, then escalate.
|
||||
- If implement is interrupted mid-batch → next invocation re-detects via the implement skill's resumability protocol (read latest `_docs/03_implementation/suite_batch_*.md`). Step 3.5 itself is reentrant: on re-entry, if `todo/` still has tasks, it presents the Choose again with the remaining set.
|
||||
- **Half-applied state risk** (acknowledged): if implement is interrupted between commits, the working tree is clean at the last commit boundary but the in-flight batch is lost. The user is responsible for inspecting and re-invoking. This is intentional — automated rollback of suite-level renames + `.gitmodules` edits is more dangerous than a human-driven recovery.
|
||||
|
||||
**Idempotency**: if `_docs/tasks/todo/` becomes empty after this step (all tasks moved to `done/`), the next `/autodev` invocation skips Step 3.5 entirely and proceeds with normal Status → sync flow.
|
||||
|
||||
---
|
||||
|
||||
@@ -287,11 +421,16 @@ After onboarding completes, the config is updated. Auto-chain back to **Step 3 (
|
||||
| Config Review (2, user picked A, confirmed_by_user: true) | Auto-chain → Glossary & Architecture Vision (2.5) |
|
||||
| Config Review (2, user picked B) | **Session boundary** — end session, await re-invocation |
|
||||
| Glossary & Architecture Vision (2.5) | Auto-chain → Status (3) |
|
||||
| Status (3, doc drift) | Auto-chain → Document Sync (4) |
|
||||
| Status (3, suite-e2e drift only) | Auto-chain → Integration Test Sync (4.5) |
|
||||
| Status (3, CI drift only) | Auto-chain → CICD Sync (5) |
|
||||
| Status (3, no drift) | **Cycle complete** — end session, await re-invocation |
|
||||
| Status (3, todo tasks present) | Auto-chain → Suite Implement (3.5) — pre-routing gate fires before drift-based routing |
|
||||
| Status (3, no todo tasks, doc drift) | Auto-chain → Document Sync (4) |
|
||||
| Status (3, no todo tasks, suite-e2e drift only) | Auto-chain → Integration Test Sync (4.5) |
|
||||
| Status (3, no todo tasks, CI drift only) | Auto-chain → CICD Sync (5) |
|
||||
| Status (3, no todo tasks, no drift) | **Cycle complete** — end session, await re-invocation |
|
||||
| Status (3, registry mismatch) | Ask user (A: discover, B: onboard, C: continue) |
|
||||
| Suite Implement (3.5, user picked A, success) | Silent re-status; auto-chain per post-implementation drift (Step 4 / 4.5 / 5 / cycle complete) |
|
||||
| Suite Implement (3.5, user picked B) | Mark `skipped`; auto-chain per Step 3's original drift findings |
|
||||
| Suite Implement (3.5, user picked C) | **Session boundary** — end session, await re-invocation |
|
||||
| Suite Implement (3.5, FAILED ×3) | Standard Failure Handling escalation (`protocols.md`) |
|
||||
| Document Sync (4) + suite-e2e drift pending | Auto-chain → Integration Test Sync (4.5) |
|
||||
| Document Sync (4) + CI drift only pending | Auto-chain → CICD Sync (5) |
|
||||
| Document Sync (4) + no further drift | **Cycle complete** |
|
||||
@@ -317,11 +456,12 @@ Flow-specific slot values:
|
||||
| 2 | Config Review | `IN PROGRESS (awaiting human)` |
|
||||
| 2.5 | Glossary & Architecture Vision | `SKIPPED (already captured)` |
|
||||
| 3 | Status | `DONE (no drift)`, `DONE (N drifts)` |
|
||||
| 3.5 | Suite Implement | `DONE (N tasks)`, `SKIPPED (no todo tasks)`, `SKIPPED (user picked B)`, `IN PROGRESS (batch M of ~N)`, `IN PROGRESS (awaiting-task-review)` |
|
||||
| 4 | Document Sync | `DONE (N docs)`, `SKIPPED (no doc drift)` |
|
||||
| 4.5 | Integration Test Sync | `DONE (N files)`, `SKIPPED (no suite-e2e drift)`, `SKIPPED (no suite_e2e config block)` |
|
||||
| 5 | CICD Sync | `DONE (N files)`, `SKIPPED (no CI drift)` |
|
||||
|
||||
All rows accept the shared state tokens (`DONE`, `IN PROGRESS`, `NOT STARTED`, `FAILED (retry N/3)`); rows 2.5, 4, 4.5, and 5 additionally accept `SKIPPED`.
|
||||
All rows accept the shared state tokens (`DONE`, `IN PROGRESS`, `NOT STARTED`, `FAILED (retry N/3)`); rows 2.5, 3.5, 4, 4.5, and 5 additionally accept `SKIPPED`.
|
||||
|
||||
Row rendering format:
|
||||
|
||||
@@ -330,6 +470,7 @@ Row rendering format:
|
||||
Step 2 Config Review [<state token>]
|
||||
Step 2.5 Glossary & Architecture Vision [<state token>]
|
||||
Step 3 Status [<state token>]
|
||||
Step 3.5 Suite Implement [<state token>]
|
||||
Step 4 Document Sync [<state token>]
|
||||
Step 4.5 Integration Test Sync [<state token>]
|
||||
Step 5 CICD Sync [<state token>]
|
||||
@@ -337,8 +478,12 @@ Row rendering format:
|
||||
|
||||
## Notes for the meta-repo flow
|
||||
|
||||
- **No session boundary except Step 2 and Step 2.5**: unlike existing-code flow (which has boundaries around decompose), meta-repo flow only pauses at config review and the one-shot glossary/vision capture. Once both are confirmed, syncing is fast enough to complete in one session and Step 2.5 idempotently no-ops on every subsequent invocation.
|
||||
- **Session boundaries**: Step 2 (Config Review pending), Step 2.5 (one-shot glossary/vision review), and Step 3.5 (when user picks C "Pause"). Step 3.5's A/B picks do NOT cross a session boundary — they auto-chain to syncs in the same session.
|
||||
- **Cyclical, not terminal**: no "done forever" state. Each invocation completes a drift cycle; next invocation starts fresh.
|
||||
- **No tracker integration**: this flow does NOT create Jira/ADO tickets. Maintenance is not a feature — if a feature-level ticket spans the meta-repo's concerns, it lives in the per-component workspace.
|
||||
- **Tracker integration scope**: this flow does NOT create Jira/ADO tickets in its sync skills (Status / Document Sync / E2E / CICD). Step 3.5 (Suite Implement) IS tracker-integrated — it transitions existing tickets In Progress → In Testing per the implement skill's standard tracker handling. Suite-level tickets are authored manually by the operator (typically as children of an Epic that spans multiple components, like AZ-539); the flow doesn't auto-create them.
|
||||
- **Per-component vs. suite-level work**:
|
||||
- Tickets that touch component source code (`<component>/src/**`) belong in that component's own workspace `/autodev` cycle. The meta-repo flow does NOT execute them.
|
||||
- Tickets that touch suite-root paths only (`.gitmodules`, `_infra/**`, suite `e2e/**`, root `README.md`, suite `_docs/**` outside `tasks/_*`) are eligible for Step 3.5.
|
||||
- Tickets that span both (e.g., AZ-550 B11 consumer cutover, which touches `autopilot/`, `ui/`, AND suite `e2e/`) are NOT executable from a single workspace by design — split the ticket so the suite-level slice can run in Step 3.5 and the component slices run in their owning workspaces.
|
||||
- **Onboarding is opt-in**: never auto-onboarded. User must explicitly request.
|
||||
- **Failure handling**: uses the same retry/escalation protocol as other flows (see `protocols.md`).
|
||||
|
||||
@@ -114,6 +114,7 @@ Before entering a step from this table for the first time in a session, verify t
|
||||
| greenfield | Decompose Tests | Step 1t + Step 3 — All test tasks | Create ticket per task, link to epic |
|
||||
| existing-code | Decompose Tests | Step 1t + Step 3 — All test tasks | Create ticket per task, link to epic |
|
||||
| existing-code | New Task | Step 7 — Ticket | Create ticket per task, link to epic |
|
||||
| meta-repo | Suite Implement | Step 3.5 — implement skill Step 5 / Step 12 | Transition existing tickets In Progress → In Testing per implement skill (does NOT create new tickets — operator authors them) |
|
||||
|
||||
### State File Marker
|
||||
|
||||
@@ -388,7 +389,7 @@ The banner shell is defined here once. Each flow file contributes only its step-
|
||||
where `<state token>` comes from the state-token set defined per row in the flow's step-list table.
|
||||
- `<current-suffix>` — optional, flow-specific. The existing-code flow appends ` (cycle <N>)` when `state.cycle > 1`; other flows leave it empty.
|
||||
- `Retry:` row — omit entirely when `retry_count` is 0. Include it with `<N>/3` otherwise.
|
||||
- `<footer-extras>` — optional, flow-specific. The meta-repo flow adds a `Config:` line with `_docs/_repo-config.yaml` state; other flows leave it empty.
|
||||
- `<footer-extras>` — optional, flow-specific. The meta-repo flow adds a `Config:` line with `_docs/_repo-config.yaml` state; other flows leave it empty unless **parent suite docs** apply: if `<workspace-root>/../docs` exists and is a directory, append `Suite docs (parent): <absolute path>` on its own line (or `Suite docs (parent): absent` is **not** required — omit when missing). This line is orthogonal to flow-specific footer lines; both may appear.
|
||||
|
||||
### State token set (shared)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ The autodev persists its position to `_docs/_autodev_state.md`. This is a lightw
|
||||
|
||||
## Current Step
|
||||
flow: [greenfield | existing-code | meta-repo]
|
||||
step: [1-17 for greenfield, 1-17 for existing-code, 1-6 for meta-repo, or "done"]
|
||||
step: [1-17 for greenfield (incl. fractional 16.5), 1-17 for existing-code (incl. fractional 16.5), 1-6 for meta-repo (incl. fractional 2.5 and 3.5), or "done"]
|
||||
name: [step name from the active flow's Step Reference Table]
|
||||
status: [not_started / in_progress / completed / skipped / failed]
|
||||
sub_step:
|
||||
@@ -82,6 +82,19 @@ retry_count: 0
|
||||
cycle: 1
|
||||
```
|
||||
|
||||
```
|
||||
flow: meta-repo
|
||||
step: 3.5
|
||||
name: Suite Implement
|
||||
status: in_progress
|
||||
sub_step:
|
||||
phase: 7
|
||||
name: batch-loop
|
||||
detail: "AZ-543 batch 1 of 1; suite-level"
|
||||
retry_count: 0
|
||||
cycle: 1
|
||||
```
|
||||
|
||||
```
|
||||
flow: existing-code
|
||||
step: 10
|
||||
@@ -100,7 +113,7 @@ cycle: 3
|
||||
1. **Create** on the first autodev invocation (after state detection determines Step 1)
|
||||
2. **Update** after every change — this includes: batch completion, sub-step progress, step completion, session boundary, failed retry, or any meaningful state transition. The state file must always reflect the current reality.
|
||||
3. **Read** as the first action on every invocation — before folder scanning
|
||||
4. **Cross-check**: verify against actual `_docs/` folder contents. If they disagree, trust the folder structure and update the state file
|
||||
4. **Cross-check**: verify against actual `_docs/` folder contents. If they disagree, trust the folder structure and update the state file. **Parent suite `docs/`**: on every invocation, also probe `<workspace-root>/../docs` (the parent directory’s `docs` folder — typical suite-level shared documentation next to a component repo). If it exists, mention it in the Status Summary footer per `protocols.md`; use it only as supplemental reading context unless a flow step explicitly ties detection to it. It never replaces workspace `_docs/` for step detection by default.
|
||||
5. **Never delete** the state file
|
||||
6. **Retry tracking**: increment `retry_count` on each failed auto-retry; reset to `0` on success. If `retry_count` reaches 3, set `status: failed`
|
||||
7. **Failed state on re-entry**: if `status: failed` with `retry_count: 3`, do NOT auto-retry — present the issue to the user first
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name: code-review
|
||||
description: |
|
||||
Multi-phase code review against task specs with structured findings output.
|
||||
6-phase workflow: context loading, spec compliance, code quality, security quick-scan, performance scan, cross-task consistency.
|
||||
7-phase workflow: context loading, spec compliance, code quality, security quick-scan, performance scan, cross-task consistency, architecture compliance.
|
||||
Produces a structured report with severity-ranked findings and a PASS/FAIL/PASS_WITH_WARNINGS verdict.
|
||||
Invoked by /implement skill after each batch, or manually.
|
||||
Trigger phrases:
|
||||
@@ -106,11 +106,12 @@ When multiple tasks were implemented in the same batch:
|
||||
|
||||
## Phase 7: Architecture Compliance
|
||||
|
||||
Verify the implemented code respects the architecture documented in `_docs/02_document/architecture.md` and the component boundaries declared in `_docs/02_document/module-layout.md`.
|
||||
Verify the implemented code respects the architecture documented in `_docs/02_document/architecture.md`, the component boundaries declared in `_docs/02_document/module-layout.md`, and the **accepted Architectural Decision Records** under `_docs/02_document/adr/`.
|
||||
|
||||
**Inputs**:
|
||||
- `_docs/02_document/architecture.md` — layering, allowed dependencies, patterns
|
||||
- `_docs/02_document/module-layout.md` — per-component directories, Public API surface, `Imports from` lists, Allowed Dependencies table
|
||||
- `_docs/02_document/adr/` — every `Status: Accepted` ADR is an enforceable structural rule. `Status: Proposed`, `Status: Deprecated`, and `Status: Superseded` ADRs are NOT enforced (Proposed = not yet ratified; Deprecated/Superseded = a later ADR overturned it). If the directory does not exist or has only the index file, ADRs are skipped — log this skip in the report so the absence is visible.
|
||||
- The cumulative list of changed files (for per-batch invocation) or the full codebase (for baseline invocation)
|
||||
|
||||
**Checks**:
|
||||
@@ -125,6 +126,11 @@ Verify the implemented code respects the architecture documented in `_docs/02_do
|
||||
|
||||
5. **Cross-cutting concerns not locally re-implemented**: if a file under a component directory contains logic that should live in `shared/<concern>/` (e.g., custom logging setup, config loader, error envelope), flag it. Severity: Medium. Category: Architecture.
|
||||
|
||||
6. **ADR compliance**: for each `Status: Accepted` ADR, confirm the changed code does not contradict the ADR's `Decision`. Two failure modes are flagged:
|
||||
- **ADR-Violation**: the changed code does the opposite of an Accepted ADR's `Decision`. Example: ADR-002 says "We will use Postgres for transactional data" and the changed code introduces a SQLite dependency for a transactional path. Severity: **Critical**. Category: Architecture. The finding cites the ADR by `NNN_<slug>` and the offending file/line.
|
||||
- **ADR-Drift**: the changed code does something the ADR did not anticipate AND that materially affects the ADR's `Consequences` (positive or negative). Example: ADR-004 says "Event-driven cross-component comms" and a changed file introduces a new synchronous HTTP call between two components. Severity: **High**. Category: Architecture. The finding either proposes "Update ADR-NNN to acknowledge the new pattern" or "Remove the drift to align with ADR-NNN" — never silently accepts.
|
||||
The check skips ADRs that are explicitly out of scope of the changed batch (e.g., ADR-001 about deployment pipeline when the batch only touches business-logic files). Use the ADR's `Evidence` section to determine scope: if no Evidence path overlaps with any changed file, skip the ADR for this batch.
|
||||
|
||||
**Detection approach (per language)**:
|
||||
|
||||
- Python: parse `import` / `from ... import` statements; optionally AST with `ast` module for reliable symbol resolution.
|
||||
@@ -197,7 +203,7 @@ Produce a structured report with findings deduplicated and sorted by severity:
|
||||
|
||||
Bug, Spec-Gap, Security, Performance, Maintainability, Style, Scope, Architecture
|
||||
|
||||
`Architecture` findings come from Phase 7. They indicate layering violations, Public API bypasses, new cyclic dependencies, duplicate symbols, or cross-cutting concerns re-implemented locally.
|
||||
`Architecture` findings come from Phase 7. They indicate layering violations, Public API bypasses, new cyclic dependencies, duplicate symbols, cross-cutting concerns re-implemented locally, **ADR-Violation** (changed code contradicts an `Accepted` ADR's Decision — Critical), or **ADR-Drift** (changed code introduces a pattern that materially affects an `Accepted` ADR's Consequences without superseding it — High).
|
||||
|
||||
## Verdict Logic
|
||||
|
||||
@@ -232,7 +238,7 @@ The implement skill invokes code-review by:
|
||||
|
||||
1. Reading `.cursor/skills/code-review/SKILL.md`
|
||||
2. Providing the inputs above as context (read the files, pass content to the review phases)
|
||||
3. Executing all 6 phases sequentially
|
||||
3. Executing all 7 phases sequentially
|
||||
4. Consuming the verdict from the output
|
||||
|
||||
### Outputs (returned to the implement skill)
|
||||
|
||||
@@ -65,6 +65,7 @@ Announce the selected entrypoint and resolved paths to the user before proceedin
|
||||
| 1 Bootstrap Structure | `steps/01_bootstrap-structure.md` | ✓ | — | — |
|
||||
| 1t Test Infrastructure | `steps/01t_test-infrastructure.md` | — | — | ✓ |
|
||||
| 1.5 Module Layout | `steps/01-5_module-layout.md` | ✓ | — | — |
|
||||
| 1.7 System-Pipeline Tasks | `steps/01-7_system-pipeline-tasks.md` | ✓ | — | — |
|
||||
| 2 Task Decomposition | `steps/02_task-decomposition.md` | ✓ | ✓ | — |
|
||||
| 3 Blackbox Test Tasks | `steps/03_blackbox-test-decomposition.md` | — | — | ✓ |
|
||||
| 4 Cross-Verification | `steps/04_cross-verification.md` | ✓ | — | ✓ |
|
||||
@@ -191,6 +192,20 @@ Read and follow `steps/01-5_module-layout.md`.
|
||||
|
||||
---
|
||||
|
||||
### Step 1.7: System-Pipeline Tasks (implementation mode only)
|
||||
|
||||
Read and follow `steps/01-7_system-pipeline-tasks.md`.
|
||||
|
||||
This step exists because per-component task decomposition (Step 2)
|
||||
produces one task per component but NEVER produces a task whose
|
||||
deliverable is "the production code that drives the end-to-end
|
||||
pipeline by calling each component in order against real inputs".
|
||||
The architecture document describes the loop; nobody owns it. The
|
||||
GPS-passthrough incident (May 2026) is the canonical failure this
|
||||
step prevents.
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Task Decomposition (implementation and single component modes)
|
||||
|
||||
Read and follow `steps/02_task-decomposition.md`.
|
||||
@@ -243,6 +258,8 @@ Read and follow `steps/04_cross-verification.md`.
|
||||
│ [BLOCKING: user confirms structure] │
|
||||
│ 1.5 Module Layout → steps/01-5_module-layout.md │
|
||||
│ [BLOCKING: user confirms layout] │
|
||||
│ 1.7 System-Pipeline → steps/01-7_system-pipeline-tasks.md │
|
||||
│ [BLOCKING: user confirms pipeline owners] │
|
||||
│ 2. Component Tasks → steps/02_task-decomposition.md │
|
||||
│ 4. Cross-Verification → steps/04_cross-verification.md │
|
||||
│ [BLOCKING: user confirms dependencies] │
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
3. Each component owns ONE top-level directory. Shared code goes under `<root>/shared/` (or language equivalent).
|
||||
4. Public API surface = files in the layout's `public:` list for each component; everything else is internal and MUST NOT be imported from other components.
|
||||
5. Cross-cutting concerns (logging, error handling, config, telemetry, auth middleware, feature flags, i18n) each get ONE entry under Shared / Cross-Cutting; per-component tasks consume them (see Step 2 cross-cutting rule).
|
||||
6. Write `_docs/02_document/module-layout.md` using `templates/module-layout.md` format.
|
||||
6. **ADR cross-check**: if `_docs/02_document/adr/` exists, read every `Status: Accepted` ADR. For each, confirm the proposed module layout does not contradict the ADR's `Decision` (e.g., an ADR mandating an event-bus boundary between two components must show up as a `Imports from` exclusion in the layout; an ADR locking a layering style must show up in the Layering table). If an ADR conflicts with the language-conventional layout from step 2, the ADR wins — record the conflict in a `## ADR-driven exceptions to the conventional layout` section of `module-layout.md` with `See ADR NNN_<slug>` references. If the ADR conflict is irreconcilable (the ADR demands something the language genuinely cannot express), STOP and ask the user A/B/C: (A) update the ADR via plan Step 4.5 supersede flow, (B) accept a layered exception with documented rationale, (C) re-open architecture.
|
||||
7. Write `_docs/02_document/module-layout.md` using `templates/module-layout.md` format. Each Per-Component Mapping entry that is governed by an ADR includes a trailing `> See ADR NNN_<slug>` line.
|
||||
|
||||
## Self-verification
|
||||
|
||||
@@ -26,6 +27,8 @@
|
||||
- [ ] No component's `Imports from` list points at a higher layer
|
||||
- [ ] Paths follow the detected language's convention
|
||||
- [ ] No two components own overlapping paths
|
||||
- [ ] If `_docs/02_document/adr/` exists with Accepted ADRs, every layout decision that an ADR governs has a trailing `> See ADR NNN_<slug>` reference
|
||||
- [ ] No Accepted ADR is contradicted by the layout without a documented exception
|
||||
|
||||
## Save action
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Step 1.7: System-Pipeline Tasks (implementation mode only)
|
||||
|
||||
**Role**: Professional software architect, integration-focused.
|
||||
**Goal**: For every end-to-end pipeline named in `_docs/02_document/architecture.md` and `_docs/02_document/system-flows.md`, ensure there is exactly ONE explicit task that owns the production code that drives that pipeline against real inputs. This step prevents the failure mode where every individual component is "complete" but no production code wires them together (May 2026 GPS-passthrough incident — see `meta-rule.mdc` "When a test reveals missing production code").
|
||||
|
||||
**Constraints**:
|
||||
|
||||
- This step produces *integration* tasks, not per-component tasks. Per-component tasks come from Step 2.
|
||||
- An integration task's owner is typically the composition root, runtime root, main loop, or whichever component the module layout (Step 1.5) names as the "system spine". It is NEVER a leaf component.
|
||||
- Each integration task must be sized at 5 points or fewer. If the pipeline is too large for one task, split it into per-stage integration tasks (e.g. "wire ingress → C1", then "wire C1 → C5") rather than one giant task.
|
||||
|
||||
## Inputs
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `_docs/02_document/architecture.md` | Source of named end-to-end pipelines and their component sequences |
|
||||
| `_docs/02_document/system-flows.md` | Source of operational flows (per-frame loop, request lifecycle, batch job, etc.) |
|
||||
| `_docs/02_document/module-layout.md` | Produced by Step 1.5. Names the "system spine" component(s) — typically `runtime_root`, `app`, `main`, `composition`, or equivalent. |
|
||||
| `_docs/02_document/components/*/description.md` | Per-component contracts so you can tell which side of a seam each method lives on |
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Enumerate end-to-end pipelines.** Read `architecture.md` and `system-flows.md`. For each named pipeline / flow that spans 2+ components, record:
|
||||
- The pipeline name (e.g. "per-frame nav loop", "tile-cache build", "operator pre-flight verification").
|
||||
- The ordered sequence of components it touches (e.g. `frame_source → c1_vio → c2_vpr → ... → c5_state → replay_sink`).
|
||||
- The trigger (per-frame, per-request, scheduled, manual).
|
||||
- The output (what the pipeline emits and to whom).
|
||||
2. **For each pipeline, locate the owner.** Use `module-layout.md` to find the component that owns the orchestration (the "spine"). If `module-layout.md` does not name one, STOP and ASK the user which component owns the pipeline. Do NOT silently default to the bootstrap structure task — bootstrap is about project skeleton, not behavior.
|
||||
3. **Check whether the pipeline is already covered by an existing task spec or by the bootstrap-structure task.** A pipeline is "covered" only if:
|
||||
- A task spec's `Outcome` or `Acceptance Criteria` section explicitly names "drives the {pipeline_name} end-to-end against real production components", AND
|
||||
- That task's owned files include the orchestration code (typically the spine component's main loop / entrypoint).
|
||||
4. **For every uncovered pipeline, create a system-integration task spec** in `_docs/02_tasks/todo/` using `.cursor/skills/decompose/templates/task.md`:
|
||||
- **Component**: the spine component from step 2 (e.g. `runtime_root`).
|
||||
- **Outcome**: the production callsite that drives the pipeline exists and runs end-to-end on real inputs.
|
||||
- **Scope / Included**: the orchestration code (loop body, dispatcher, scheduler, entrypoint); explicit list of every component it must call in order; the data type at each seam.
|
||||
- **Acceptance Criteria** (write each as testable):
|
||||
- At least one production caller of every component method in the pipeline can be found by grep — name the methods explicitly.
|
||||
- The orchestration runs against the real production component instances (NOT mocks, NOT a passthrough that bypasses them).
|
||||
- At least one integration test exercises the orchestration end-to-end against real inputs.
|
||||
- **Dependencies**: every per-component task whose component appears in the pipeline.
|
||||
- **Complexity points**: ≤5; split the pipeline if it doesn't fit.
|
||||
- **Tracker**: create a ticket immediately (per `decompose/SKILL.md` "Tracker inline" principle); rename the file to `[TRACKER-ID]_pipeline_<name>.md`.
|
||||
5. **Mark the integration task as `Dependencies` for the integration test task.** If `tests-only` decomposition has already produced an e2e/integration test task for this pipeline, append the new integration task to its `Dependencies` field so the test cannot be "made green" before the integration ships.
|
||||
|
||||
## Anti-patterns this step explicitly blocks
|
||||
|
||||
- **"compose_root returns a wired runtime"** prose interpreted as "the loop exists". Composition assembles the graph; it is NOT the loop. The loop is the code that pulls inputs, drives each node, and emits outputs. If grep finds zero callers of the leaf components, the loop does not exist regardless of what compose_root does.
|
||||
- **Treating the bootstrap-structure task as the home of the main loop.** Bootstrap is project skeleton (package layout, CLI scaffold, build files). It is NOT the main loop. Main loop is its own task.
|
||||
- **Per-component tasks claiming integration scope.** A C1 VIO task's deliverable is "C1 works in isolation against unit tests". A C1 task's acceptance criteria MUST NOT include "C1 is wired into the runtime" — that's the integration task's job.
|
||||
|
||||
## Self-verification
|
||||
|
||||
- [ ] Every pipeline named in `architecture.md` / `system-flows.md` is listed in your enumeration.
|
||||
- [ ] Every enumerated pipeline either (a) has an existing covered task, or (b) has a new integration task in `todo/`.
|
||||
- [ ] No integration task exceeds 5 complexity points.
|
||||
- [ ] Every integration task names every component in the pipeline as a `Dependencies` entry.
|
||||
- [ ] No integration task is owned by a leaf component — every owner is named in `module-layout.md` as a spine / orchestrator.
|
||||
- [ ] Every integration task has a tracker ticket created and the filename renamed to `[TRACKER-ID]_pipeline_<name>.md`.
|
||||
|
||||
## Save action
|
||||
|
||||
Write the new integration task files into `_docs/02_tasks/todo/`. They will be picked up by Step 2 (Task Decomposition's dependency-table writer) and by Step 4 (Cross-Verification).
|
||||
|
||||
## Blocking
|
||||
|
||||
**BLOCKING**: Present the pipeline enumeration + the list of new integration tasks to the user. Do NOT proceed to Step 2 until the user confirms:
|
||||
|
||||
- The enumeration matches what they expect from the architecture documents.
|
||||
- Every uncovered pipeline now has an integration task.
|
||||
- The chosen spine owners are correct.
|
||||
|
||||
If the user identifies a pipeline you missed, add it before proceeding. If the user names a different spine owner, update the task and re-run self-verification.
|
||||
@@ -43,6 +43,21 @@ For each component (or the single provided component):
|
||||
Consumers read the contract file, not the producer's task spec. This prevents interface drift when the producer's implementation detail leaks into consumers.
|
||||
11. **Immediately after writing each task file**: create a work item ticket, link it to the component's epic, write the work item ticket ID and Epic ID back into the task header, then rename the file from `todo/[##]_[short_name].md` to `todo/[TRACKER-ID]_[short_name].md`.
|
||||
|
||||
## Runtime Completeness Decomposition Gate
|
||||
|
||||
Before Step 2 is considered complete, scan `architecture.md`, `system-flows.md`, component descriptions, and the solution for named internal runtime capabilities and dependencies. Examples include BASALT/OpenVINS/Kimera, FAISS, DINOv2, ONNX/TensorRT, ALIKED/DISK, LightGlue, RANSAC, PostGIS, MAVLink emission, FDR rollover, and any "A-Z" user-visible pipeline.
|
||||
|
||||
For every named internal capability:
|
||||
|
||||
1. Ensure at least one implementation task explicitly owns the production integration or production algorithm.
|
||||
2. Do not treat "define protocol", "create adapter boundary", "add deterministic fallback", "create scaffold", or "prepare native bridge" as implementation of the capability unless the architecture explicitly says the real capability is out of scope.
|
||||
3. If a capability needs external hardware/data to verify, still create the production implementation task. Verification may be hardware-gated later; implementation must not be omitted.
|
||||
4. Add a `## Runtime Completeness` section to any affected task with:
|
||||
- named capability/dependency,
|
||||
- production code that must exist,
|
||||
- allowed external stubs, if any,
|
||||
- unacceptable substitutes such as fake/deterministic/internal stubs.
|
||||
|
||||
## Self-verification (per component)
|
||||
|
||||
- [ ] Every task is atomic (single concern)
|
||||
@@ -53,6 +68,7 @@ For each component (or the single provided component):
|
||||
- [ ] Every task has a work item ticket linked to the correct epic
|
||||
- [ ] Every shared-models / shared-API task has a contract file at `_docs/02_document/contracts/<component>/<name>.md` and a `## Contract` section linking to it
|
||||
- [ ] Every cross-cutting concern appears exactly once as a shared task, not N per-component copies
|
||||
- [ ] Every named internal runtime capability has a production implementation task, not only an interface/scaffold/fallback task
|
||||
|
||||
## Save action
|
||||
|
||||
|
||||
@@ -13,12 +13,17 @@
|
||||
1. Read all test specs from `DOCUMENT_DIR/tests/` (`blackbox-tests.md`, `performance-tests.md`, `resilience-tests.md`, `security-tests.md`, `resource-limit-tests.md`)
|
||||
2. Group related test scenarios into atomic tasks (e.g., one task per test category or per component under test)
|
||||
3. Each task should reference the specific test scenarios it implements and the environment/test-data specs
|
||||
4. Dependencies:
|
||||
4. Add a **System Under Test Boundary** section to every e2e/blackbox test task:
|
||||
- The test must drive the product through public runtime boundaries and compare actual outputs to `_docs/00_problem/input_data/expected_results/results_report.md` and any referenced machine-readable expected-result files.
|
||||
- Stubs are allowed only for external systems outside the product boundary: flight controller/SITL, QGC observer, satellite-provider/Suite service, physical Jetson hardware, physical camera, licensed public datasets, and network services.
|
||||
- Stubs, fakes, deterministic fallbacks, monkeypatches, or direct imports are not allowed for internal product modules that the scenario is meant to validate, such as VIO, safety/anchor wrapper, satellite retrieval, anchor verification, tile manager, MAVLink output adapter, or FDR.
|
||||
- If an internal module is not implemented, the test must fail/block as missing product implementation; it must not pass by replacing that module with a test stub.
|
||||
5. Dependencies:
|
||||
- In tests-only mode: blackbox test tasks depend on the test infrastructure bootstrap task (Step 1t)
|
||||
5. Write each task spec using `templates/task.md`
|
||||
6. Estimate complexity per task (1, 2, 3, 5 points); no task should exceed 5 points — split if it does
|
||||
7. Note task dependencies (referencing tracker IDs of already-created dependency tasks)
|
||||
8. **Immediately after writing each task file**: create a work item ticket under the "Blackbox Tests" epic, write the work item ticket ID and Epic ID back into the task header, then rename the file from `todo/[##]_[short_name].md` to `todo/[TRACKER-ID]_[short_name].md`.
|
||||
6. Write each task spec using `templates/task.md`
|
||||
7. Estimate complexity per task (1, 2, 3, 5 points); no task should exceed 5 points — split if it does
|
||||
8. Note task dependencies (referencing tracker IDs of already-created dependency tasks)
|
||||
9. **Immediately after writing each task file**: create a work item ticket under the "Blackbox Tests" epic, write the work item ticket ID and Epic ID back into the task header, then rename the file from `todo/[##]_[short_name].md` to `todo/[TRACKER-ID]_[short_name].md`.
|
||||
|
||||
## Self-verification
|
||||
|
||||
@@ -27,6 +32,7 @@
|
||||
- [ ] No task exceeds 5 complexity points
|
||||
- [ ] Dependencies correctly reference the test infrastructure task
|
||||
- [ ] Every task has a work item ticket linked to the "Blackbox Tests" epic
|
||||
- [ ] Every e2e/blackbox task forbids internal product stubs/fakes and requires comparison against expected-results artifacts
|
||||
|
||||
## Save action
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
2. Check no gaps:
|
||||
- In implementation mode: every product interface in `architecture.md` has implementation task coverage
|
||||
- In tests-only mode: every test scenario in `traceability-matrix.md` is covered by a task
|
||||
- In implementation mode: every named internal runtime capability/dependency from architecture, solution, system flows, and component descriptions has a production implementation task, not only an interface/scaffold/fallback task
|
||||
- In tests-only mode: every e2e/blackbox task has a System Under Test Boundary section that forbids stubbing internal product modules and requires comparison to expected-results artifacts
|
||||
3. Check no overlaps: tasks don't duplicate work
|
||||
4. Check no circular dependencies in the task graph
|
||||
5. Produce `_dependencies_table.md` using `templates/dependencies-table.md`
|
||||
@@ -19,6 +21,7 @@
|
||||
### Implementation mode
|
||||
|
||||
- [ ] Every product interface in `architecture.md` is covered by at least one implementation task
|
||||
- [ ] Every named internal runtime capability has a production implementation task
|
||||
- [ ] No circular dependencies in the task graph
|
||||
- [ ] Cross-component dependencies are explicitly noted in affected task specs
|
||||
- [ ] `_dependencies_table.md` contains every task with correct dependencies
|
||||
@@ -26,6 +29,7 @@
|
||||
### Tests-only mode
|
||||
|
||||
- [ ] Every test scenario from `traceability-matrix.md` "Covered" entries has a corresponding task
|
||||
- [ ] Every e2e/blackbox task validates actual product behavior and allows stubs only for external systems
|
||||
- [ ] No circular dependencies in the task graph
|
||||
- [ ] Test task dependencies reference the test infrastructure bootstrap
|
||||
- [ ] `_dependencies_table.md` contains every task with correct dependencies
|
||||
|
||||
@@ -29,7 +29,7 @@ Save as `_docs/04_deploy/ci_cd_pipeline.md`.
|
||||
### Test
|
||||
- Unit tests: [framework and command]
|
||||
- Blackbox tests: [framework and command, uses docker-compose.test.yml]
|
||||
- Coverage threshold: 75% overall, 90% critical paths
|
||||
- Coverage threshold: 75% overall, 90% critical-path floor (100% aim) — per `.cursor/rules/cursor-meta.mdc` Quality Thresholds
|
||||
- Coverage report published as pipeline artifact
|
||||
|
||||
### Security
|
||||
|
||||
@@ -25,7 +25,8 @@ For each task the main agent receives a task spec, analyzes the codebase, implem
|
||||
- **Dependency-aware ordering**: tasks run only when all their dependencies are satisfied
|
||||
- **Batching for review, not parallelism**: tasks are grouped into batches so `/code-review` and commits operate on a coherent unit of work — all tasks inside a batch are still implemented one after the other
|
||||
- **Integrated review**: `/code-review` skill runs automatically after each batch
|
||||
- **Completeness before testing**: product implementation is not done until code is checked against task outcomes, included scope, architecture/component promises, and unresolved scaffold/native placeholders — not just task AC tests
|
||||
- **Completeness before testing**: product implementation is not done until code is checked against task outcomes, included scope, architecture/component promises, named runtime dependencies, and unresolved scaffold/native placeholders — not just task AC tests
|
||||
- **Runtime dependency reality**: production code cannot satisfy a task by exposing only a protocol, fake runner, deterministic fallback, or "native bridge" placeholder when the task/architecture promises a concrete internal capability such as BASALT VIO, FAISS retrieval, LightGlue matching, or a full A-Z localization pipeline. Stubs are allowed only for external systems and tests.
|
||||
- **Auto-start**: batches start immediately — no user confirmation before a batch
|
||||
- **Gate on failure**: user confirmation is required only when code review returns FAIL
|
||||
- **Commit per batch**: after each batch is confirmed, commit. Ask the user whether to push to remote unless the user previously opted into auto-push for this session.
|
||||
@@ -63,9 +64,31 @@ TASKS_DIR/
|
||||
└── done/ ← completed tasks (moved here after implementation)
|
||||
```
|
||||
|
||||
### Suite-level invocation context (meta-repo flow)
|
||||
|
||||
When invoked from `.cursor/skills/autodev/flows/meta-repo.md` Step 3.5 (or any caller that supplies the same context envelope), the skill receives:
|
||||
|
||||
```
|
||||
suite_level: true
|
||||
TASKS_DIR: <override> # e.g., _docs/tasks/ (vs. default _docs/02_tasks/)
|
||||
module_layout_path: <override> # e.g., _docs/tasks/_suite_module_layout.md
|
||||
```
|
||||
|
||||
When `suite_level: true` is present, the following gate adjustments apply — and ONLY these. All other steps (1–14, 16) execute unchanged:
|
||||
|
||||
1. **TASKS_DIR override** is honored throughout the skill (Step 1 Parse, Step 13 Archive, Step 15 input paths if it ran). Default `_docs/02_tasks/` is replaced by the supplied path.
|
||||
2. **module_layout_path override** is read instead of the hardcoded `_docs/02_document/module-layout.md` in Step 4 (Assign File Ownership). The supplied file uses the same `Per-Component Mapping` schema. If both the override and the hardcoded path are missing, behavior is unchanged from default mode (STOP and instruct).
|
||||
3. **Step 14.5 (Cumulative Code Review) — SKIPPED**. The meta-repo has no `_docs/02_document/architecture_compliance_baseline.md`; cross-task drift is captured by the next `monorepo-status` cycle instead.
|
||||
4. **Step 15 (Product Implementation Completeness Gate) — SKIPPED**. The gate's hard inputs (`_docs/02_document/architecture.md`, `system-flows.md`, `components/*/description.md`) do not exist in the meta-repo artifact layout. Suite-level tasks are infrastructure / coordination work (renames, cross-repo edits, suite-root infra additions), not feature implementation; the equivalent completeness signal is the next `monorepo-status` drift report (which the meta-repo flow re-runs immediately after Step 3.5 returns).
|
||||
5. **Final report filename**: `_docs/03_implementation/suite_implementation_report_{run_name}.md` (in addition to the existing feature/test/refactor variants). Batch reports follow `_docs/03_implementation/suite_batch_{NN}_report.md`.
|
||||
6. **Tracker integration** (Step 5: In Progress, Step 12: In Testing) runs unchanged — suite-level tickets follow the same tracker rules as any other.
|
||||
|
||||
Without `suite_level: true`, none of these adjustments apply and the skill runs exactly as documented in default mode.
|
||||
|
||||
## Prerequisite Checks (BLOCKING)
|
||||
|
||||
1. `TASKS_DIR/todo/` exists and contains at least one task file for the selected context — **STOP if missing**
|
||||
- Exception for Product implementation re-entry: if no selected product tasks remain in `todo/`, but the active autodev state is Step 7 or the latest product completeness report is missing/invalid/contains `FAIL`, skip directly to Step 15 (Product Implementation Completeness Gate). This gate may create remediation tasks and return to Step 1. Do not write a final implementation report from this state.
|
||||
2. `_dependencies_table.md` exists — **STOP if missing**
|
||||
3. At least one task is not yet completed — **STOP if all done**
|
||||
4. **Working tree is clean** — run `git status --porcelain`; the output must be empty.
|
||||
@@ -101,7 +124,7 @@ TASKS_DIR/
|
||||
|
||||
### 4. Assign File Ownership
|
||||
|
||||
The authoritative file-ownership map is `_docs/02_document/module-layout.md` (produced by the decompose skill's Step 1.5). Task specs are purely behavioral — they do NOT carry file paths. Derive ownership from the layout, not from the task spec's prose.
|
||||
The authoritative file-ownership map is `_docs/02_document/module-layout.md` (produced by the decompose skill's Step 1.5), unless `suite_level: true` was supplied in the invocation context — in which case the `module_layout_path` override is read instead (see "Suite-level invocation context" above). Task specs are purely behavioral — they do NOT carry file paths. Derive ownership from the layout, not from the task spec's prose.
|
||||
|
||||
For each task in the batch:
|
||||
- Read the task spec's **Component** field.
|
||||
@@ -129,7 +152,7 @@ For each task in the batch, transition its ticket status to **In Progress** via
|
||||
For each task in the batch **in topological order, one at a time**:
|
||||
1. Read the task spec file.
|
||||
2. Respect the file-ownership envelope computed in Step 4 (OWNED / READ-ONLY / FORBIDDEN).
|
||||
3. Implement the feature and write/update tests for every acceptance criterion in the spec. If a test cannot run in the current environment (e.g., TensorRT requires GPU), the test must still be written and skip with a clear reason.
|
||||
3. Implement the feature and write/update tests for every acceptance criterion in the spec. Tests for internal product behavior must exercise the production implementation path. If a test cannot run in the current environment (e.g., TensorRT requires GPU), the test must still exist and skip/block with a clear prerequisite reason, but that skip does not make missing production code complete.
|
||||
4. Run the relevant tests locally before moving on to the next task in the batch. If tests fail, fix in-place — do not defer.
|
||||
5. Capture a short per-task status line (files changed, tests pass/fail, any blockers) for the batch report.
|
||||
|
||||
@@ -220,6 +243,8 @@ For product implementation, this archive means "batch implementation accepted."
|
||||
|
||||
### 14.5. Cumulative Code Review (every K batches)
|
||||
|
||||
**Skipped entirely when `suite_level: true`** (see "Suite-level invocation context" above) — the meta-repo has no `architecture_compliance_baseline.md` to evaluate against; cross-task drift is captured by the next `monorepo-status` cycle.
|
||||
|
||||
- **Trigger**: every K completed batches (default `K = 3`; configurable per run via a `cumulative_review_interval` knob in the invocation context)
|
||||
- **Purpose**: per-batch review (Step 9) catches batch-local issues; cumulative review catches issues that only appear when tasks are combined — architecture drift, cross-task inconsistency, duplicate symbols introduced across different batches, contracts that drifted across producer/consumer batches
|
||||
- **Scope**: the union of files changed since the **last** cumulative review (or since the start of the run if this is the first)
|
||||
@@ -237,7 +262,7 @@ For product implementation, this archive means "batch implementation accepted."
|
||||
|
||||
### 15. Product Implementation Completeness Gate
|
||||
|
||||
Run this gate after all **product implementation** tasks are complete and before writing any final product implementation report or allowing autodev to proceed to testability/test decomposition. Skip this gate only when the remaining context is explicitly test implementation or refactoring, as determined by the task files and report filename rules.
|
||||
Run this gate after all **product implementation** tasks are complete and before writing any final product implementation report or allowing autodev to proceed to testability/test decomposition. Skip this gate when (a) the remaining context is explicitly test implementation or refactoring (as determined by the task files and report filename rules), OR (b) `suite_level: true` was supplied in the invocation context (the gate's inputs do not exist in the meta-repo artifact layout — see "Suite-level invocation context" above).
|
||||
|
||||
**Goal**: catch the failure mode where narrow tests validate scaffold behavior while the task's actual outcome, included scope, architecture promise, or named integration remains unimplemented.
|
||||
|
||||
@@ -255,26 +280,57 @@ For each completed product task:
|
||||
1. Read these sections from the task spec: `Description`, `Outcome`, `Scope / Included`, `Acceptance Criteria`, `Non-Functional Requirements`, `Constraints`, and explicit named technologies or integrations.
|
||||
2. Compare those promises against actual source code, not only tests or report prose.
|
||||
3. Search the task's owned component files for unresolved implementation markers: `placeholder`, `stub`, `reserved`, `TODO`, `NotImplemented`, `pass`, `deterministic`, `fake`, `mock`, `scaffold`, `native bridge`, and empty native/readme-only integration directories. Ignore test fixtures/mocks only when they are under test-owned paths and not used as production behavior.
|
||||
4. Verify that each named runtime dependency in the task promise is either integrated behind the approved boundary or explicitly documented as a blocked prerequisite in the task/report. Examples: if a task promises FAISS, DINOv2, BASALT, LightGlue, OpenCV, RANSAC, a database, cloud service, or hardware SDK, the production code must contain that integration boundary; a deterministic fallback alone is not complete.
|
||||
5. Verify tests exercise the real implementation path where local prerequisites exist. Environment-gated tests may skip only with an explicit prerequisite reason; they do not make missing production code complete.
|
||||
6. Classify each task:
|
||||
4. Verify that each named runtime dependency in the task promise is integrated as production behavior, not merely represented by an interface. Examples: if a task promises FAISS, DINOv2, BASALT, LightGlue, OpenCV, RANSAC, a database, cloud service, or hardware SDK, the production code must either call that dependency or contain an adapter that loads and executes the real dependency package. A deterministic fallback, fake runner, empty `native/` package, or "bridge to be supplied later" is **FAIL** unless the task itself explicitly scoped the dependency out before implementation started.
|
||||
5. Distinguish internal implementation from external prerequisites:
|
||||
- Internal product capabilities (VIO, anchor verification, cache retrieval, safety wrapper, FDR, MAVLink emission) must be implemented in production code before the task can pass.
|
||||
- External systems/hardware/data (Jetson device, physical camera, ArduPilot process, QGC, third-party service credentials, unavailable licensed dataset) may be `BLOCKED` only when production code exists and the missing prerequisite is outside the product boundary.
|
||||
6. Verify tests exercise the real implementation path where local prerequisites exist. Environment-gated tests may skip only with an explicit prerequisite reason; they do not make missing production code complete.
|
||||
7. For any architecture promise that describes an end-to-end user outcome, verify there is an executable production pipeline connecting the relevant components. Isolated component contracts and test-only harness orchestration are not enough.
|
||||
8. Classify each task:
|
||||
- **PASS**: task promises are implemented or explicitly out of scope in the task itself.
|
||||
- **BLOCKED**: production code exists but cannot be fully verified due to external hardware/data/license/runtime prerequisites; the blocker is explicit and tests report blocked/skipped with reason.
|
||||
- **FAIL**: promised production behavior is missing, only scaffolded, or only represented in tests/reports.
|
||||
|
||||
#### 15.b System-Pipeline Check (runs ONCE per gate invocation, after per-task classification)
|
||||
|
||||
The per-task classification above (steps 1–8) operates on `_docs/02_tasks/done/`. It catches missing component-local behavior but it CANNOT catch a missing *integration* — there is no task to fail if no task ever owned the integration in the first place. The GPS-passthrough incident (May 2026) escaped this gate because every per-component task in `done/` was honestly complete; the missing piece was the cross-component loop, which had no owning task.
|
||||
|
||||
The system-pipeline check fixes that by walking the architecture documents directly, independent of `done/`.
|
||||
|
||||
**Inputs**:
|
||||
- `_docs/02_document/architecture.md`
|
||||
- `_docs/02_document/system-flows.md`
|
||||
- Full source tree under the project's production directory (e.g. `src/`).
|
||||
|
||||
**Procedure**:
|
||||
|
||||
1. **Enumerate end-to-end pipelines.** Read `architecture.md` and `system-flows.md`. For each named pipeline / operational flow that spans 2+ components, record the ordered component sequence and the trigger (per-frame, per-request, scheduled, manual).
|
||||
2. **Grep for production callers of each seam method.** For each adjacent pair `A → B` in a pipeline, find a production source file (not under `tests/`, not under a `bench/` package, not a doc) that calls `A`'s public output method AND passes the result into `B`'s public input method.
|
||||
3. **Classify the pipeline**:
|
||||
- **WIRED**: a production caller exists and the chain is complete from the first to the last component in the sequence.
|
||||
- **PARTIALLY WIRED**: some adjacent pairs have callers but at least one seam is missing.
|
||||
- **NOT WIRED**: no production code calls the pipeline's components in order. Bench tools, unit tests, and microbenchmarks do NOT count as "wiring".
|
||||
4. **Distinguish "wired but stubbed" from "wired with real components"**: a caller that invokes a passthrough / GPS-from-tlog / mock-output-generator instead of the real component is `NOT WIRED` for the purposes of this gate. The seam exists in the source file but the production behavior is faked. Grep for the same scaffold markers Step 15 already enumerates (`placeholder`, `stub`, `passthrough`, `scaffold until`, etc.) inside the caller's body.
|
||||
5. **Output**: append a `## System Pipeline Audit` section to `_docs/03_implementation/implementation_completeness_cycle[N]_report.md`. Per-pipeline row: name, sequence, classification, evidence file (the caller, or "NONE FOUND"), remediation suggestion if not `WIRED`.
|
||||
|
||||
**Pipeline classification feeds the combined gate below.** Any pipeline that is not `WIRED` is a system-level FAIL that the per-task gate cannot rescue.
|
||||
|
||||
**Why this is here and not only in decompose**: decompose Step 1.7 creates integration tasks up front; this check verifies the integration tasks actually got implemented (or, if they were never created, surfaces the gap before the cycle closes). The two layers are belt-and-suspenders by design.
|
||||
|
||||
Save the audit to `_docs/03_implementation/implementation_completeness_cycle[N]_report.md` with:
|
||||
|
||||
- Per-task classification
|
||||
- Evidence files/symbols checked
|
||||
- Any unresolved scaffold/native placeholders
|
||||
- Any named promised technologies not integrated
|
||||
- **System Pipeline Audit table** (per pipeline: name, sequence, WIRED / PARTIALLY WIRED / NOT WIRED, evidence file, remediation suggestion)
|
||||
- Required remediation task suggestions, each sized to 5 points or less
|
||||
|
||||
Gate:
|
||||
|
||||
- If every product task is `PASS` or `BLOCKED` with explicit prerequisite evidence, continue to Final Test Run.
|
||||
- If any product task is `FAIL`, STOP. Do not write the final product implementation report and do not proceed to any downstream autodev step. Completed original task files remain in `done/`; the missing work is represented by remediation tasks. Present a Choose block:
|
||||
- A) Create remediation tasks now and return to implementation
|
||||
- If every product task is `PASS` or `BLOCKED` with explicit prerequisite evidence, AND every enumerated pipeline is `WIRED`, continue to Final Test Run.
|
||||
- If any product task is `FAIL` OR any pipeline is `PARTIALLY WIRED` / `NOT WIRED`, STOP. Do not write the final product implementation report and do not proceed to any downstream autodev step. Completed original task files remain in `done/`; the missing work is represented by remediation tasks. Present a Choose block:
|
||||
- A) Create remediation tasks now and return to implementation. (For pipeline FAILs the remediation task is a NEW integration task owned by the spine component per `_docs/02_document/module-layout.md`; it is NOT a test task and NOT a doc task; its deliverable is production code that drives the pipeline against real components.)
|
||||
- B) Mark the missing behavior explicitly out of scope in task/docs, then re-run this gate
|
||||
- C) Abort for manual correction
|
||||
- Recommendation must normally be A unless the user deliberately accepts reduced scope.
|
||||
@@ -303,8 +359,9 @@ After each batch completes, save the batch report to `_docs/03_implementation/ba
|
||||
- **Test implementation** (tasks from test decomposition): `_docs/03_implementation/implementation_report_tests.md`
|
||||
- **Feature implementation**: `_docs/03_implementation/implementation_report_{feature_slug}_cycle{N}.md` where `{feature_slug}` is derived from the batch task names (e.g., `implementation_report_core_api_cycle2.md`) and `{N}` is the current `state.cycle` from `_docs/_autodev_state.md`. If `state.cycle` is absent (pre-migration), default to `cycle1`.
|
||||
- **Refactoring**: `_docs/03_implementation/implementation_report_refactor_{run_name}.md`
|
||||
- **Suite-level** (when `suite_level: true` was supplied — see "Suite-level invocation context" above): `_docs/03_implementation/suite_implementation_report_{run_name}.md`. Batch reports use `_docs/03_implementation/suite_batch_{NN}_report.md`. `{run_name}` is derived from the batch task IDs (e.g., `suite_implementation_report_az543_az549_az550.md`).
|
||||
|
||||
Determine the context from the task files being implemented: if all tasks have test-related names or belong to a test epic, use the tests filename; otherwise derive the feature slug from the component names and append the cycle suffix.
|
||||
Determine the context from the task files being implemented: if all tasks have test-related names or belong to a test epic, use the tests filename; if `suite_level: true` was supplied, use the suite filename; otherwise derive the feature slug from the component names and append the cycle suffix.
|
||||
|
||||
Batch report filenames must also include the cycle counter when running feature implementation: `_docs/03_implementation/batch_{NN}_cycle{N}_report.md` (test and refactor runs may use the plain `batch_{NN}_report.md` form since they are not cycle-scoped).
|
||||
|
||||
|
||||
@@ -84,29 +84,66 @@ Assess the change along these dimensions:
|
||||
- **Novelty**: does it involve libraries, protocols, or patterns not already in the codebase?
|
||||
- **Risk**: could it break existing functionality or require architectural changes?
|
||||
|
||||
Classification:
|
||||
### 2a. Complexity-Points Estimate
|
||||
|
||||
Project policy (per the workspace user-rule on ADO points): aim for tasks at 2–3 points (rarely 5). Tasks at 8 points are high risk; tasks at 13 are too complex and MUST be broken down. The new-task skill enforces this here, before producing a single-file task spec.
|
||||
|
||||
Map the Scope/Novelty/Risk profile to a points estimate using this table:
|
||||
|
||||
| Profile | Points | Examples |
|
||||
|---------|--------|----------|
|
||||
| All three low | **1–2** | One-line config change; trivial CRUD field addition |
|
||||
| Two low + one medium | **3** | Localized refactor; add one well-understood endpoint |
|
||||
| One low + two medium, OR all medium | **5** | New small feature touching 2–3 components; integration with a known library |
|
||||
| Any high, OR two medium + one high | **8** | Cross-cutting concern across 4+ components; integration with an unfamiliar protocol; significant architectural change |
|
||||
| Two or three high | **13** | New subsystem; unfamiliar tech across the stack; multiple unknown unknowns |
|
||||
|
||||
If a relevant LESSONS.md entry biases the estimate (e.g., "auth-related changes historically take 2× estimate"), apply the multiplier and round up to the next discrete point on the scale (1, 2, 3, 5, 8, 13).
|
||||
|
||||
### 2b. Routing by Complexity
|
||||
|
||||
| Estimate | Default routing | Override path |
|
||||
|----------|-----------------|---------------|
|
||||
| **1–5** | Continue this skill at Step 3 (Research) or Step 4 (Codebase Analysis) — see classification below | — |
|
||||
| **8** | **STOP this skill and recommend handoff to `/decompose @<feature_description>`** (single-component decompose mode if the affected scope fits inside one component, default mode if it does not). The user may override and proceed in `/new-task`, but the override must be explicitly chosen. | C) Proceed in /new-task anyway with the user's acknowledgement that the resulting task is high-risk and may need to be re-decomposed mid-implementation |
|
||||
| **13** | **STOP this skill — auto-handoff is mandatory.** A 13-point feature cannot be a single task spec. Invoke `/decompose @<feature_description>` (default mode) before writing any task file. Surface the handoff to the user with no override path; this is a hard policy gate. | None — must decompose |
|
||||
|
||||
For the auto-handoff path:
|
||||
|
||||
1. Render a one-paragraph description of the feature suitable to feed `/decompose` (combine Step 1's verbatim user description with the complexity-points reasoning).
|
||||
2. Save it to `_docs/02_task_plans/<feature_slug>/feature-description.md` so the decompose skill has a stable input file.
|
||||
3. Either (a) directly auto-chain into `.cursor/skills/decompose/SKILL.md` in default mode with this file as input, or (b) report the handoff to the user along with the exact `/decompose` invocation and stop. Pick (a) only if the user has explicitly enabled auto-chain across skills (e.g., we are inside an `/autodev` invocation); otherwise pick (b).
|
||||
|
||||
### 2c. Research vs Skip Research (only for ≤5 estimates)
|
||||
|
||||
Classification (independent of points; runs only when points ≤ 5 and Step 2b chose Continue):
|
||||
|
||||
| Category | Criteria | Action |
|
||||
|----------|----------|--------|
|
||||
| **Needs research** | New libraries/frameworks, unfamiliar protocols, significant architectural change, multiple unknowns | Proceed to Step 3 (Research) |
|
||||
| **Needs research** | New libraries/frameworks, unfamiliar protocols, multiple unknowns | Proceed to Step 3 (Research) |
|
||||
| **Skip research** | Extends existing functionality, uses patterns already in codebase, straightforward new component with known tech | Skip to Step 4 (Codebase Analysis) |
|
||||
|
||||
Present the assessment to the user:
|
||||
Present the full assessment to the user:
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
COMPLEXITY ASSESSMENT
|
||||
══════════════════════════════════════
|
||||
Scope: [low / medium / high]
|
||||
Novelty: [low / medium / high]
|
||||
Risk: [low / medium / high]
|
||||
Scope: [low / medium / high]
|
||||
Novelty: [low / medium / high]
|
||||
Risk: [low / medium / high]
|
||||
Points: [1 / 2 / 3 / 5 / 8 / 13] (project aim: 2–3, rarely 5)
|
||||
Routing: [Continue in /new-task | Hand off to /decompose]
|
||||
══════════════════════════════════════
|
||||
Recommendation: [Research needed / Skip research]
|
||||
Reason: [one-line justification]
|
||||
Recommendation: [Research needed | Skip research | Decompose required]
|
||||
Reason: [one-line justification, including any LESSONS.md influence]
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
**BLOCKING**: Ask the user to confirm or override the recommendation before proceeding.
|
||||
**BLOCKING**:
|
||||
- If points ≤ 5 → ask the user to confirm or override the research recommendation before proceeding.
|
||||
- If points = 8 → ask the user to choose between hand-off to /decompose (recommended) and continuing in /new-task with explicit risk acknowledgement.
|
||||
- If points = 13 → STOP and present the handoff plan; do not offer a continue-anyway override.
|
||||
|
||||
---
|
||||
|
||||
@@ -203,7 +240,13 @@ Apply the four shared-task triggers from `.cursor/skills/decompose/SKILL.md` Ste
|
||||
2. Add the layout edit to the task's deliverables; the implementer writes it alongside the code change.
|
||||
3. If `module-layout.md` does not exist, STOP and instruct the user to run `/document` first (existing-code flow) or `/decompose` default mode (greenfield). Do not guess.
|
||||
|
||||
Record the classification and any contract/layout deliverables in the working notes; they feed Step 5 (Validate Assumptions) and Step 6 (Create Task).
|
||||
- **ADR cross-check** — runs unconditionally for every new-task in any of the three classifications above:
|
||||
1. If `_docs/02_document/adr/` exists, scan every `Status: Accepted` ADR. For each, ask: "would the proposed task either contradict this ADR's `Decision` or materially affect its `Consequences`?"
|
||||
2. **Conflict** (task contradicts an Accepted ADR) → STOP and Choose A/B/C: **A)** Re-scope the task to comply with the ADR, **B)** Propose superseding the ADR — the task spec then includes a deliverable to invoke `/plan --adr-only` (or the next `/plan` cycle's Step 4.5) with `Supersedes: ADR-NNN`, and the new task does NOT proceed until that supersede ADR is `Accepted`, **C)** Park the task in `backlog/` with a `Blocked-By: ADR-NNN review` note. Do not silently approve a contradictory task.
|
||||
3. **Drift** (task changes assumptions an ADR depends on but does not directly contradict it) → record the affected ADR(s) under a new `### ADR Impact` section in the task spec with `> Affects ADR NNN_<slug>: <one-line summary>`. The implementer surfaces this at code-review Phase 7 (which then classifies it as ADR-Drift if not addressed).
|
||||
4. **Aligned** (task implements something an Accepted ADR mandates) → cite the ADR(s) under `### ADR Compliance` in the task spec with `> Implements ADR NNN_<slug>`. Code-review Phase 7 then expects matching evidence in the implemented code.
|
||||
|
||||
Record the classification, any contract/layout deliverables, and any ADR cross-check outcomes in the working notes; they feed Step 5 (Validate Assumptions) and Step 6 (Create Task).
|
||||
|
||||
**BLOCKING**: none — this step surfaces findings; the user confirms them in Step 5.
|
||||
|
||||
@@ -263,6 +306,9 @@ Present using the Choose format for each decision that has meaningful alternativ
|
||||
- [ ] If Step 4.5 classified the task as producer, the `## Contract` section exists and points at a contract file
|
||||
- [ ] If Step 4.5 classified the task as consumer, `### Document Dependencies` lists the relevant contract file
|
||||
- [ ] If Step 4.5 flagged a layout delta, the task's Scope.Included names the `module-layout.md` edit
|
||||
- [ ] If Step 4.5 flagged an ADR conflict, the task is either re-scoped (A), explicitly blocked on a supersede ADR (B), or parked in backlog (C) — never silently bypassed
|
||||
- [ ] If Step 4.5 flagged ADR drift, the task spec has an `### ADR Impact` section listing the affected ADR(s)
|
||||
- [ ] If Step 4.5 flagged ADR alignment, the task spec has an `### ADR Compliance` section citing the implemented ADR(s)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ disable-model-invocation: true
|
||||
|
||||
# Solution Planning
|
||||
|
||||
Decompose a problem and solution into architecture, data model, deployment plan, system flows, components, tests, and work item epics through a systematic 6-step workflow.
|
||||
Decompose a problem and solution into architecture, data model, deployment plan, system flows, components, ADRs, tests, and work item epics through a systematic workflow with seven step files (1, 2, 3, 4, 4.5, 5, 6) plus a Final quality checklist.
|
||||
|
||||
## Core Principles
|
||||
|
||||
@@ -55,7 +55,7 @@ Read `steps/01_artifact-management.md` for directory structure, save timing, sav
|
||||
|
||||
## Progress Tracking
|
||||
|
||||
At the start of execution, create a TodoWrite with all steps (1 through 6 plus Final). Update status as each step completes.
|
||||
At the start of execution, create a TodoWrite with all steps (1, 2, 3, 4, 4.5, 5, 6 plus Final). Update status as each step completes. The fractional Step 4.5 (ADR Capture) sits between Architecture Review (Step 4) and Test Specifications (Step 5).
|
||||
|
||||
## Workflow
|
||||
|
||||
@@ -85,6 +85,16 @@ Read and follow `steps/04_review-risk.md`.
|
||||
|
||||
---
|
||||
|
||||
### Step 4.5: Architecture Decision Records (ADRs)
|
||||
|
||||
Read and follow `steps/04-5_adr-capture.md`.
|
||||
|
||||
This step captures the architecture and tech-stack decisions that were made (or revised) in Steps 2–4 as durable, dated, immutable records under `_docs/02_document/adr/`. ADRs are the single thing in `_docs/` that explain the **why** of each major decision after the conversation history is gone. They are consumed by `decompose` (when bootstrapping module layout), `new-task` (when assessing a new feature against existing decisions), `refactor` (when proposing replacements), and any future code-review cycle that needs to confirm a structural choice was deliberate.
|
||||
|
||||
This step is **BLOCKING**: the ADR set must be reviewed and confirmed by the user before Step 5 begins.
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Test Specifications
|
||||
|
||||
Read and follow `steps/05_test-specifications.md`.
|
||||
@@ -120,7 +130,7 @@ Read and follow `steps/07_quality-checklist.md`.
|
||||
|-----------|--------|
|
||||
| Missing acceptance_criteria.md, restrictions.md, or input_data/ | **STOP** — planning cannot proceed |
|
||||
| Ambiguous requirements | ASK user |
|
||||
| Input data coverage below 75% | Search internet for supplementary data, ASK user to validate |
|
||||
| Input data coverage below the canonical threshold (`cursor-meta.mdc` Quality Thresholds) | Search internet for supplementary data, ASK user to validate |
|
||||
| Technology choice with multiple valid options | ASK user |
|
||||
| Component naming | PROCEED, confirm at next BLOCKING gate |
|
||||
| File structure within templates | PROCEED |
|
||||
@@ -146,6 +156,8 @@ Read and follow `steps/07_quality-checklist.md`.
|
||||
│ [BLOCKING: user confirms components] │
|
||||
│ 4. Review & Risk → risk register, iterations │
|
||||
│ [BLOCKING: user confirms mitigations] │
|
||||
│ 4.5 ADR Capture → _docs/02_document/adr/NNN_*.md │
|
||||
│ [BLOCKING: user confirms ADR set] │
|
||||
│ 5. Test Specifications → per-component test specs │
|
||||
│ 6. Work Item Epics → epic per component + bootstrap │
|
||||
│ ───────────────────────────────────────────────── │
|
||||
|
||||
@@ -26,6 +26,10 @@ DOCUMENT_DIR/
|
||||
│ └── deployment_procedures.md
|
||||
├── risk_mitigations.md
|
||||
├── risk_mitigations_02.md (iterative, ## as sequence)
|
||||
├── adr/
|
||||
│ ├── 001_[decision_slug].md
|
||||
│ ├── 002_[decision_slug].md
|
||||
│ └── ...
|
||||
├── components/
|
||||
│ ├── 01_[name]/
|
||||
│ │ ├── description.md
|
||||
@@ -66,6 +70,8 @@ DOCUMENT_DIR/
|
||||
| Step 3 | Common helpers generated | `common-helpers/[##]_helper_[name].md` |
|
||||
| Step 3 | Diagrams generated | `diagrams/` |
|
||||
| Step 4 | Risk assessment complete | `risk_mitigations.md` |
|
||||
| Step 4.5 | Each ADR captured | `adr/NNN_[decision_slug].md` |
|
||||
| Step 4.5 | ADR index updated | `adr/README.md` |
|
||||
| Step 5 | Tests written per component | `components/[##]_[name]/tests.md` |
|
||||
| Step 6 | Epics created in work item tracker | Tracker via MCP |
|
||||
| Final | All steps complete | `FINAL_report.md` |
|
||||
@@ -85,3 +91,15 @@ If DOCUMENT_DIR already contains artifacts:
|
||||
2. Identify the last completed step based on which artifacts exist
|
||||
3. Resume from the next incomplete step
|
||||
4. Inform the user which steps are being skipped
|
||||
|
||||
#### Step 4.5 (ADR Capture) resumption rule
|
||||
|
||||
ADR files have a `Status` field that disambiguates "step in progress" from "step done":
|
||||
|
||||
- `Status: Proposed` → Step 4.5 is **in progress**. The user has not yet hit the BLOCKING gate (or hit it and chose B/C/D, which kept files at `Proposed`). Resume Step 4.5 at Phase 4.5f and re-present the BLOCKING Choose to the user. Do NOT skip to Step 5.
|
||||
- `Status: Accepted` AND `adr/README.md` index exists AND every Accepted ADR is referenced in the index → Step 4.5 is **done**. Skip to Step 5.
|
||||
- `Status: Accepted` but `adr/README.md` is missing or out of date → Step 4.5 is **partially complete**. Resume at Phase 4.5d (Maintain the ADR Index) before moving on.
|
||||
- Mixed `Proposed` + `Accepted` files in the same directory → Step 4.5 is **in progress** with prior partial confirmations. Resume at Phase 4.5f and re-present only the still-`Proposed` ADRs.
|
||||
- Empty `adr/` directory or no `adr/` directory → Step 4.5 has not started yet. Begin at Phase 4.5a.
|
||||
|
||||
The `Date` field on every Accepted ADR is the date the user confirmed it; do not regenerate it during resumption.
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
# Step 4.5: Architecture Decision Records (ADRs)
|
||||
|
||||
**Role**: Architect / technical writer
|
||||
**Goal**: Capture every major architecture, tech-stack, data-model, and integration decision made during Steps 2–4 as a durable, dated, immutable record under `_docs/02_document/adr/`.
|
||||
**Constraints**: ADRs only — do not re-open architecture; do not make new decisions in this step. Document what has been decided, not what is still open.
|
||||
|
||||
ADRs are the single thing in `_docs/` that explains the **why** of each major decision after the conversation history is gone. They are consumed by:
|
||||
|
||||
- `decompose` Step 1.5 (`steps/01-5_module-layout.md`) — every Accepted ADR is cross-checked against the module-layout proposal; conflicts trigger an explicit Choose between supersede / exception / re-open.
|
||||
- `new-task` Step 4.5 (`SKILL.md` § "Step 4.5: Contract & Layout Check") — every new task is classified against Accepted ADRs as Conflict / Drift / Aligned; conflicts STOP the task with a Choose A/B/C; drift adds an `### ADR Impact` section; alignment adds an `### ADR Compliance` section.
|
||||
- `refactor` Phase 2b.1 (`phases/02-analysis.md`) — every Accepted ADR is diffed against the proposed roadmap; Violations trigger a BLOCKING supersede gate that produces a `supersede_adr_NNN.md` task before any refactor task is created.
|
||||
- `code-review` Phase 7 (`SKILL.md` § "Phase 7: Architecture Compliance") — every changed-files batch is checked against Accepted ADRs; ADR-Violation findings are Critical, ADR-Drift findings are High.
|
||||
|
||||
Discipline that still relies on the human: when a downstream skill detects a Drift case, the resulting task spec MUST land its `## ADR Impact` / `## ADR Compliance` section; the implementer must address it; the next code-review batch then has the context it needs. Drift left undocumented is the silent-failure path — every consumer hook above is designed to make it visible.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `_docs/02_document/architecture.md` (incl. confirmed `## Architecture Vision`)
|
||||
- `_docs/02_document/glossary.md`
|
||||
- `_docs/02_document/data_model.md`
|
||||
- `_docs/02_document/system-flows.md`
|
||||
- `_docs/02_document/risk_mitigations.md` (and any `risk_mitigations_NN.md` iterations from Step 4)
|
||||
- `_docs/02_document/components/[##]_[name]/description.md`
|
||||
- `_docs/02_document/deployment/` (CI/CD, environments, observability)
|
||||
- `_docs/00_problem/restrictions.md` and `_docs/00_problem/acceptance_criteria.md` (each ADR must reference relevant constraints / AC by ID)
|
||||
- Optional: `_docs/01_solution/solution.md` and `_docs/01_solution/tech_stack.md` (research output)
|
||||
- Optional: `_docs/LESSONS.md` — surface any lesson categories of `architecture` / `dependencies` that bias the recommendation
|
||||
|
||||
## What is an ADR (and what is not)
|
||||
|
||||
Capture an ADR when **all** of the following hold:
|
||||
|
||||
1. The decision picks between two or more genuinely valid approaches with meaningful trade-offs.
|
||||
2. The decision has **downstream consequences** that other decisions, code, or tasks inherit from.
|
||||
3. The decision is **non-obvious** to a future reader who only sees the final code — they would ask "why was it built this way?" rather than discovering the answer by reading the source.
|
||||
|
||||
Do NOT create an ADR for:
|
||||
|
||||
- Naming, formatting, or purely cosmetic choices.
|
||||
- A choice that is fully implied by a single explicit restriction (`restrictions.md` is itself the record — link to it from the architecture doc instead).
|
||||
- A choice the team has not actually made yet — open questions live in `risk_mitigations.md` or `_docs/_process_leftovers/`, not in ADRs.
|
||||
- A technology selection where research already produced an exact-fit selection with one viable option (the research doc is the record — link to the relevant `solution_draft*.md` section).
|
||||
|
||||
## Process
|
||||
|
||||
### Phase 4.5a: Decision Inventory
|
||||
|
||||
Walk the inputs and list candidate decisions. For each candidate, record a one-liner:
|
||||
|
||||
```
|
||||
- [decision] — [trade-off summary] — [downstream consumers] — [evidence file:section]
|
||||
```
|
||||
|
||||
Inspect at minimum:
|
||||
|
||||
| Inspection target | Typical decisions surfaced |
|
||||
|-------------------|----------------------------|
|
||||
| `architecture.md` § layering | Layering style (clean vs hex vs n-tier), which layer owns transactions, how cross-cutting concerns enter |
|
||||
| `architecture.md` § Architecture Vision | The North Star principle (e.g., "edge-first, sync-second"); ADR captures the implication for one specific subsystem |
|
||||
| `data_model.md` | Datastore choice (Postgres vs Mongo), partitioning, soft vs hard deletes, schema evolution strategy |
|
||||
| `system-flows.md` | Sync vs async boundaries, idempotency strategy, retry policy ownership, error envelope shape |
|
||||
| `components/*/description.md` § interfaces | Public-API style (REST vs RPC vs event), versioning strategy, auth/authorization placement |
|
||||
| `deployment/containerization.md` | Single container vs sidecar vs init container, base image lineage |
|
||||
| `deployment/ci_cd_pipeline.md` | Trunk-based vs feature-branch, gate ordering, deploy strategy (blue-green / canary / all-at-once) |
|
||||
| `deployment/observability.md` | Logging stack, metric backend, sampling rate decisions, retention |
|
||||
| `risk_mitigations.md` | Risk-acceptance trade-offs (e.g., "we accept N% data loss in exchange for sub-100ms p99") |
|
||||
| Tech-stack from `_docs/01_solution/tech_stack.md` | Anything where research recorded ≥2 candidates and a winner |
|
||||
|
||||
Drop any candidate that fails the three "what is an ADR" criteria above. Keep the rest.
|
||||
|
||||
### Phase 4.5b: Numbering and Slugs
|
||||
|
||||
ADRs are numbered globally per project, monotonically, never re-used.
|
||||
|
||||
1. List existing files under `_docs/02_document/adr/` matching `^[0-9]{3}_.+\.md$`.
|
||||
2. The next ADR number is `max(existing) + 1`, zero-padded to 3 digits.
|
||||
3. The slug is kebab-case, ≤6 words, derived from the decision summary. Example: `001_use-postgres-for-transactional-data.md`, `004_event-driven-cross-component-comms.md`.
|
||||
|
||||
### Phase 4.5c: Render One ADR Per Decision
|
||||
|
||||
For each kept candidate, render the ADR using `templates/adr.md`. Required sections (do NOT omit any):
|
||||
|
||||
| Section | Content |
|
||||
|---------|---------|
|
||||
| **Number** | `NNN` |
|
||||
| **Title** | One-line decision statement (matches slug) |
|
||||
| **Status** | `Proposed` (only during Step 4.5 iteration) → `Accepted` (after user confirmation at the BLOCKING gate) |
|
||||
| **Date** | YYYY-MM-DD (the date the user confirmed) |
|
||||
| **Deciders** | The user (project owner) — the AI is not a decider |
|
||||
| **Context** | The problem this decision addresses, including links to AC IDs, restriction IDs, risks, and (where relevant) the research draft section |
|
||||
| **Decision** | The chosen approach in one sentence, then the supporting detail |
|
||||
| **Alternatives Considered** | Each alternative with a one-line "rejected because…" |
|
||||
| **Consequences** | Positive (what becomes easier / cheaper / faster) and negative (what becomes harder / locked in / costly to undo). Be honest — every decision has a downside. |
|
||||
| **Supersedes / Superseded by** | Empty initially; updated when a future ADR overturns this one |
|
||||
| **Evidence** | File-and-section pointers into `_docs/` showing where the decision is reflected (architecture.md § layering, components/02_*/description.md § interface, etc.) |
|
||||
|
||||
After rendering, write each file to `_docs/02_document/adr/NNN_<slug>.md`. Keep `Status: Proposed` until the BLOCKING gate.
|
||||
|
||||
### Phase 4.5d: Maintain the ADR Index
|
||||
|
||||
Write or update `_docs/02_document/adr/README.md` with this exact shape:
|
||||
|
||||
```markdown
|
||||
# Architecture Decision Records
|
||||
|
||||
This index lists every ADR for this project, in number order. ADRs are immutable once `Accepted` —
|
||||
new decisions that overturn a prior ADR are recorded as new ADRs whose `Supersedes` field points
|
||||
back, and the original ADR's `Superseded by` field is updated.
|
||||
|
||||
| # | Title | Status | Date | Supersedes |
|
||||
|---|-------|--------|------|------------|
|
||||
| 001 | Use Postgres for transactional data | Accepted | 2026-05-21 | — |
|
||||
| 002 | Event-driven cross-component comms | Accepted | 2026-05-21 | — |
|
||||
| ... | ... | ... | ... | ... |
|
||||
```
|
||||
|
||||
Sort by `#` ascending. Include all ADRs ever written, even superseded ones — the audit trail is the point.
|
||||
|
||||
### Phase 4.5e: Cross-Link from architecture.md
|
||||
|
||||
In `architecture.md`, every section that reflects an ADR decision gets a one-line trailing reference:
|
||||
|
||||
```markdown
|
||||
> See ADR 001 (Use Postgres for transactional data), ADR 003 (Event-driven cross-component comms).
|
||||
```
|
||||
|
||||
Place the reference at the end of the section, after the prose. This lets a future reader of `architecture.md` jump straight to the rationale.
|
||||
|
||||
### Phase 4.5f: BLOCKING Gate — User Confirmation
|
||||
|
||||
Present the ADR set to the user using the Choose format from `.cursor/skills/autodev/protocols.md` (or plain text if AskQuestion is unavailable):
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
DECISION REQUIRED: ADR set captured (N records)
|
||||
══════════════════════════════════════
|
||||
001 — [title]
|
||||
002 — [title]
|
||||
...
|
||||
══════════════════════════════════════
|
||||
A) Accept all ADRs as written
|
||||
B) Edit specific ADRs (numbers and edits)
|
||||
C) Add a missed decision (description)
|
||||
D) Remove an ADR (number and reason)
|
||||
══════════════════════════════════════
|
||||
Recommendation: A — review the rendered set and confirm; corrections are quick on Round 2
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
Loop:
|
||||
|
||||
- **A** → flip every ADR's `Status` from `Proposed` to `Accepted`, set `Date` to today's date, save, exit step.
|
||||
- **B** → apply edits, re-present the modified ADRs, loop.
|
||||
- **C** → run Phase 4.5a–4.5e for the missed decision only, append to the set, re-present, loop.
|
||||
- **D** → confirm with the user that the candidate fails the three "what is an ADR" criteria, remove the file, update the index, loop.
|
||||
|
||||
Do NOT mark `Accepted` without an explicit user A.
|
||||
|
||||
## Self-verification
|
||||
|
||||
- [ ] Every kept candidate from Phase 4.5a has a corresponding file under `adr/`
|
||||
- [ ] Every ADR has all required sections (none empty except `Supersedes` / `Superseded by`)
|
||||
- [ ] `Decision` sections are one-sentence-then-detail, not "we'll figure it out"
|
||||
- [ ] `Alternatives Considered` lists at least one rejected alternative per ADR
|
||||
- [ ] `Consequences` lists both positive AND negative consequences (an ADR with no negatives is suspect)
|
||||
- [ ] `Evidence` points at real `_docs/` sections that exist on disk
|
||||
- [ ] `adr/README.md` index lists every file in the directory and matches their `Status` / `Date`
|
||||
- [ ] `architecture.md` has a trailing `See ADR …` reference at every section that an ADR reflects
|
||||
- [ ] The user confirmed the set via Choose A; every ADR is `Accepted` with today's date
|
||||
|
||||
## Common mistakes
|
||||
|
||||
- **Re-opening architecture**: Step 4.5 records, it does not decide. If a candidate decision turns out to be unsettled, that's a Step 2 / Step 4 gap — return there, do not paper over it with a wishy-washy ADR.
|
||||
- **Decision-of-the-week**: do not write an ADR for every minor pattern choice. The bar is "non-obvious to a future reader". 5–15 ADRs is typical for a planning round; 40+ is over-capture.
|
||||
- **Negative consequences left empty**: every real decision has costs. If you cannot name one, the decision was not actually weighed.
|
||||
- **Vague evidence**: `architecture.md` is not enough — point at the specific section. `architecture.md § Layering` ≠ `architecture.md`.
|
||||
- **Numbering reuse**: never recycle a number from a deleted ADR. The audit trail is more important than tidy numbering.
|
||||
- **Superseding without recording**: when a later cycle overturns an ADR, the new ADR must point at the old one via `Supersedes`, AND the old ADR's `Superseded by` field must be updated. Index reflects both. (This is enforced when `decompose` or `refactor` later updates ADRs.)
|
||||
|
||||
## Escalation
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| Candidate decision is unsettled (the team has not actually decided) | Return to the originating step (2 / 3 / 4); do NOT write a placeholder ADR |
|
||||
| Two candidates in Phase 4.5a turn out to be the same decision phrased differently | Merge into one ADR, list both phrasings in `Context` |
|
||||
| User picks D (remove an ADR) and the AI judges the decision is genuinely worth recording | Surface the disagreement, ASK why the user wants it removed, defer to user |
|
||||
| Existing `adr/` directory has files but `adr/README.md` is missing or stale | Rebuild the index from the directory before adding new ADRs |
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Role**: Professional Quality Assurance Engineer
|
||||
|
||||
**Goal**: Write test specs for each component achieving minimum 75% acceptance criteria coverage
|
||||
**Goal**: Write test specs for each component achieving the canonical minimum acceptance-criteria coverage (currently 75% — see `.cursor/rules/cursor-meta.mdc` Quality Thresholds; do not restate a different number here)
|
||||
|
||||
**Constraints**: Test specs only — no test code. Each test must trace to an acceptance criterion.
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# ADR-{NNN}: {decision-title}
|
||||
|
||||
- **Status**: {Proposed | Accepted | Deprecated | Superseded}
|
||||
- **Date**: {YYYY-MM-DD}
|
||||
- **Deciders**: {user / project owner}
|
||||
- **Supersedes**: {ADR-NNN | —}
|
||||
- **Superseded by**: {ADR-NNN | —}
|
||||
|
||||
## Context
|
||||
|
||||
What problem does this decision address? Cite the relevant constraint(s), acceptance criterion / criteria, and risk(s) by ID.
|
||||
|
||||
- Acceptance criteria addressed: AC-{ID-1}, AC-{ID-2}
|
||||
- Restrictions addressed: R-{ID-1}, R-{ID-2}
|
||||
- Risks addressed: RISK-{ID-1}
|
||||
- Research source (if any): `_docs/01_solution/solution_draftN.md` § {section}
|
||||
|
||||
A short paragraph (3–6 sentences) explaining why a choice is required now and what makes it non-trivial. Do not pre-announce the decision here — that goes in `Decision`. Focus on the forces at play (load, scale, team familiarity, hardware constraints, regulatory drivers, third-party limits).
|
||||
|
||||
## Decision
|
||||
|
||||
One declarative sentence: **"We will …"** Then 1–3 paragraphs of supporting detail explaining how the decision will be implemented at the boundaries between components.
|
||||
|
||||
Be specific. "We will use Postgres" is too thin; "We will use Postgres 16 with logical replication for read scaling, restricting JSONB columns to top-level metadata only, with all transactional data in normalized tables" is the right resolution.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
| Alternative | Rejected because |
|
||||
|-------------|------------------|
|
||||
| {Alt 1 — short label} | {one line: the cost / mismatch / risk that ruled it out, ideally referencing a measurable criterion} |
|
||||
| {Alt 2 — short label} | {one line} |
|
||||
| {Alt 3 — short label} | {one line} |
|
||||
|
||||
At least one rejected alternative is mandatory. If only one option was ever considered, this is not an ADR — link to the source restriction or research selection from the parent doc instead.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- {What becomes easier / cheaper / faster, with concrete examples where possible}
|
||||
- {…}
|
||||
|
||||
### Negative
|
||||
|
||||
- {What becomes harder / locked in / costly to undo}
|
||||
- {…}
|
||||
|
||||
Every real decision has both. If the negatives section is hard to fill, the alternatives were probably not weighed seriously — return to the prior step.
|
||||
|
||||
### Neutral / Open
|
||||
|
||||
- {What is unchanged but worth flagging for future readers (e.g., "this does not change the auth boundary; auth remains in component 02_user_management as decided in ADR-003")}
|
||||
|
||||
## Evidence
|
||||
|
||||
Where this decision is reflected on disk. Use `file:section` links so future readers can jump.
|
||||
|
||||
- `_docs/02_document/architecture.md` § {section}
|
||||
- `_docs/02_document/data_model.md` § {section}
|
||||
- `_docs/02_document/components/{##_name}/description.md` § {section}
|
||||
- `_docs/02_document/system-flows.md` § {flow name}
|
||||
- `_docs/02_document/deployment/{file}.md` § {section}
|
||||
- {add more as needed}
|
||||
|
||||
## Notes
|
||||
|
||||
Optional. Use for caveats that did not fit above, links to external research, or follow-ups that the team agreed to revisit on a known trigger ("re-evaluate after 6 months in production" / "re-evaluate when load exceeds 10× baseline").
|
||||
@@ -1,6 +1,6 @@
|
||||
# Final Planning Report Template
|
||||
|
||||
Use this template after completing all 6 steps and the quality checklist. Save as `_docs/02_document/FINAL_report.md`.
|
||||
Use this template after completing all steps (1, 2, 3, 4, 4.5, 5, 6) and the quality checklist. Save as `_docs/02_document/FINAL_report.md`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -181,6 +181,8 @@ Categorized measurable criteria with markdown headers and bullet points:
|
||||
|
||||
Every criterion must have a measurable value. Vague criteria like "should be fast" are not acceptable — push for "less than 400ms end-to-end".
|
||||
|
||||
**AC must be design-independent**: describe testable outcomes only — no libraries, algorithms, params, or design choices. Implementation follows AC, never reverse. (IEEE 830 / Atlassian / GitScrum)
|
||||
|
||||
### input_data/
|
||||
|
||||
At least one file. Options:
|
||||
|
||||
@@ -39,6 +39,44 @@ Write `RUN_DIR/analysis/research_findings.md`:
|
||||
4. Prioritize changes by impact and effort
|
||||
5. Reject or escalate any proposed refactor that improves code structure while weakening required behavior, integration contracts, runtime constraints, safety/security posture, or acceptance criteria
|
||||
|
||||
### 2b.1. ADR Superseding Gate (BLOCKING)
|
||||
|
||||
A refactor that improves code structure while overturning a documented architecture decision is the silent-drift class the project repeatedly burns on (see `meta-rule.mdc` § GPS-passthrough postmortem and the auto-lessons it produced). This gate makes drift visible and forces a deliberate ADR update.
|
||||
|
||||
1. **List candidate ADRs**: read every `Status: Accepted` file in `_docs/02_document/adr/`. If the directory does not exist or contains only the index, log `No ADRs in scope` to `RUN_DIR/analysis/adr_impact.md` and skip the rest of this gate.
|
||||
2. **Diff each candidate against the proposed refactor roadmap**: for each ADR, ask the same two questions as code-review Phase 7:
|
||||
- **Violation**: does any roadmap item do the *opposite* of the ADR's `Decision`?
|
||||
- **Drift**: does any roadmap item materially affect the ADR's `Consequences` (positive or negative) without contradicting the Decision outright?
|
||||
3. **Classify each impacted ADR** in `RUN_DIR/analysis/adr_impact.md`:
|
||||
|
||||
| ADR | Roadmap item | Impact | Required action |
|
||||
|-----|--------------|--------|-----------------|
|
||||
| NNN | `roadmap-item-NN` | Violation / Drift / Aligned | (filled by Choose A/B/C below) |
|
||||
|
||||
4. **For every Violation row, present a BLOCKING Choose**:
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
DECISION REQUIRED: Refactor would violate ADR-NNN (<title>)
|
||||
══════════════════════════════════════
|
||||
A) Update the ADR via supersede: the refactor produces a NEW ADR
|
||||
(`Supersedes: NNN`) capturing the new Decision, and ADR-NNN's
|
||||
`Superseded by` field is updated. The supersede ADR is itself a
|
||||
deliverable of this refactor run (added to RUN_DIR/analysis/adr_impact.md
|
||||
and to TASKS_DIR as a task) and must be `Accepted` before Phase 4.
|
||||
B) Reduce the refactor scope to NOT violate ADR-NNN
|
||||
C) Re-evaluate ADR-NNN: keep the refactor but only after ADR-NNN is
|
||||
formally re-opened in a new /plan Step 4.5 round
|
||||
══════════════════════════════════════
|
||||
Recommendation: A — supersede is the only path that keeps the audit
|
||||
trail intact while letting the refactor land
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
5. **For every Drift row**: do not block, but the roadmap item must include a `## ADR Impact` section in its task spec citing the affected ADR(s). The implementer surfaces this at code-review Phase 7, which would otherwise classify the change as ADR-Drift (High) without context.
|
||||
6. **For every Aligned row**: cite the ADR in the roadmap item's task spec under `## ADR Compliance`. No further action.
|
||||
7. **Self-supersede deliverable**: any Choose A path adds a `[##]_supersede_adr_NNN.md` task file to the refactor run's TASKS_DIR with the new ADR text drafted (using `.cursor/skills/plan/templates/adr.md`). The task's only Acceptance Criterion is "ADR file exists at `_docs/02_document/adr/<next>_<slug>.md` with `Status: Accepted`, ADR-NNN's `Superseded by` field updated, and `_docs/02_document/adr/README.md` index reflects both."
|
||||
|
||||
Present optional hardening tracks for user to include in the roadmap:
|
||||
|
||||
```
|
||||
@@ -67,6 +105,8 @@ Write `RUN_DIR/analysis/refactoring_roadmap.md`:
|
||||
|
||||
**BLOCKING applicability gate**: Before 2c and 2d, every recommendation in the roadmap must be `Selected`. Items marked `Rejected` are excluded. Items marked `Experimental only` or `Needs user decision` require a user decision before task creation.
|
||||
|
||||
**BLOCKING ADR-supersede gate**: Before 2c and 2d, every Violation row in `RUN_DIR/analysis/adr_impact.md` (from 2b.1) must be resolved via Choose A, B, or C. A Violation row with no chosen path blocks task creation.
|
||||
|
||||
## 2c. Create Epic
|
||||
|
||||
Create a work item tracker epic for this refactoring run:
|
||||
@@ -111,6 +151,10 @@ Convert the finalized `RUN_DIR/list-of-changes.md` into implementable task files
|
||||
- [ ] Task dependencies are consistent (no circular dependencies)
|
||||
- [ ] `_dependencies_table.md` includes all refactoring tasks
|
||||
- [ ] Every task has a work item ticket (or PENDING placeholder)
|
||||
- [ ] If `_docs/02_document/adr/` exists with Accepted ADRs, `RUN_DIR/analysis/adr_impact.md` has been written and every Violation row is resolved (A/B/C) — no implicit overrides
|
||||
- [ ] For every Violation resolved via Choose A, a `[##]_supersede_adr_NNN.md` task exists in TASKS_DIR with the drafted supersede ADR
|
||||
- [ ] For every Drift row, the corresponding roadmap-item task spec has a `## ADR Impact` section
|
||||
- [ ] For every Aligned row, the corresponding roadmap-item task spec has a `## ADR Compliance` section
|
||||
|
||||
**Save action**: Write analysis artifacts to RUN_DIR, task files to TASKS_DIR
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ Before designing or implementing any new tests, check what already exists:
|
||||
1. Scan the project for existing test files (unit tests, integration tests, blackbox tests)
|
||||
2. Run the existing test suite — record pass/fail counts
|
||||
3. Measure current coverage against the areas being refactored (from `RUN_DIR/list-of-changes.md` file paths)
|
||||
4. Assess coverage against thresholds:
|
||||
4. Assess coverage against thresholds (canonical: see `.cursor/rules/cursor-meta.mdc` Quality Thresholds — never hardcode a different number):
|
||||
- Minimum overall coverage: 75%
|
||||
- Critical path coverage: 90%
|
||||
- Critical path coverage: **90% floor / 100% aim** — 90% is the enforcement floor (blocks Phase 4 if not met); 100% is the aspirational target. Refactors are NOT permitted to drop below 90% on the critical paths covered by the in-scope changes.
|
||||
- All public APIs must have blackbox tests
|
||||
- All error handling paths must be tested
|
||||
|
||||
@@ -47,7 +47,7 @@ For each uncovered critical area, write test specs to `RUN_DIR/test_specs/[##]_[
|
||||
4. Document any discovered issues
|
||||
|
||||
**Self-verification**:
|
||||
- [ ] Coverage requirements met (75% overall, 90% critical paths) across existing + new tests
|
||||
- [ ] Coverage requirements met (75% overall, 90% critical-path floor — 100% aim — per canonical `cursor-meta.mdc` Quality Thresholds) across existing + new tests
|
||||
- [ ] All tests pass on current codebase
|
||||
- [ ] All public APIs in refactoring scope have blackbox tests
|
||||
- [ ] Test data fixtures are configured
|
||||
|
||||
@@ -45,7 +45,7 @@ Write `RUN_DIR/test_sync/new_tests.md`:
|
||||
- [ ] All obsolete tests removed or merged
|
||||
- [ ] All pre-existing tests pass after updates
|
||||
- [ ] New code from Phase 4 has test coverage
|
||||
- [ ] Overall coverage meets or exceeds Phase 3 baseline (75% overall, 90% critical paths)
|
||||
- [ ] Overall coverage meets or exceeds Phase 3 baseline (75% overall, 90% critical-path floor / 100% aim — per `.cursor/rules/cursor-meta.mdc` Quality Thresholds)
|
||||
- [ ] No tests reference removed or renamed code
|
||||
|
||||
**Save action**: Write test_sync artifacts; implemented tests go into the project's test folder
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
---
|
||||
name: release
|
||||
description: |
|
||||
Executes the deployment plan produced by /deploy against a target environment.
|
||||
Closes the loop between "we have a plan" and "the new version is running in production with a verdict on disk."
|
||||
6-phase workflow: pre-release gate, strategy select, execute, smoke test, watch window, commit-or-rollback.
|
||||
Outputs _docs/04_release/release_<version>.md with a definitive Released / Rolled-Back / Aborted verdict.
|
||||
Trigger phrases:
|
||||
- "release", "ship", "go live", "release this version"
|
||||
- "deploy to prod", "promote to staging", "roll out"
|
||||
- "rollback", "abort the release"
|
||||
category: ship
|
||||
tags: [release, deployment, rollback, smoke-test, observability, production]
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Release Execution
|
||||
|
||||
The `/deploy` skill produces a plan and scripts. The `/release` skill **runs** them, verifies the live system, watches it for a defined window, and produces a definitive verdict on disk.
|
||||
|
||||
## Core Principles
|
||||
|
||||
- **Real execution, not simulation**: every phase must actually run against the target environment. If a phase cannot be executed (missing scripts, no SSH access, disabled secrets, registry auth failure), STOP — do not pretend a step succeeded. See `meta-rule.mdc` § "Real Results, Not Simulated Ones".
|
||||
- **Verifiable rollback path**: the release does not start until rollback is proven viable for this version. "We can roll back" without evidence is not a rollback path.
|
||||
- **Quiet failure is a release failure**: a deploy script that exits 0 but emits no observable signal in the watch window is treated as a regression, not a success.
|
||||
- **One release per invocation**: a single `/release` execution targets exactly one version against exactly one environment. Multi-stage promotion (staging → prod) is two invocations, not one.
|
||||
- **Never skip the watch window**: even successful deploys can degrade after 5–60 minutes (cache warm-up, scheduled jobs, downstream backpressure). The watch window is mandatory.
|
||||
- **Autonomous rollback on hard regressions**: critical health-check failure, error-rate spike above threshold, or smoke-test failure → automatic rollback. Soft regressions (latency drift, capacity warnings) escalate to the user.
|
||||
|
||||
## Context Resolution
|
||||
|
||||
Fixed paths:
|
||||
|
||||
- DEPLOY_DIR: `_docs/04_deploy/`
|
||||
- RELEASE_DIR: `_docs/04_release/`
|
||||
- SCRIPTS_DIR: `scripts/`
|
||||
- DEPLOY_SCRIPT: `scripts/deploy.sh`
|
||||
- HEALTH_SCRIPT: `scripts/health-check.sh`
|
||||
- ENV_TEMPLATE: `.env.example`
|
||||
- OBSERVABILITY_DOC: `_docs/04_deploy/observability.md`
|
||||
- ENVIRONMENT_DOC: `_docs/04_deploy/environment_strategy.md`
|
||||
- PROCEDURES_DOC: `_docs/04_deploy/deployment_procedures.md`
|
||||
- ARCHITECTURE: `_docs/02_document/architecture.md`
|
||||
- RESTRICTIONS: `_docs/00_problem/restrictions.md`
|
||||
|
||||
Announce the resolved paths and the **target environment + version + strategy** to the user before any phase that touches the live system.
|
||||
|
||||
## Inputs (BLOCKING prerequisites)
|
||||
|
||||
| Input | Required | Source |
|
||||
|-------|----------|--------|
|
||||
| Target environment | Yes — ASK user | `environment_strategy.md` enumerates valid options |
|
||||
| Target version / image tag | Yes — ASK user | Must exist in the registry; verified in Phase 1 |
|
||||
| Rollback target version | Yes — ASK user | Defaults to currently-deployed version if discoverable |
|
||||
| `scripts/deploy.sh` | Yes | Produced by `/deploy` Step 7. STOP if missing → run `/deploy` first |
|
||||
| `scripts/health-check.sh` | Yes | Same |
|
||||
| `_docs/04_deploy/deployment_procedures.md` | Yes | Defines per-environment runbook, manual approval rules, change-window restrictions |
|
||||
| `_docs/04_deploy/observability.md` | Yes | Defines watch metrics, thresholds, and dashboards |
|
||||
| `_docs/04_deploy/environment_strategy.md` | Yes | Defines target hostnames, registries, secrets, deploy strategy per env |
|
||||
|
||||
## Outputs
|
||||
|
||||
```
|
||||
RELEASE_DIR/
|
||||
├── release_<version>_<env>_<YYYY-MM-DD-HHmm>.md (mandatory; one per invocation)
|
||||
├── rollback_<version>_<env>_<YYYY-MM-DD-HHmm>.md (only when rollback fires; pairs with the release file)
|
||||
└── manual_approvals/
|
||||
└── approval_<version>_<env>.md (when restrictions require manual approval, written before Phase 3)
|
||||
```
|
||||
|
||||
The release report (`templates/release-report.md`) is appended to as each phase completes — it is durable across phase failures and reflects partial progress so the next operator can resume or audit.
|
||||
|
||||
## Phases
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ Release Execution (6-Phase Method) │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ PREREQ: deploy artifacts on disk; tests green at HEAD │
|
||||
│ │
|
||||
│ 1. Pre-Release Gate → AC + change summary + readiness │
|
||||
│ [BLOCKING: user confirms or aborts] │
|
||||
│ 2. Strategy Select → all-at-once / blue-green / canary │
|
||||
│ [BLOCKING: user picks strategy] │
|
||||
│ 3. Execute → run deploy.sh, capture exit + logs │
|
||||
│ [AUTO-ROLLBACK on non-zero exit] │
|
||||
│ 4. Smoke Test → /test-run prod-smoke in target env │
|
||||
│ [AUTO-ROLLBACK on failure] │
|
||||
│ 5. Watch Window → poll observability for N minutes │
|
||||
│ [AUTO-ROLLBACK on hard threshold breach] │
|
||||
│ 6. Commit or Rollback → finalize verdict, update tracker │
|
||||
│ [BLOCKING: user confirms only if soft regression escalated] │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ Verdicts: Released · Rolled-Back · Aborted │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Phase 1: Pre-Release Gate
|
||||
|
||||
**Goal**: Refuse to start if the system is not ready for a real release.
|
||||
|
||||
1. **Acceptance criteria check**: read `_docs/00_problem/acceptance_criteria.md`. If any AC is marked unmet OR if any AC has no associated test marked `Passed` in the latest `test-run` report, STOP and surface the unmet items. Do not let the user override with "ship anyway" without a recorded reason in the release report.
|
||||
2. **Test status check**: read the most recent `_docs/06_metrics/perf_*.md` (if perf is required by restrictions) and the latest functional test report. Any failing or skipped test that maps to a critical-path AC blocks the release.
|
||||
3. **Change summary**: read the git log between the version-tag-of-last-release and HEAD (or, if no prior release exists, from the project root commit). Render a short list grouped by component: features, fixes, breaking changes, security fixes. Cross-reference against the latest implementation reports under `_docs/03_implementation/`.
|
||||
4. **Rollback readiness**:
|
||||
- Confirm the previous version's image is still pullable from the registry (do not deploy without this).
|
||||
- Confirm `scripts/deploy.sh --rollback` works as documented (read the script; if `--rollback` flag is missing, STOP — that is a deploy-skill bug).
|
||||
- Confirm a rollback target exists (e.g., previously-deployed image tag) and is recorded in the release report under `Rollback Plan`.
|
||||
5. **Restrictions**: read `_docs/00_problem/restrictions.md` for change-window rules, manual-approval rules, blackout windows, regulatory requirements (e.g., 4-eyes review, ITAR controls). If any apply, gate accordingly — write a `manual_approvals/approval_<version>_<env>.md` file once received.
|
||||
6. **Tracker check**: list tracker tickets in the release scope (per `tracker.mdc` rules). Any ticket still in `In Progress` or `Code Review` that maps to a change in the release scope blocks Phase 1. Move-and-deploy is not allowed.
|
||||
|
||||
**BLOCKING gate**: present the assembled summary to the user using Choose A/B/C:
|
||||
|
||||
```
|
||||
══════════════════════════════════════
|
||||
PRE-RELEASE GATE
|
||||
══════════════════════════════════════
|
||||
Target env: {env}
|
||||
Target version: {version} ({git-sha})
|
||||
Rollback target: {previous-version}
|
||||
Changes: N tickets, M components
|
||||
- {summary list}
|
||||
Open risks: {summary or "none"}
|
||||
Blocking issues: {summary or "none"}
|
||||
══════════════════════════════════════
|
||||
A) Proceed to Strategy Select
|
||||
B) Abort — fix blocking issue and re-invoke
|
||||
C) Edit release scope — exclude a ticket and reassemble
|
||||
══════════════════════════════════════
|
||||
```
|
||||
|
||||
If A → write Phase 1 section to release report, proceed. If B → write `Aborted` verdict to release report with reason, exit. If C → loop back into Phase 1 with edited scope.
|
||||
|
||||
### Phase 2: Strategy Select
|
||||
|
||||
**Goal**: Pick the deployment strategy that fits the change risk and environment capability.
|
||||
|
||||
Read `environment_strategy.md` and `deployment_procedures.md` to learn which strategies the target env supports. Strategies and when each is appropriate:
|
||||
|
||||
| Strategy | When to pick | Risk if wrong |
|
||||
|----------|--------------|---------------|
|
||||
| **all-at-once** | Internal tools, low traffic, well-rehearsed change, env supports nothing else | All users hit the new version simultaneously — bug blast radius is 100% |
|
||||
| **blue-green** | Stateless services with a load balancer, env has dual-stack capability | Cutover is binary — observability must be ready to detect issues fast |
|
||||
| **canary** | Customer-facing, traffic-tier load balancer in place, gradual rollout possible | Canary metric thresholds must be well-tuned or canary fails for harmless reasons |
|
||||
| **manual** | Non-automatable env (one-off VMs, regulated infrastructure, non-Docker host) | The whole release becomes a runbook and the watch window phases are operator-driven; the release skill records but does not execute |
|
||||
|
||||
Recommend a default based on:
|
||||
- Risk level inferred from change summary (any breaking change → bias toward canary or blue-green)
|
||||
- Restrictions (e.g., regulatory rules forcing manual approval at each step)
|
||||
- Environment capability (some envs may only support all-at-once)
|
||||
|
||||
**BLOCKING gate**: Choose A/B/C/D between strategies. Record the choice in the release report.
|
||||
|
||||
### Phase 3: Execute
|
||||
|
||||
**Goal**: Actually run the deploy. Capture exit code and full stdout/stderr.
|
||||
|
||||
1. Validate environment file (`.env`) exists, all required vars from `.env.example` are set, no placeholder secrets remain.
|
||||
2. Source the env file and run `scripts/deploy.sh` against the target host. The script produced by `/deploy` Step 7 is the point of execution; do NOT bypass it. If a strategy-specific flag is needed (e.g., `--canary 5%`), pass it through.
|
||||
3. Stream stdout/stderr to the release report, with timestamps, in a fenced code block under `## Phase 3: Execute`.
|
||||
4. Capture exit code.
|
||||
5. **AUTO-ROLLBACK trigger**: non-zero exit code → immediately invoke Phase 6 with verdict `Rolled-Back: deploy script failure`. Do NOT continue to Phase 4.
|
||||
|
||||
If `deploy.sh` emits no output for more than the configured idle threshold (default 5 minutes; check `deployment_procedures.md` for an explicit value), treat it as hung — capture a snapshot of what's running on the target, kill the script, and AUTO-ROLLBACK with reason `Deploy hung — manual investigation required`.
|
||||
|
||||
**Manual strategy**: if Phase 2 picked `manual`, write a checklist of operator steps from `deployment_procedures.md` to the release report and pause until the user types `done` or `failed`. Phase 3 then records the user's report verbatim.
|
||||
|
||||
### Phase 4: Smoke Test
|
||||
|
||||
**Goal**: Verify the new version is *actually serving traffic correctly* in the target environment.
|
||||
|
||||
1. Resolve the smoke-test command from `_docs/02_document/tests/blackbox-tests.md` § Production Smoke Tests, OR delegate to `/test-run` in `--prod-smoke` mode against the target environment.
|
||||
2. The smoke-test set must (a) hit each public endpoint of each component, (b) include at least one read AND one write per public endpoint where applicable, and (c) complete in under 5 minutes total.
|
||||
3. Capture pass/fail per case to the release report.
|
||||
4. **AUTO-ROLLBACK trigger**: any smoke-test failure → invoke Phase 6 with verdict `Rolled-Back: smoke test failure: <test-name>`.
|
||||
|
||||
If smoke tests are **missing** for the target environment (no production-mode test set), STOP — write a leftover entry to `_docs/_process_leftovers/` per `tracker.mdc`, do not proceed to watch window without smoke coverage. Write `Aborted: smoke tests missing for prod-mode target` and ASK the user.
|
||||
|
||||
### Phase 5: Watch Window
|
||||
|
||||
**Goal**: Observe the live system for a defined window to catch latent regressions.
|
||||
|
||||
1. Read `observability.md` for the project's metrics, dashboards, and threshold definitions. Required watch metrics for any production target (per cursor-meta convention) include error rate, request rate, p99 latency, and saturation (CPU/memory/queue-depth).
|
||||
2. Compute the watch-window duration from `deployment_procedures.md`. If unspecified, default to **15 minutes** for staging and **60 minutes** for production.
|
||||
3. Poll the observability backend at 1-minute intervals (or the configured cadence). For each interval, record metric snapshots to the release report.
|
||||
4. Threshold rules:
|
||||
- **Hard breach** (auto-rollback): error-rate ≥ 2× baseline, p99 latency ≥ 3× baseline, any health-check failure persisting for 2 consecutive intervals.
|
||||
- **Soft breach** (escalate): metric drift between 1.5× and 2× baseline, single-interval health blip, queue-depth steady but elevated.
|
||||
- **No data** (escalate): if metrics are not flowing within the first 3 minutes, treat the absence as a hard breach — observability is itself broken.
|
||||
5. **AUTO-ROLLBACK trigger**: hard breach at any interval. Move to Phase 6 with verdict `Rolled-Back: <metric> breached <multiplier>× baseline at T+<minutes>`.
|
||||
6. **ESCALATE trigger**: soft breach. Pause polling, surface the metric, and ask the user A/B/C:
|
||||
- A) Continue watch — accept current drift, keep polling
|
||||
- B) Roll back now — treat soft drift as hard
|
||||
- C) Extend watch window by N minutes
|
||||
7. End of watch window with no breach → proceed to Phase 6.
|
||||
|
||||
The watch window cannot be skipped. If the user explicitly demands skipping (e.g., emergency rollforward), record the override reason in the release report and continue, but mark the verdict as `Released-with-override` — this triggers an automatic incident retrospective per `retrospective/SKILL.md`.
|
||||
|
||||
### Phase 6: Commit or Rollback
|
||||
|
||||
**Goal**: Finalize the release with a definitive verdict on disk.
|
||||
|
||||
**Path A — Commit (clean release)**:
|
||||
1. Update tracker tickets: every ticket in scope moves to `Released` (or `Done`, per project convention defined in `tracker.mdc` / `_docs/_repo-config.yaml`).
|
||||
2. Tag the git HEAD with `release/<version>` (or the project's tag convention from `deployment_procedures.md`).
|
||||
3. Write the final `Released` verdict to the release report with a summary table.
|
||||
4. Trigger `/retrospective --cycle-end` with this release as the cycle terminus.
|
||||
5. Auto-chain to autodev's next step (Retrospective in greenfield, or feature-cycle loop start in existing-code).
|
||||
|
||||
**Path B — Rollback (auto-fired or user-elected)**:
|
||||
1. Run `scripts/deploy.sh --rollback` with the rollback target captured in Phase 1.
|
||||
2. Stream output to a new file `RELEASE_DIR/rollback_<version>_<env>_<YYYY-MM-DD-HHmm>.md` AND append a summary to the original release report under `## Rollback`.
|
||||
3. Re-run Phase 4 (smoke test) and a 5-minute mini watch window against the rolled-back version. If THAT also fails, escalate immediately — the system is in an unknown state and needs human takeover.
|
||||
4. Update tracker tickets back to `Ready for Release` (or the project's pre-release status).
|
||||
5. Write the final `Rolled-Back` verdict with full reason chain.
|
||||
6. Auto-trigger `/retrospective --incident` with this release as the incident anchor (per `retrospective/SKILL.md` incident mode).
|
||||
7. Do NOT auto-chain to anything else — the user owns the next step.
|
||||
|
||||
**Path C — Aborted**:
|
||||
Reached only via Phase 1 Choose B, Phase 4 smoke-tests-missing escalation, or any phase that detects a precondition violation. Write `Aborted: <reason>` to the release report. Do not auto-chain.
|
||||
|
||||
## Self-verification
|
||||
|
||||
- [ ] Release report exists at `RELEASE_DIR/release_<version>_<env>_<timestamp>.md` with verdict (Released / Rolled-Back / Aborted)
|
||||
- [ ] Every phase that ran has a section in the release report with timestamps and tool output
|
||||
- [ ] On Released: tracker tickets moved to release status; git tag pushed (if convention)
|
||||
- [ ] On Rolled-Back: rollback report exists at `RELEASE_DIR/rollback_<version>_<env>_<timestamp>.md`; tracker tickets moved back to pre-release status; incident retrospective scheduled
|
||||
- [ ] On Aborted: reason recorded; no live-system changes attempted; no tracker movement
|
||||
- [ ] No phase was skipped without an explicit reason recorded in the release report
|
||||
|
||||
## Escalation Rules
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| `scripts/deploy.sh` missing or `--rollback` unsupported | STOP — return to `/deploy` Step 7, do not patch the script in `/release` |
|
||||
| Registry auth failure during pre-release | STOP — fix credentials at infra layer (per `coderule.mdc`); do not embed creds in the script |
|
||||
| Smoke tests missing for prod target | STOP — write a leftover; do not improvise smoke tests in `/release` |
|
||||
| Observability backend unreachable | STOP — observability blindness is itself a release blocker |
|
||||
| User asks to skip the watch window | Record override, mark verdict `Released-with-override`, fire incident retro |
|
||||
| Rollback also fails its smoke test | ESCALATE to user — system is in unknown state; do not loop deploys |
|
||||
| Tracker MCP returns Unauthorized during ticket movement | Per `tracker.mdc`, write a leftover entry; do NOT silently continue without confirming the move |
|
||||
| Multiple environments named in user request | STOP — one release per invocation; ask user to pick one |
|
||||
| Production smoke test would touch real customer data | STOP — that is a `coderule.mdc` violation; ask user to define a smoke endpoint or test account |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- **Skipping the watch window when "everything looks fine after deploy"** — a deploy that exited 0 is not a release that's stable. Watch is mandatory.
|
||||
- **Faking smoke tests** to pass the gate when the prod test set is incomplete. STOP and surface the gap; do not embed prod URLs into ad-hoc curl commands.
|
||||
- **Rolling forward through a failure** ("the next deploy will fix it"). Roll back first, fix the cause, then deploy a real fix.
|
||||
- **Treating the release report as optional** when only an internal tool changed. Every release writes a report — the audit trail is the value, not the prose volume.
|
||||
- **Approving manual gates yourself** without the user's input when restrictions require human approval. The release skill records, the human approves.
|
||||
- **Reusing `release_<version>` filenames** across attempted releases. Always include the timestamp in the filename so re-attempts are visible side-by-side.
|
||||
- **Letting tracker drift silently** between release attempts. If Phase 6 cannot move tickets, the release is not complete — write a leftover and stop.
|
||||
|
||||
## Project Mode vs Standalone
|
||||
|
||||
- **Project mode** (default): autodev invokes `/release` after `/deploy`. State writes occur under `_docs/_autodev_state.md`. Full integration with retrospective and feature-cycle loop.
|
||||
- **Standalone mode**: `/release` invoked directly with `@<artifact>` (rare; usually only for re-running a rollback against a specific version). All outputs still go to `RELEASE_DIR/`.
|
||||
|
||||
## Methodology Quick Reference
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ Release (6 phases, 3 verdicts) │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ Phase 1 Pre-Release Gate │
|
||||
│ AC + tests + change summary + rollback path │
|
||||
│ [BLOCKING — user A/B/C] │
|
||||
│ Phase 2 Strategy Select │
|
||||
│ all-at-once · blue-green · canary · manual │
|
||||
│ [BLOCKING — user picks] │
|
||||
│ Phase 3 Execute │
|
||||
│ scripts/deploy.sh, capture exit code + logs │
|
||||
│ [AUTO-ROLLBACK on non-zero or hang] │
|
||||
│ Phase 4 Smoke Test │
|
||||
│ /test-run --prod-smoke against target │
|
||||
│ [AUTO-ROLLBACK on any failure] │
|
||||
│ Phase 5 Watch Window │
|
||||
│ Poll observability for N minutes │
|
||||
│ [AUTO-ROLLBACK on hard breach; escalate on soft] │
|
||||
│ Phase 6 Commit or Rollback │
|
||||
│ Released → tracker, tag, retrospective │
|
||||
│ Rolled-Back → tracker reset, incident retrospective │
|
||||
│ Aborted → no live-system change │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ Principles: real execution · verifiable rollback · │
|
||||
│ quiet failure = release failure · │
|
||||
│ watch window mandatory │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
@@ -0,0 +1,114 @@
|
||||
# Release Report — {version} → {env}
|
||||
|
||||
- **Date**: {YYYY-MM-DD HH:MM} {timezone}
|
||||
- **Operator**: {user}
|
||||
- **Strategy**: {all-at-once | blue-green | canary | manual}
|
||||
- **Verdict**: {Released | Released-with-override | Rolled-Back | Aborted}
|
||||
- **Verdict reason**: {one-line summary}
|
||||
|
||||
## Pre-Release Gate (Phase 1)
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
| AC ID | Status | Evidence |
|
||||
|-------|--------|----------|
|
||||
| AC-001 | Met / Unmet | path:section, test report, etc. |
|
||||
|
||||
### Test Status
|
||||
|
||||
| Suite | Pass | Fail | Skip | Source |
|
||||
|-------|------|------|------|--------|
|
||||
| Functional | N | N | N | _docs/03_implementation/{batch}.md |
|
||||
| Performance | N | N | N | _docs/06_metrics/perf_*.md |
|
||||
|
||||
### Change Summary
|
||||
|
||||
| Component | Tickets | Type |
|
||||
|-----------|---------|------|
|
||||
| {component} | TKT-001, TKT-002 | feature / fix / breaking / security |
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
- Previous version: `{previous-version}` (registry digest: `{sha}`)
|
||||
- Rollback script: `scripts/deploy.sh --rollback`
|
||||
- Rollback target verified pullable: yes / no
|
||||
- Rollback target verified bootable in target env: yes / no
|
||||
|
||||
### Restrictions / Approvals
|
||||
|
||||
- Change-window restrictions: {none | description}
|
||||
- Manual approvals required: {none | reference to approval file}
|
||||
|
||||
### Tracker State at Gate
|
||||
|
||||
- Tickets in scope: {N}
|
||||
- Tickets blocking release: {0 — list any}
|
||||
|
||||
## Strategy Select (Phase 2)
|
||||
|
||||
- Recommended: {strategy} — reasoning
|
||||
- Chosen: {strategy} — reasoning (if differs from recommended)
|
||||
|
||||
## Execute (Phase 3)
|
||||
|
||||
- Start: {timestamp}
|
||||
- End: {timestamp}
|
||||
- Exit code: {0 / non-zero}
|
||||
|
||||
```
|
||||
<scripts/deploy.sh stdout/stderr stream, with timestamps>
|
||||
```
|
||||
|
||||
## Smoke Test (Phase 4)
|
||||
|
||||
- Mode: {/test-run --prod-smoke | manual smoke set}
|
||||
- Start: {timestamp}
|
||||
- End: {timestamp}
|
||||
|
||||
| Test | Result | Notes |
|
||||
|------|--------|-------|
|
||||
| {name} | Pass / Fail | response time, status, etc. |
|
||||
|
||||
## Watch Window (Phase 5)
|
||||
|
||||
- Duration: {minutes}
|
||||
- Cadence: {minutes per poll}
|
||||
- Backend: {observability source — Prometheus, CloudWatch, Datadog, etc.}
|
||||
|
||||
| T+min | error_rate | rps | p99_latency | saturation | health | notes |
|
||||
|-------|------------|-----|-------------|------------|--------|-------|
|
||||
| 0 | … | … | … | … | OK | … |
|
||||
| 1 | … | … | … | … | OK | … |
|
||||
| … | … | … | … | … | … | … |
|
||||
|
||||
### Threshold breaches
|
||||
|
||||
- {None | "p99 latency 1.7× baseline at T+8 — soft breach, user accepted continuation"}
|
||||
|
||||
## Commit or Rollback (Phase 6)
|
||||
|
||||
### If Released
|
||||
|
||||
- Tracker tickets moved: {list}
|
||||
- Git tag pushed: {tag} → {sha}
|
||||
- Retrospective scheduled: yes — {/retrospective --cycle-end output path}
|
||||
|
||||
### If Rolled-Back
|
||||
|
||||
- Trigger: {auto / user-elected}
|
||||
- Reason: {phase + one-line cause}
|
||||
- Rollback start: {timestamp}
|
||||
- Rollback end: {timestamp}
|
||||
- Post-rollback smoke: pass / fail
|
||||
- Tracker tickets moved back: {list}
|
||||
- Incident retrospective scheduled: yes — {/retrospective --incident output path}
|
||||
|
||||
### If Aborted
|
||||
|
||||
- Phase that aborted: {1 / 2 / 3 / 4 / 5}
|
||||
- Reason: {one-line cause}
|
||||
- No live-system changes attempted: yes / no (if live changes, document under Phase 3 above and treat as Rolled-Back instead)
|
||||
|
||||
## Lessons (one-liners; full incident retro if Rolled-Back / Released-with-override)
|
||||
|
||||
- {Optional: short one-liner observations the operator wants the next /retrospective to consider}
|
||||
@@ -45,7 +45,7 @@
|
||||
- [ ] All components have comparison tables: Each component lists alternatives with tools, advantages, limitations, security, cost
|
||||
- [ ] Component options are broad: component tables include baseline, production, open-source, commercial/vendor, SOTA/research, adjacent-domain, defer/no-build, and disqualified options where applicable
|
||||
- [ ] Tools/libraries verified: Suggested tools actually exist and work as described
|
||||
- [ ] Component fit matrix completed: `06_component_fit_matrix.md` exists and every selected component/tool/pattern is marked `Selected`
|
||||
- [ ] Component fit matrix completed: `06_component_fit_matrix.md` (or `06_component_fit_matrix/` if split) exists and every selected component/tool/pattern is marked `Selected`
|
||||
- [ ] No field-adjacent substitution: no selected candidate is chosen only because it solves a similar class of problem while failing the project's explicit constraints
|
||||
- [ ] Testing strategy covers AC: Tests map to acceptance criteria
|
||||
- [ ] Tech stack documented (if Phase 3 ran): `tech_stack.md` has evaluation tables, risk assessment, and learning requirements
|
||||
@@ -80,7 +80,7 @@ When the research topic has Critical or High sensitivity level:
|
||||
## Target Audience Consistency Check (BLOCKING)
|
||||
|
||||
- [ ] Research boundary clearly defined: `00_question_decomposition.md` has clear population/geography/timeframe/level boundaries
|
||||
- [ ] Every source has target audience annotated in `01_source_registry.md`
|
||||
- [ ] Every source has target audience annotated in `01_source_registry.md` (or category files under `01_source_registry/` if split)
|
||||
- [ ] Mismatched sources properly handled (excluded, annotated, or marked reference-only)
|
||||
- [ ] No audience confusion in fact cards: Every fact has target audience consistent with research boundary
|
||||
- [ ] No audience confusion in the report: Policies/research/data cited have consistent target audiences
|
||||
@@ -113,11 +113,11 @@ For every lead candidate that is a library/SDK/framework/service:
|
||||
|
||||
- [ ] The exact mode/configuration the project will use is pinned in one explicit sentence (inputs, outputs, runtime); no vague "supports X" language
|
||||
- [ ] `context7` (or equivalent docs lookup) was run for the candidate, with at least 3 queries: mode enumeration, project's exact mode, disqualifier probe
|
||||
- [ ] All consulted URLs from context7 / official docs are appended to `01_source_registry.md`
|
||||
- [ ] A Minimum Viable Example (MVE) was saved for the pinned mode in `02_fact_cards.md` (or `02_mve_evidence.md`) with: source, inputs in example, outputs in example, project inputs, project outputs required, match assessment ✅/⚠️/❌
|
||||
- [ ] All consulted URLs from context7 / official docs are appended to `01_source_registry.md` (or files under `01_source_registry/` if split)
|
||||
- [ ] A Minimum Viable Example (MVE) was saved for the pinned mode in `02_fact_cards.md` / `02_fact_cards/` (or `02_mve_evidence.md`) with: source, inputs in example, outputs in example, project inputs, project outputs required, match assessment ✅/⚠️/❌
|
||||
- [ ] When the MVE inputs or outputs do not exactly match the project's, the mismatch is cited from the official docs (not inferred), and the candidate is `Experimental only` or `Rejected`
|
||||
- [ ] When a library has multiple modes, each project-relevant mode appears as its own candidate row (not a single library row that softens across modes)
|
||||
- [ ] Restrictions × Candidate-Modes sub-matrix in `06_component_fit_matrix.md` is filled for every lead candidate, with one row per numbered restriction and per numbered acceptance criterion
|
||||
- [ ] Restrictions × Candidate-Modes sub-matrix in `06_component_fit_matrix.md` (or files under `06_component_fit_matrix/` if split) is filled for every lead candidate, with one row per numbered restriction and per numbered acceptance criterion
|
||||
- [ ] Sub-matrix uses ✅ / ❌ / ❓ / N/A only — no free-form prose substitutes
|
||||
- [ ] No `Selected` candidate has any ❌ or ❓ cell in its sub-matrix
|
||||
- [ ] "Validation gate required" footnotes are explicitly classified as either *API capability* (must be resolved here) or *runtime quality* (may be carried forward)
|
||||
|
||||
@@ -89,7 +89,7 @@ Value Translation:
|
||||
|
||||
## Source Registry Entry Template
|
||||
|
||||
For each source consulted, immediately append to `01_source_registry.md`:
|
||||
For each source consulted, immediately append to `01_source_registry.md` (or the appropriate category file under `01_source_registry/` if the artifact has been split — see splittable-artifacts convention in `steps/00_project-integration.md`):
|
||||
```markdown
|
||||
## Source #[number]
|
||||
- **Title**: [source title]
|
||||
|
||||
@@ -63,18 +63,43 @@ RESEARCH_DIR/
|
||||
└── source_2.md
|
||||
```
|
||||
|
||||
#### Splittable artifacts — Layout convention
|
||||
|
||||
The following three artifacts MAY equivalently be a **folder** of the same base name when the single-file form has grown unwieldy (typically ≳ 1000 lines or ≳ 200 KB):
|
||||
|
||||
- `01_source_registry.md` ↔ `01_source_registry/`
|
||||
- `02_fact_cards.md` ↔ `02_fact_cards/`
|
||||
- `06_component_fit_matrix.md` ↔ `06_component_fit_matrix/`
|
||||
|
||||
When using the folder form:
|
||||
|
||||
- Place a `00_summary.md` index file at the folder root with a short common summary table and the cross-cutting status the single-file form would have carried in its preamble.
|
||||
- Split per-entry content into category files (e.g. one file per sub-question or per component): `SQ1_*.md`, `C1_*.md`, etc. Keep entry numbering global across the folder so cross-references like "Source #42" still resolve to exactly one place.
|
||||
- Cross-references from outside the folder may point at either `01_source_registry/00_summary.md` (for the index) or directly at the relevant category file.
|
||||
|
||||
```
|
||||
RESEARCH_DIR/01_source_registry/ # split form (when single-file is too large)
|
||||
├── 00_summary.md # index + investigation status + compact source table
|
||||
├── SQ1_existing_systems.md # category file
|
||||
├── SQ2_canonical_pipeline.md # category file
|
||||
├── C1_vio.md # per-component file
|
||||
└── ...
|
||||
```
|
||||
|
||||
Throughout the rest of this skill (other steps, references, templates), the singular `XX.md` form is used as a logical name; treat each occurrence as applying equally to the folder form when the artifact has been split.
|
||||
|
||||
### Save Timing & Content
|
||||
|
||||
| Step | Save immediately after completion | Filename |
|
||||
|------|-----------------------------------|----------|
|
||||
| Mode A Phase 1 | AC & restrictions assessment tables | `00_ac_assessment.md` |
|
||||
| Step 0-1 | Question type classification + sub-question list | `00_question_decomposition.md` |
|
||||
| Step 2 | Each consulted source link, tier, summary | `01_source_registry.md` |
|
||||
| Step 3 | Each fact card (statement + source + confidence) | `02_fact_cards.md` |
|
||||
| Step 2 | Each consulted source link, tier, summary | `01_source_registry.md` *(splittable, see convention)* |
|
||||
| Step 3 | Each fact card (statement + source + confidence) | `02_fact_cards.md` *(splittable, see convention)* |
|
||||
| Step 4 | Selected comparison framework + initial population | `03_comparison_framework.md` |
|
||||
| Step 6 | Reasoning process for each dimension | `04_reasoning_chain.md` |
|
||||
| Step 7 | Validation scenarios + results + review checklist | `05_validation_log.md` |
|
||||
| Step 7.5 | Component exact-fit gate and selection status | `06_component_fit_matrix.md` |
|
||||
| Step 7.5 | Component exact-fit gate and selection status | `06_component_fit_matrix.md` *(splittable, see convention)* |
|
||||
| Step 8 | Complete solution draft | `OUTPUT_DIR/solution_draft##.md` |
|
||||
|
||||
### Save Principles
|
||||
@@ -92,12 +117,12 @@ RESEARCH_DIR/
|
||||
|------|---------|----------------|
|
||||
| `00_ac_assessment.md` | AC & restrictions assessment (Mode A only) | After Phase 1 completion |
|
||||
| `00_question_decomposition.md` | Question type, sub-question list | After Step 0-1 completion |
|
||||
| `01_source_registry.md` | All source links and summaries | Continuously updated during Step 2 |
|
||||
| `02_fact_cards.md` | Extracted facts and sources | Continuously updated during Step 3 |
|
||||
| `01_source_registry.md` *(splittable)* | All source links and summaries | Continuously updated during Step 2 |
|
||||
| `02_fact_cards.md` *(splittable)* | Extracted facts and sources | Continuously updated during Step 3 |
|
||||
| `03_comparison_framework.md` | Selected framework and populated data | After Step 4 completion |
|
||||
| `04_reasoning_chain.md` | Fact → conclusion reasoning | After Step 6 completion |
|
||||
| `05_validation_log.md` | Use-case validation and review | After Step 7 completion |
|
||||
| `06_component_fit_matrix.md` | Exact-fit matrix for every proposed component/tool/pattern with status `Selected` / `Rejected` / `Experimental only` / `Needs user decision` | Before Step 8 deliverable formatting |
|
||||
| `06_component_fit_matrix.md` *(splittable)* | Exact-fit matrix for every proposed component/tool/pattern with status `Selected` / `Rejected` / `Experimental only` / `Needs user decision` | Before Step 8 deliverable formatting |
|
||||
| `OUTPUT_DIR/solution_draft##.md` | Complete solution draft | After Step 8 completion |
|
||||
| `OUTPUT_DIR/tech_stack.md` | Tech stack evaluation and decisions | After Phase 3 (optional) |
|
||||
| `OUTPUT_DIR/security_analysis.md` | Threat model and security controls | After Phase 4 (optional) |
|
||||
|
||||
@@ -6,7 +6,9 @@ Triggered when no `solution_draft*.md` files exist in OUTPUT_DIR, or when the us
|
||||
|
||||
**Role**: Professional software architect
|
||||
|
||||
A focused preliminary research pass **before** the main solution research. The goal is to validate that the acceptance criteria and restrictions are realistic before designing a solution around them.
|
||||
> **AC must be design-independent**: describe testable outcomes only — no libraries, algorithms, params, or design choices. Implementation follows AC, never reverse. (IEEE 830 / Atlassian / GitScrum)
|
||||
|
||||
A focused preliminary research pass **before** the main solution research. The goal is to validate that the acceptance criteria and restrictions are realistic before designing a solution around them. Any revision proposed in this phase must respect the design-independence rule above — propose AC changes as outcome/budget edits, not as implementation prescriptions.
|
||||
|
||||
**Input**: All files from INPUT_DIR (or INPUT_FILE in standalone mode)
|
||||
|
||||
@@ -84,7 +86,7 @@ Full 8-step research methodology. Produces the first solution draft.
|
||||
|
||||
Be concise in formulating. The fewer words, the better, but do not miss any important details.
|
||||
|
||||
**Save action**: Write `RESEARCH_DIR/06_component_fit_matrix.md` before the final draft, then write `OUTPUT_DIR/solution_draft##.md` using template: `templates/solution_draft_mode_a.md`
|
||||
**Save action**: Write `RESEARCH_DIR/06_component_fit_matrix.md` (or its split-folder equivalent under `RESEARCH_DIR/06_component_fit_matrix/`, per the splittable-artifacts convention in `00_project-integration.md`) before the final draft, then write `OUTPUT_DIR/solution_draft##.md` using template: `templates/solution_draft_mode_a.md`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -29,6 +29,6 @@ Full 8-step research methodology applied to assessing and improving an existing
|
||||
9. For every revised candidate, prove exact fit against the Project Constraint Matrix. Do not select field-adjacent or "similar problem" options unless their intrinsic implementation constraints match the project.
|
||||
10. Based on findings, form a new solution draft in the same format
|
||||
|
||||
**Save action**: Write `RESEARCH_DIR/06_component_fit_matrix.md` before the final draft, then write `OUTPUT_DIR/solution_draft##.md` (incremented) using template: `templates/solution_draft_mode_b.md`
|
||||
**Save action**: Write `RESEARCH_DIR/06_component_fit_matrix.md` (or its split-folder equivalent under `RESEARCH_DIR/06_component_fit_matrix/`, per the splittable-artifacts convention in `00_project-integration.md`) before the final draft, then write `OUTPUT_DIR/solution_draft##.md` (incremented) using template: `templates/solution_draft_mode_b.md`
|
||||
|
||||
**Optional follow-up**: After Mode B completes, the user can request Phase 3 (Tech Stack Consolidation) or Phase 4 (Security Deep Dive) using the revised draft. These phases work identically to their Mode A descriptions in `steps/01_mode-a-initial-research.md`.
|
||||
|
||||
@@ -192,7 +192,7 @@ For every component/tool/library/service/pattern/algorithm that may be selected
|
||||
|
||||
**API Capability Verification — Per-Mode (MANDATORY, BLOCKING for lead candidates)**:
|
||||
|
||||
**Applicability**: this section applies only when the run is classified as **Technical-component selection** in the SKILL's Research Output Class section, and only to lead candidates that are libraries/SDKs/frameworks/services/protocols/data formats with multiple modes or configurations. For non-technical research (concept comparison, market/policy investigation, knowledge organization, root-cause analysis without tooling commitments), skip this entire sub-section and continue with the rest of Step 2 — the broader candidate implementation-limit search above is sufficient. State the skip explicitly once in `02_fact_cards.md`: `API Capability Verification: not applicable — this run is a Non-technical investigation, no library/SDK/service candidates`.
|
||||
**Applicability**: this section applies only when the run is classified as **Technical-component selection** in the SKILL's Research Output Class section, and only to lead candidates that are libraries/SDKs/frameworks/services/protocols/data formats with multiple modes or configurations. For non-technical research (concept comparison, market/policy investigation, knowledge organization, root-cause analysis without tooling commitments), skip this entire sub-section and continue with the rest of Step 2 — the broader candidate implementation-limit search above is sufficient. State the skip explicitly once in `02_fact_cards.md` (or in `02_fact_cards/00_summary.md` if split): `API Capability Verification: not applicable — this run is a Non-technical investigation, no library/SDK/service candidates`.
|
||||
|
||||
Most libraries/SDKs/services expose **multiple modes or configurations** (e.g., monocular vs stereo VO, sync vs async API, batch vs streaming inference, write-through vs write-behind cache). Selecting a candidate "because it supports X" without pinning *which mode* the project will use, and *whether that exact mode produces the required outputs from the required inputs*, is the most common silent-failure path in research. A library can support a class of problem in mode A while being unusable for the project's specific configuration in mode B.
|
||||
|
||||
@@ -206,10 +206,10 @@ For every lead candidate that is a library/SDK/framework/service with multiple m
|
||||
2. *Project's exact mode*: "Show a minimum runnable example of `<library>` in `<the pinned mode>` with `<the project's input shape>`. What does it produce?"
|
||||
3. *Disqualifier probe*: "Does `<library>` `<the pinned mode>` produce `<the required output>`? Are there published limitations of `<the pinned mode>` for `<the project's runtime/hardware>`?"
|
||||
|
||||
For services without context7 coverage, use official docs site + WebFetch on the API reference page + the project's example/tutorial directory in the source repo. Append every consulted URL to `01_source_registry.md`.
|
||||
For services without context7 coverage, use official docs site + WebFetch on the API reference page + the project's example/tutorial directory in the source repo. Append every consulted URL to `01_source_registry.md` (or the appropriate category file under `01_source_registry/` if split — see splittable-artifacts convention in `00_project-integration.md`).
|
||||
|
||||
3. **Save a Minimum Viable Example (MVE) for the pinned mode.**
|
||||
Append to `02_fact_cards.md` (or a sibling `02_mve_evidence.md`) at least one block per lead library candidate with:
|
||||
Append to `02_fact_cards.md` / `02_fact_cards/` (or a sibling `02_mve_evidence.md`) at least one block per lead library candidate with:
|
||||
|
||||
```markdown
|
||||
## MVE — <library> in <pinned mode>
|
||||
@@ -225,7 +225,7 @@ For every lead candidate that is a library/SDK/framework/service with multiple m
|
||||
If no official example covers the project's exact configuration → the candidate cannot be marked `Selected` based on category fit alone. Status must be `Experimental only` (with required-evidence note) or `Rejected` (when the docs explicitly disqualify the configuration).
|
||||
|
||||
4. **Bind every numbered Restriction and Acceptance Criterion to the candidate's pinned mode.**
|
||||
For each numbered line in `restrictions.md` and `acceptance_criteria.md`, decide one of: `Pass` (the pinned mode satisfies it with cited evidence), `Fail` (the pinned mode contradicts it with cited evidence), `Verify` (no evidence either way; deeper investigation required), `N/A` (the line is irrelevant to this component area). Record this in `02_fact_cards.md` under the candidate's MVE block. The structural matrix in Step 7.5 reads from these bindings.
|
||||
For each numbered line in `restrictions.md` and `acceptance_criteria.md`, decide one of: `Pass` (the pinned mode satisfies it with cited evidence), `Fail` (the pinned mode contradicts it with cited evidence), `Verify` (no evidence either way; deeper investigation required), `N/A` (the line is irrelevant to this component area). Record this in `02_fact_cards.md` (or the candidate's per-component file under `02_fact_cards/` if split) under the candidate's MVE block. The structural matrix in Step 7.5 reads from these bindings.
|
||||
|
||||
5. **Treat "the same library in a different mode" as a different candidate.**
|
||||
If the project's pinned mode is `Monocular` but the only documented evidence covers `Stereo`, do not silently soften "rotation only" into "rotation + translation". Open a separate candidate row for the Monocular mode, with its own MVE, fit assessment, and disqualifiers. Two modes of one library are two distinct candidates for the purposes of this gate.
|
||||
@@ -243,7 +243,7 @@ For every lead candidate that is a library/SDK/framework/service with multiple m
|
||||
**Search saturation rule**: Continue searching until new queries stop producing substantially new information. If the last 3 searches only repeat previously found facts, the sub-question is saturated.
|
||||
|
||||
**Save action**:
|
||||
For each source consulted, **immediately** append to `01_source_registry.md` using the entry template from `references/source-tiering.md`.
|
||||
For each source consulted, **immediately** append to `01_source_registry.md` (or the appropriate category file under `01_source_registry/` if split) using the entry template from `references/source-tiering.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -273,7 +273,7 @@ Transform sources into **verifiable fact cards**:
|
||||
- ❓ Low: Inference or from unofficial sources
|
||||
|
||||
**Save action**:
|
||||
For each extracted fact, **immediately** append to `02_fact_cards.md`:
|
||||
For each extracted fact, **immediately** append to `02_fact_cards.md` (or the appropriate category file under `02_fact_cards/` if split):
|
||||
```markdown
|
||||
## Fact #[number]
|
||||
- **Statement**: [specific fact description]
|
||||
@@ -318,7 +318,7 @@ After initial fact extraction, review what you have found and identify **knowled
|
||||
- Failure cases and edge conditions
|
||||
- Recent developments that may change the picture
|
||||
|
||||
4. **Update artifacts**: Append new sources to `01_source_registry.md`, new facts to `02_fact_cards.md`
|
||||
4. **Update artifacts**: Append new sources to `01_source_registry.md`, new facts to `02_fact_cards.md` (use the appropriate category files under `01_source_registry/` and `02_fact_cards/` if split)
|
||||
|
||||
**Exit criteria**: Proceed to Step 4 when:
|
||||
- Every sub-question has at least 3 facts with at least one from L1/L2
|
||||
|
||||
@@ -155,7 +155,7 @@ Before finalizing the solution draft, build an exact-fit matrix for every compon
|
||||
|
||||
| Component Area | Candidate | Pinned Mode/Config | Option Family | Intended Role | API Capability Evidence | Mismatches / Disqualifiers | Status | Decision Rationale |
|
||||
|----------------|-----------|--------------------|---------------|---------------|-------------------------|----------------------------|--------|--------------------|
|
||||
| [area] | [name] | [exact mode/config the project will use, copied verbatim from the MVE block in Step 2] | [family] | [role] | MVE: [link to MVE block in `02_fact_cards.md` or `02_mve_evidence.md`]; docs: [Source #] | [none / list] | Selected / Rejected / Experimental only / Needs user decision | [why] |
|
||||
| [area] | [name] | [exact mode/config the project will use, copied verbatim from the MVE block in Step 2] | [family] | [role] | MVE: [link to MVE block in `02_fact_cards.md` / `02_fact_cards/` or `02_mve_evidence.md`]; docs: [Source #] | [none / list] | Selected / Rejected / Experimental only / Needs user decision | [why] |
|
||||
```
|
||||
|
||||
The new **Pinned Mode/Config** column is mandatory. A row without a pinned mode is incomplete. The new **API Capability Evidence** column links to the Minimum Viable Example saved during Step 2's API Capability Verification — without an MVE link the candidate cannot be `Selected`.
|
||||
@@ -196,7 +196,7 @@ A candidate row may not be marked `Selected` while any cell is ❌ or ❓.
|
||||
- A candidate may not appear as the lead solution in Step 8 unless this gate marks it `Selected`.
|
||||
- "Validation gate required" footnotes are not equivalent to `Selected`. If the validation gate concerns API capability (does the mode produce the required output?), that is a Step-2 / Step-7.5 question and must be resolved here, not deferred to runtime. Only validation gates concerning *runtime quality* (e.g., "does this VO converge on this terrain class?") may be carried forward as `Selected with runtime gate`.
|
||||
|
||||
**Save action**: Write `06_component_fit_matrix.md` containing both 7.5.1 (top-level) and 7.5.2 (per-candidate sub-matrices).
|
||||
**Save action**: Write `06_component_fit_matrix.md` (or, when split, the equivalent files under `06_component_fit_matrix/` — typically `00_summary.md` for the top-level matrix plus per-component sub-matrix files) containing both 7.5.1 (top-level) and 7.5.2 (per-candidate sub-matrices).
|
||||
|
||||
**BLOCKING**: If any lead candidate has ❌, ❓, `Experimental only`, `Rejected`, or `Needs user decision` status, do not silently proceed. Ask the user or choose a different selected candidate.
|
||||
|
||||
@@ -213,8 +213,8 @@ Integrate all intermediate artifacts. Write to `OUTPUT_DIR/solution_draft##.md`
|
||||
|
||||
Sources to integrate:
|
||||
- Extract background from `00_question_decomposition.md`
|
||||
- Reference key facts from `02_fact_cards.md`
|
||||
- Reference key facts from `02_fact_cards.md` (or files under `02_fact_cards/` if split)
|
||||
- Organize conclusions from `04_reasoning_chain.md`
|
||||
- Generate references from `01_source_registry.md`
|
||||
- Generate references from `01_source_registry.md` (or files under `01_source_registry/` if split)
|
||||
- Supplement with use cases from `05_validation_log.md`
|
||||
- For Mode A: include AC assessment from `00_ac_assessment.md`
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
- Project constraints checked: [inputs/outputs, operating context, lifecycle, NFRs, acceptance criteria]
|
||||
- Evidence: [Fact # / Source #]
|
||||
- Disqualifiers: [none or list]
|
||||
- Restrictions × Candidate-Modes sub-matrix: see `06_component_fit_matrix.md` § <Candidate Name>
|
||||
- Restrictions × Candidate-Modes sub-matrix: see `06_component_fit_matrix.md` (or `06_component_fit_matrix/` if split) § <Candidate Name>
|
||||
- API capability gates: ✅ MVE saved / ⚠️ partial — see disqualifiers / ❌ no MVE — candidate is Experimental only or Rejected
|
||||
|
||||
[Repeat per component]
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- Project constraints checked: [inputs/outputs, operating context, lifecycle, NFRs, acceptance criteria]
|
||||
- Evidence: [Fact # / Source #]
|
||||
- Disqualifiers: [none or list]
|
||||
- Restrictions × Candidate-Modes sub-matrix: see `06_component_fit_matrix.md` § <Candidate Name>
|
||||
- Restrictions × Candidate-Modes sub-matrix: see `06_component_fit_matrix.md` (or `06_component_fit_matrix/` if split) § <Candidate Name>
|
||||
- API capability gates: ✅ MVE saved / ⚠️ partial — see disqualifiers / ❌ no MVE — candidate is Experimental only or Rejected
|
||||
|
||||
[Repeat per component]
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
name: retrospective
|
||||
description: |
|
||||
Collect metrics from implementation batch reports and code review findings, analyze trends across cycles,
|
||||
and produce improvement reports with actionable recommendations.
|
||||
3-step workflow: collect metrics, analyze trends, produce report.
|
||||
Outputs to _docs/06_metrics/.
|
||||
and produce improvement reports plus a lessons-log update with actionable recommendations.
|
||||
4-step workflow: collect metrics, analyze trends, produce report, update lessons log.
|
||||
Outputs to _docs/06_metrics/ and appends to _docs/LESSONS.md (ring buffer, last 15).
|
||||
Trigger phrases:
|
||||
- "retrospective", "retro", "run retro"
|
||||
- "metrics review", "feedback loop"
|
||||
@@ -232,7 +232,7 @@ Present the report summary to the user.
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ Retrospective (3-Step Method) │
|
||||
│ Retrospective (4-Step Method) │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ PREREQ: batch reports exist in _docs/03_implementation/ │
|
||||
│ │
|
||||
|
||||
@@ -32,6 +32,17 @@ After selecting a mode, read its corresponding workflow below; do not mix them.
|
||||
|
||||
## Functional Mode
|
||||
|
||||
### 0. System-Under-Test Reality Gate
|
||||
|
||||
Before accepting any functional, blackbox, or e2e result as a pass, verify what the tests actually exercised.
|
||||
|
||||
1. If `_docs/00_problem/input_data/expected_results/results_report.md` exists, at least one e2e/blackbox run must compare actual product outputs against that mapping or the machine-readable files it references.
|
||||
2. Stubs are allowed only for external systems outside the product boundary: flight controller/SITL, QGC observer, satellite-provider/Suite service, physical Jetson hardware, physical camera, unavailable licensed datasets, and network services.
|
||||
3. Stubs, fakes, deterministic fallbacks, monkeypatches, or direct replacement of internal product modules are not allowed for the behavior under test. Internal examples include VIO, safety/anchor wrapper, satellite retrieval, anchor verification, tile manager, MAVLink output adapter, FDR, and the A-Z localization pipeline.
|
||||
4. If tests pass only because an internal module is fake/scaffolded, classify the run as **failed** with category `missing product implementation`.
|
||||
5. If a scenario is blocked because external hardware/data is absent, verify the production code path exists before accepting the block as legitimate. Missing internal production code is not an environment block.
|
||||
6. If the test runner writes CSV/Markdown reports, inspect them. A zero exit code is not enough; blocked/internal-stubbed scenarios still require classification.
|
||||
|
||||
### 1. Detect Test Runner
|
||||
|
||||
Check in order — first match wins:
|
||||
@@ -94,7 +105,7 @@ Categorize skips as: **explicit skip (dead code)**, **runtime skip (unreachable)
|
||||
|
||||
### 5. Handle Outcome
|
||||
|
||||
**All tests pass, zero skipped** → return success to the autodev for auto-chain.
|
||||
**All tests pass, zero skipped, and the System-Under-Test Reality Gate passes** → return success to the autodev for auto-chain.
|
||||
|
||||
**Any test fails or errors** → this is a **blocking gate**. Never silently ignore failures. **Always investigate the root cause before deciding on an action.** Read the failing test code, read the error output, check service logs if applicable, and determine whether the bug is in the test or in the production code.
|
||||
|
||||
|
||||
@@ -202,12 +202,12 @@ If invoked in `cycle-update` mode (see "Invocation Modes" above), read and follo
|
||||
| Missing acceptance_criteria.md, restrictions.md, or input_data/ | **STOP** — specification cannot proceed |
|
||||
| Missing input_data/expected_results/results_report.md | **STOP** — ask user to provide expected results mapping using the template |
|
||||
| Ambiguous requirements | ASK user |
|
||||
| Input data coverage below 75% (Phase 1) | Search internet for supplementary data, ASK user to validate |
|
||||
| Input data coverage below the canonical threshold (Phase 1) | Search internet for supplementary data, ASK user to validate. See `.cursor/rules/cursor-meta.mdc` Quality Thresholds for the canonical 75% number — do not hardcode a different threshold here. |
|
||||
| Expected results missing or not quantifiable (Phase 1) | ASK user to provide quantifiable expected results before proceeding |
|
||||
| Test scenario conflicts with restrictions | ASK user to clarify intent |
|
||||
| System interfaces unclear (no architecture.md) | ASK user or derive from solution.md |
|
||||
| Test data or expected result not provided for a test scenario (Phase 3) | WARN user and REMOVE the test |
|
||||
| Final coverage below 75% after removals (Phase 3) | BLOCK — require user to supply data or accept reduced spec |
|
||||
| Final coverage below the canonical threshold after removals (Phase 3) | BLOCK — require user to supply data or accept reduced spec (see `cursor-meta.mdc` Quality Thresholds) |
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
@@ -252,7 +252,8 @@ When the user wants to:
|
||||
│ │
|
||||
│ Phase 3: Test Data & Expected Results Validation Gate (HARD GATE) │
|
||||
│ → phases/03-data-validation-gate.md │
|
||||
│ [BLOCKING: coverage ≥ 75% required to pass] │
|
||||
│ [BLOCKING: coverage ≥ canonical threshold required to pass — │
|
||||
│ see cursor-meta.mdc Quality Thresholds (75%)] │
|
||||
│ │
|
||||
│ Hardware-Dependency Assessment (BLOCKING, pre-Phase-4) │
|
||||
│ → phases/hardware-assessment.md │
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Phase 3: Test Data & Expected Results Validation Gate (HARD GATE)
|
||||
|
||||
**Role**: Professional Quality Assurance Engineer
|
||||
**Goal**: Ensure every test scenario produced in Phase 2 has concrete, sufficient test data. Remove tests that lack data. Verify final coverage stays above 75%.
|
||||
**Goal**: Ensure every test scenario produced in Phase 2 has concrete, sufficient test data. Remove tests that lack data. Verify final coverage stays above the canonical threshold (currently 75% — see `.cursor/rules/cursor-meta.mdc` Quality Thresholds; never hardcode a different number in any phase).
|
||||
**Constraints**: This phase is MANDATORY and cannot be skipped.
|
||||
|
||||
## Step 1 — Build the requirements checklist
|
||||
|
||||
+29
-27
@@ -1,27 +1,29 @@
|
||||
.git
|
||||
.github
|
||||
.cursor
|
||||
_docs
|
||||
.venv
|
||||
__pycache__
|
||||
.pytest_cache
|
||||
.ruff_cache
|
||||
.mypy_cache
|
||||
.env
|
||||
.env.*
|
||||
*.pem
|
||||
*.key
|
||||
*.secret
|
||||
data/input/*
|
||||
data/cache/*
|
||||
data/fdr/*
|
||||
data/test-results/*
|
||||
*.tlog
|
||||
*.ulg
|
||||
*.bag
|
||||
*.mcap
|
||||
*.cbor
|
||||
*.parquet
|
||||
*.mp4
|
||||
*.mov
|
||||
*.avi
|
||||
.git/
|
||||
.github/
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.coverage*
|
||||
htmlcov/
|
||||
build/
|
||||
dist/
|
||||
_skbuild/
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
*.engine
|
||||
*.calib
|
||||
*.index
|
||||
*.faiss
|
||||
*.onnx
|
||||
tests/fixtures/large_replays/
|
||||
tests/fixtures/flight_derkachi/
|
||||
tests/fixtures/tiles_corpus/
|
||||
_docs/
|
||||
*.log
|
||||
.DS_Store
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml,yaml,json,toml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.{cpp,c,h,hpp,cc,hh}]
|
||||
indent_size = 4
|
||||
|
||||
[*.{cmake,CMakeLists.txt}]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
+53
-10
@@ -1,10 +1,53 @@
|
||||
GPSD_ENV=development
|
||||
GPSD_CONFIG_DIR=./config/development
|
||||
GPSD_CACHE_DIR=./data/cache
|
||||
GPSD_FDR_DIR=./data/fdr
|
||||
GPSD_DATABASE_URL=postgresql://gpsd:gpsd@localhost:5432/gpsd
|
||||
GPSD_MAVLINK_URL=udp:127.0.0.1:14550
|
||||
GPSD_CAMERA_SOURCE=./data/input
|
||||
GPSD_SIGNING_KEY_REF=test-key-ref
|
||||
GPSD_MAX_FDR_BYTES=104857600
|
||||
GPSD_LOG_LEVEL=info
|
||||
# gps-denied-onboard — environment variables
|
||||
# See _docs/02_document/module-layout.md and AZ-263_initial_structure.md § Environment Variables.
|
||||
|
||||
# Required: selects the FC adapter at the composition root.
|
||||
# One of: ardupilot_plane | inav
|
||||
GPS_DENIED_FC_PROFILE=ardupilot_plane
|
||||
|
||||
# Required: runtime tier gate; 1=workstation/CI, 2=Jetson production
|
||||
GPS_DENIED_TIER=1
|
||||
|
||||
# Required: Postgres connection used by C6 (tile cache + descriptor index)
|
||||
DB_URL=postgresql://gps_denied:dev@db:5432/gps_denied
|
||||
|
||||
# Required (dev/operator only): satellite-provider base URL for tile download
|
||||
# Not set in flight (no egress)
|
||||
SATELLITE_PROVIDER_URL=http://mock-sat:5100
|
||||
|
||||
# Required: path to JSON camera calibration loaded at startup
|
||||
CAMERA_CALIBRATION_PATH=/fixtures/calibration/adti26.json
|
||||
|
||||
# Required: structured log level (DEBUG | INFO | WARNING | ERROR)
|
||||
LOG_LEVEL=DEBUG
|
||||
|
||||
# Required: structured log sink (console | journald | fdr)
|
||||
LOG_SINK=console
|
||||
|
||||
# Required (production): per-flight MAVLink 2.0 signing key path
|
||||
# Dev key from tests/fixtures/mavlink_signing/dev_key in dev-tier1.
|
||||
MAVLINK_SIGNING_KEY=tests/fixtures/mavlink_signing/dev_key
|
||||
|
||||
# CMake / runtime BUILD_* gating flags
|
||||
# Defaults below match the airborne deployment binary (ADR-002 / ADR-011).
|
||||
# Strategy flags use OFF for opt-in non-default strategies; ON for the
|
||||
# deployment defaults that the runtime expects to be linked.
|
||||
BUILD_VINS_MONO=OFF
|
||||
BUILD_SALAD=OFF
|
||||
BUILD_C11_TILE_MANAGER=OFF
|
||||
# Replay-mode strategy flags (ADR-011) — must be ON in the airborne and
|
||||
# research binaries so replay can run from the same image. The CI test
|
||||
# compose files already set these explicitly; production sets them ON.
|
||||
# BUILD_VIDEO_FILE_FRAME_SOURCE=ON
|
||||
# BUILD_TLOG_REPLAY_ADAPTER=ON
|
||||
# BUILD_REPLAY_SINK_JSONL=ON
|
||||
# Dev-only: enables `signing_key_source='dev_static'` on the AP FC adapter.
|
||||
# MUST stay OFF on production images; ON only in dev/CI containers.
|
||||
# BUILD_DEV_STATIC_KEY=OFF
|
||||
|
||||
# Required: C7 inference backend (tensorrt | pytorch_fp16 | onnx_trt_ep)
|
||||
INFERENCE_BACKEND=pytorch_fp16
|
||||
|
||||
# Required: filesystem paths for runtime artifacts
|
||||
FDR_PATH=/var/lib/gps-denied/fdr
|
||||
TILE_CACHE_PATH=/var/lib/gps-denied/tiles
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# AZ-688: dev-only environment for the Jetson e2e harness.
|
||||
# Jetson-only test policy (2026-05-20) — see _docs/LESSONS.md.
|
||||
#
|
||||
# Copy this file to `.env.test` and customize. NEVER commit `.env.test`
|
||||
# (gitignored). Sourced by `scripts/run-tests-jetson.sh` before
|
||||
# `docker compose up`.
|
||||
|
||||
# Suite JWT contract — see ../_docs/10_auth.md. The same secret signs the
|
||||
# dev JWT (AZ-690) and validates it at the satellite-provider boundary.
|
||||
# MUST be ≥ 32 bytes UTF-8. Generate a fresh value with:
|
||||
# openssl rand -hex 32
|
||||
JWT_SECRET=DEV-ONLY-REPLACE-WITH-OPENSSL-RAND-HEX-32-OUTPUT-XXXXXXX
|
||||
|
||||
# JWT issuer / audience claims. Dev-only values that ONLY validate against
|
||||
# the dev secret above. Production deploys MUST use real values provided
|
||||
# by the admin team (the admin API stamps `iss`; satellite-provider
|
||||
# validates `aud`).
|
||||
JWT_ISSUER=DEV-ONLY-iss-admin-azaion-local
|
||||
JWT_AUDIENCE=DEV-ONLY-aud-satellite-provider
|
||||
|
||||
# Google Maps Platform key. Left empty: AZ-689 seeds local fixture tiles
|
||||
# instead, so the hermetic Derkachi e2e flow never calls GoogleMaps. If
|
||||
# you need to exercise the real GMaps tile-download path, set this to a
|
||||
# valid key.
|
||||
GOOGLE_MAPS_API_KEY=
|
||||
|
||||
# AZ-777: Bearer token C11 sends to satellite-provider as
|
||||
# `Authorization: Bearer <token>`. The token is a JWT signed with
|
||||
# JWT_SECRET above and stamped with the same iss/aud the provider
|
||||
# validates. Mint a dev token with:
|
||||
# python scripts/mint_dev_jwt.py
|
||||
# Production deploys retrieve this from the admin API and rotate per
|
||||
# operator session — never commit a real one.
|
||||
SATELLITE_PROVIDER_API_KEY=PASTE-MINTED-JWT-HERE
|
||||
|
||||
# SECURITY: development-only TLS bypass for the parent-suite
|
||||
# satellite-provider self-signed dev cert. The compose env block sets
|
||||
# SATELLITE_PROVIDER_TLS_INSECURE=1 — it stays inside the Jetson e2e
|
||||
# harness, never in production. Production deploys MUST use a real
|
||||
# CA-issued cert (or your own internal CA) and leave this unset (or
|
||||
# set to "0"). C11 logs a single WARNING at startup whenever the
|
||||
# insecure flag is active so the operator can audit it.
|
||||
@@ -0,0 +1 @@
|
||||
_docs/00_problem/input_data/flight_derkachi/flight_derkachi.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -1,15 +0,0 @@
|
||||
## Summary
|
||||
[1-3 bullet points describing the change]
|
||||
|
||||
## Related Tasks
|
||||
[JIRA-ID links]
|
||||
|
||||
## Testing
|
||||
- [ ] Unit tests pass
|
||||
- [ ] Integration tests pass
|
||||
- [ ] Manual testing done (if applicable)
|
||||
|
||||
## Checklist
|
||||
- [ ] No new linter warnings
|
||||
- [ ] No secrets committed
|
||||
- [ ] API docs updated (if applicable)
|
||||
@@ -0,0 +1,25 @@
|
||||
name: ci-tier2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [stage, main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-tier2:
|
||||
runs-on: [self-hosted, jetson, orin-nano-super]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Native build (deployment)
|
||||
run: |
|
||||
cmake -S . -B build -DBUILD_VINS_MONO=OFF -DBUILD_VPR_SALAD=OFF -DBUILD_C11_TILE_MANAGER=OFF
|
||||
cmake --build build --parallel
|
||||
|
||||
ac-bound-nfts:
|
||||
runs-on: [self-hosted, jetson, orin-nano-super]
|
||||
needs: build-tier2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: AC-bound NFTs (NFT-PERF / NFT-LIM / NFT-RES / NFT-SEC / IT-12)
|
||||
run: |
|
||||
pytest -m tier2 -q tests/perf tests/security tests/resilience
|
||||
+90
-29
@@ -1,43 +1,104 @@
|
||||
name: CI
|
||||
name: ci-tier1
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
branches: [dev, stage, main]
|
||||
pull_request:
|
||||
branches: [dev, stage, main]
|
||||
|
||||
jobs:
|
||||
python-quality:
|
||||
runs-on: ubuntu-latest
|
||||
lint:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -e ".[dev]"
|
||||
- name: Format check
|
||||
run: python -m black --check src tests
|
||||
- name: Lint
|
||||
run: python -m ruff check src tests
|
||||
- name: Unit tests
|
||||
run: python -m pytest tests/unit
|
||||
# AZ-300 — `[inference]` (torch + torchvision + onnxruntime) is now
|
||||
# required for `mypy src` to type-check `c7_inference.pytorch_fp16_runtime`
|
||||
# and for `pytest` to collect `test_pytorch_fp16_runtime.py`. Tier-1
|
||||
# CI uses the CPU-only torch wheel; CUDA-gated tests skip themselves
|
||||
# via `pytest.mark.skipif(not torch.cuda.is_available(), ...)`.
|
||||
- run: pip install -e ".[dev,inference]"
|
||||
- run: ruff check src tests
|
||||
- run: mypy src
|
||||
|
||||
replay-compose-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
unit:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Validate compose files
|
||||
run: |
|
||||
docker compose -f docker-compose.yml config
|
||||
docker compose -f docker-compose.test.yml config
|
||||
- name: Collect artifact placeholders
|
||||
run: mkdir -p data/test-results e2e/reports
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
name: replay-evidence-placeholders
|
||||
path: |
|
||||
data/test-results
|
||||
e2e/reports
|
||||
python-version: "3.10"
|
||||
- run: pip install -e ".[dev,inference]"
|
||||
- name: pytest unit (per-component coverage gate)
|
||||
run: pytest -q --cov=gps_denied_onboard --cov-fail-under=75 tests/unit
|
||||
|
||||
integration:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: unit
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: docker compose up
|
||||
run: docker compose -f docker-compose.test.yml up --abort-on-container-exit --exit-code-from e2e-runner --build
|
||||
|
||||
build:
|
||||
name: build-${{ matrix.kind }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: lint
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
kind: [deployment, research]
|
||||
include:
|
||||
# AZ-332 — BUILD_OKVIS2 forced OFF in Tier-1 CI until the tier2
|
||||
# follow-up wires `okvis::ThreadedKFVio` end-to-end. The C++
|
||||
# binding skeleton + CMake glue still ship in this build; full
|
||||
# OKVIS2 native compile is gated on installing Ceres-solver +
|
||||
# OKVIS2 vendored submodules (BRISK, DBoW2) via apt, plus
|
||||
# `submodules: recursive` checkout. That CI lift is the
|
||||
# tier2 task's surface, not AZ-332's.
|
||||
- kind: deployment
|
||||
cmake_flags: >-
|
||||
-DBUILD_OKVIS2=OFF -DBUILD_VINS_MONO=OFF
|
||||
-DBUILD_VPR_SALAD=OFF -DBUILD_C11_TILE_MANAGER=OFF
|
||||
- kind: research
|
||||
cmake_flags: >-
|
||||
-DBUILD_OKVIS2=OFF -DBUILD_VINS_MONO=ON -DBUILD_VPR_SALAD=ON
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: cmake -S . -B build ${{ matrix.cmake_flags }}
|
||||
- run: cmake --build build --parallel
|
||||
|
||||
sbom-diff:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: SBOM diff (ADR-002 enforcement)
|
||||
run: python ci/sbom_diff.py --deployment build-deployment-sbom.json --research build-research-sbom.json
|
||||
|
||||
security:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- run: pip install pip-audit
|
||||
- run: pip-audit -r pyproject.toml || true
|
||||
- name: OpenCV pin gate (D-CROSS-CVE-1)
|
||||
run: python ci/opencv_pin_gate.py --pyproject pyproject.toml
|
||||
|
||||
push-images:
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'push' && contains(fromJson('["refs/heads/dev","refs/heads/stage","refs/heads/main"]'), github.ref)
|
||||
needs: [unit, integration, build, sbom-diff, security]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: echo "push images to GHCR (deployment + research) — wiring lands per release task"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
name: cve-rescan
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 5 1 * *" # 05:00 UTC on the 1st of each month
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
rescan:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- run: pip install pip-audit
|
||||
- run: pip-audit -r pyproject.toml
|
||||
- name: OpenCV pin gate (D-CROSS-CVE-1)
|
||||
run: python ci/opencv_pin_gate.py --pyproject pyproject.toml
|
||||
@@ -0,0 +1,24 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
jetpack-image:
|
||||
runs-on: [self-hosted, jetson, orin-nano-super]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build JetPack image
|
||||
run: echo "JetPack image build + sign + attest — concrete wiring lands per deploy task"
|
||||
|
||||
operator-orchestrator-tarball:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: jetpack-image
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Bundle operator-orchestrator tarball
|
||||
run: |
|
||||
mkdir -p dist
|
||||
tar -czf dist/operator-orchestrator.tar.gz docker-compose.yml docker/ _docs/
|
||||
+69
-35
@@ -1,42 +1,76 @@
|
||||
.DS_Store
|
||||
.venv/
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.mypy_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
*$py.class
|
||||
*.so
|
||||
*.egg
|
||||
*.egg-info/
|
||||
.eggs/
|
||||
.pytest_cache/
|
||||
.coverage
|
||||
.coverage.*
|
||||
coverage.xml
|
||||
htmlcov/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.tox/
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
|
||||
# Build artifacts
|
||||
build/
|
||||
dist/
|
||||
_skbuild/
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
Makefile
|
||||
compile_commands.json
|
||||
|
||||
# Native engines and caches
|
||||
*.engine
|
||||
*.calib
|
||||
*.index
|
||||
*.faiss
|
||||
*.onnx
|
||||
*.trt
|
||||
|
||||
# Test fixtures — large blobs are out-of-band
|
||||
tests/fixtures/large_replays/
|
||||
tests/fixtures/flight_derkachi/*.mp4
|
||||
tests/fixtures/flight_derkachi/*.h264
|
||||
tests/fixtures/flight_derkachi/*.tlog
|
||||
tests/fixtures/tiles_corpus/*.jpg
|
||||
tests/fixtures/tiles_corpus/*.png
|
||||
e2e/fixtures/sitl_replay/
|
||||
|
||||
# Problem-folder flight-log inputs (binary, out-of-band)
|
||||
_docs/00_problem/input_data/**/*.tlog
|
||||
_docs/00_problem/input_data/**/*.mp4
|
||||
_docs/00_problem/input_data/**/*.h264
|
||||
|
||||
# Editor / OS noise
|
||||
.idea/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.swp
|
||||
*~
|
||||
|
||||
# Logs and runtime data
|
||||
*.log
|
||||
/var/lib/gps-denied/
|
||||
fdr_output/
|
||||
tile_cache/
|
||||
e2e-results/
|
||||
|
||||
# Secrets
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.pem
|
||||
.env.local
|
||||
.env.test
|
||||
*.key
|
||||
*.secret
|
||||
!tests/fixtures/mavlink_signing/dev_key
|
||||
|
||||
data/input/*
|
||||
data/cache/*
|
||||
data/fdr/*
|
||||
data/test-results/*
|
||||
data/expected/*
|
||||
!data/input/.gitkeep
|
||||
!data/cache/.gitkeep
|
||||
!data/fdr/.gitkeep
|
||||
!data/test-results/.gitkeep
|
||||
!data/expected/.gitkeep
|
||||
|
||||
*.tlog
|
||||
*.ulg
|
||||
*.bag
|
||||
*.mcap
|
||||
*.cbor
|
||||
*.parquet
|
||||
*.mp4
|
||||
*.mov
|
||||
*.avi
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.png
|
||||
!_docs/00_problem/input_data/**
|
||||
# Deploy rollback bookmark (written by scripts/stop-services.sh)
|
||||
.previous-tags.env
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[submodule "cpp/pybind11/upstream"]
|
||||
path = cpp/pybind11/upstream
|
||||
url = https://github.com/pybind/pybind11.git
|
||||
[submodule "cpp/okvis2/upstream"]
|
||||
path = cpp/okvis2/upstream
|
||||
url = https://github.com/smartroboticslab/okvis2.git
|
||||
@@ -0,0 +1,43 @@
|
||||
# Cycle-1 trigger: manual-only.
|
||||
#
|
||||
# Rationale (per _docs/04_deploy/ci_cd_pipeline.md → Decision Record):
|
||||
# The Tier-1 e2e harness (docker-compose.test.yml + tests/e2e/Dockerfile)
|
||||
# is heavy: TensorRT-class pytorch fp16, gtsam, Postgres 16, and the
|
||||
# Derkachi replay clip. It is shipped opt-in until per-run wall-clock on
|
||||
# the colocated arm64 Jetson agent is characterised.
|
||||
#
|
||||
# Flip-back (cycle-2 polish item #1 in _docs/04_deploy/ci_cd_pipeline.md):
|
||||
# 1. Replace `event: [manual]` with `event: [push, pull_request, manual]`
|
||||
# below.
|
||||
# 2. Add `depends_on: [01-test]` to .woodpecker/02-build-push.yml.
|
||||
|
||||
when:
|
||||
event: [manual]
|
||||
branch: [dev, stage, main]
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- PLATFORM: arm64
|
||||
TAG_SUFFIX: arm
|
||||
# - PLATFORM: amd64
|
||||
# TAG_SUFFIX: amd
|
||||
|
||||
labels:
|
||||
platform: ${PLATFORM}
|
||||
|
||||
steps:
|
||||
- name: e2e
|
||||
image: docker
|
||||
commands:
|
||||
- docker compose -f docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from e2e-runner
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: down
|
||||
image: docker
|
||||
when:
|
||||
status: [success, failure]
|
||||
commands:
|
||||
- docker compose -f docker-compose.test.yml down -v
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
@@ -0,0 +1,85 @@
|
||||
# Cycle-1 trigger: push + manual on dev/stage/main, NO depends_on.
|
||||
#
|
||||
# Rationale (per _docs/04_deploy/ci_cd_pipeline.md → Decision Record):
|
||||
# 01-test.yml runs `event: [manual]` only in cycle-1, so a `depends_on:
|
||||
# [01-test]` clause here would skip every push (no preceding test run to
|
||||
# succeed against). The un-gated stance mirrors the `detections` deferral
|
||||
# pattern documented in `../_infra/ci/README.md` → "detections deferral".
|
||||
#
|
||||
# Re-gate (cycle-2 polish item #1 in _docs/04_deploy/ci_cd_pipeline.md):
|
||||
# Add `depends_on: [01-test]` below once .woodpecker/01-test.yml flips to
|
||||
# `event: [push, pull_request, manual]`.
|
||||
#
|
||||
# Images pushed in cycle-1:
|
||||
# - azaion/gps-denied-onboard-companion-tier1:${BRANCH}-${TAG_SUFFIX}
|
||||
# - azaion/gps-denied-onboard-operator-orchestrator:${BRANCH}-${TAG_SUFFIX}
|
||||
#
|
||||
# Image NOT pushed in cycle-1 (reserved for cycle-2 / companion-jetson):
|
||||
# - azaion/gps-denied-onboard:${BRANCH}-${TAG_SUFFIX}
|
||||
# (parent-suite Jetson compose at ../_infra/deploy/jetson/docker-compose.yml
|
||||
# expects this exact tag; cycle-1 must not write to it or Watchtower
|
||||
# on fielded Jetsons will pull a Tier-1 dev image.)
|
||||
#
|
||||
# OCI labels (suite-mandated, AZ-204 — see ../_infra/ci/README.md → "OCI
|
||||
# image labels and commit provenance"):
|
||||
# org.opencontainers.image.revision = $CI_COMMIT_SHA
|
||||
# org.opencontainers.image.created = <UTC RFC 3339>
|
||||
# org.opencontainers.image.source = $CI_REPO_URL
|
||||
# Plus --build-arg CI_COMMIT_SHA so the Dockerfile can bake ENV AZAION_REVISION.
|
||||
|
||||
when:
|
||||
event: [push, manual]
|
||||
branch: [dev, stage, main]
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- PLATFORM: arm64
|
||||
TAG_SUFFIX: arm
|
||||
# - PLATFORM: amd64
|
||||
# TAG_SUFFIX: amd
|
||||
|
||||
labels:
|
||||
platform: ${PLATFORM}
|
||||
|
||||
steps:
|
||||
- name: build-push-companion-tier1
|
||||
image: docker
|
||||
environment:
|
||||
REGISTRY_HOST: { from_secret: registry_host }
|
||||
REGISTRY_USER: { from_secret: registry_user }
|
||||
REGISTRY_TOKEN: { from_secret: registry_token }
|
||||
commands:
|
||||
- echo "$REGISTRY_TOKEN" | docker login "$REGISTRY_HOST" -u "$REGISTRY_USER" --password-stdin
|
||||
- export TAG=${CI_COMMIT_BRANCH}-${TAG_SUFFIX}
|
||||
- export BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
- |
|
||||
docker build -f docker/companion-tier1.Dockerfile \
|
||||
--build-arg CI_COMMIT_SHA=$CI_COMMIT_SHA \
|
||||
--label org.opencontainers.image.revision=$CI_COMMIT_SHA \
|
||||
--label org.opencontainers.image.created=$BUILD_DATE \
|
||||
--label org.opencontainers.image.source=$CI_REPO_URL \
|
||||
-t $REGISTRY_HOST/azaion/gps-denied-onboard-companion-tier1:$TAG .
|
||||
- docker push $REGISTRY_HOST/azaion/gps-denied-onboard-companion-tier1:$TAG
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: build-push-operator-orchestrator
|
||||
image: docker
|
||||
environment:
|
||||
REGISTRY_HOST: { from_secret: registry_host }
|
||||
REGISTRY_USER: { from_secret: registry_user }
|
||||
REGISTRY_TOKEN: { from_secret: registry_token }
|
||||
commands:
|
||||
- echo "$REGISTRY_TOKEN" | docker login "$REGISTRY_HOST" -u "$REGISTRY_USER" --password-stdin
|
||||
- export TAG=${CI_COMMIT_BRANCH}-${TAG_SUFFIX}
|
||||
- export BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
- |
|
||||
docker build -f docker/operator-orchestrator.Dockerfile \
|
||||
--build-arg CI_COMMIT_SHA=$CI_COMMIT_SHA \
|
||||
--label org.opencontainers.image.revision=$CI_COMMIT_SHA \
|
||||
--label org.opencontainers.image.created=$BUILD_DATE \
|
||||
--label org.opencontainers.image.source=$CI_REPO_URL \
|
||||
-t $REGISTRY_HOST/azaion/gps-denied-onboard-operator-orchestrator:$TAG .
|
||||
- docker push $REGISTRY_HOST/azaion/gps-denied-onboard-operator-orchestrator:$TAG
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
@@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(gps_denied_onboard LANGUAGES CXX)
|
||||
|
||||
# Compile options ----------------------------------------------------------
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
|
||||
# Helper modules -----------------------------------------------------------
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(build_options)
|
||||
include(dependencies)
|
||||
include(strategies)
|
||||
|
||||
# Native subprojects -------------------------------------------------------
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
||||
# Tests --------------------------------------------------------------------
|
||||
|
||||
option(BUILD_TESTING "Enable native unit tests (C++ gtest)" OFF)
|
||||
if(BUILD_TESTING)
|
||||
enable_testing()
|
||||
add_subdirectory(cpp/tests)
|
||||
endif()
|
||||
@@ -1,22 +1,26 @@
|
||||
# GPS-Denied Onboard Runtime
|
||||
# gps-denied-onboard
|
||||
|
||||
Scaffold for the Jetson-hosted GPS-denied localization runtime, replay harness, and
|
||||
deployment evidence paths.
|
||||
Companion onboard system for GPS-denied UAV navigation. Detailed design and architecture documentation lives under [`_docs/`](_docs/).
|
||||
|
||||
The project uses a Python `src/` layout for orchestration code. Native bridge
|
||||
placeholders live inside the owning component folders rather than in a shared
|
||||
native tree.
|
||||
Generated mission data, FDR payloads, cache payloads, and raw frame dumps are kept
|
||||
out of git unless they are explicitly curated test fixtures.
|
||||
## Quick links
|
||||
|
||||
## Local Development
|
||||
- Problem statement: [`_docs/00_problem/problem.md`](_docs/00_problem/problem.md)
|
||||
- Architecture: [`_docs/02_document/architecture.md`](_docs/02_document/architecture.md)
|
||||
- Module layout (file ownership): [`_docs/02_document/module-layout.md`](_docs/02_document/module-layout.md)
|
||||
- Component docs: [`_docs/02_document/components/`](_docs/02_document/components/)
|
||||
- Test specs: [`_docs/02_document/tests/`](_docs/02_document/tests/)
|
||||
- Deployment: [`_docs/02_document/deployment/`](_docs/02_document/deployment/)
|
||||
|
||||
## Local development
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -e ".[dev]"
|
||||
python -m pytest
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -e ".[dev]"
|
||||
pytest -q tests/unit/
|
||||
```
|
||||
|
||||
Local replay infrastructure is described in `docker-compose.yml`; CI and black-box
|
||||
test infrastructure are described in `docker-compose.test.yml`.
|
||||
For full Tier-1 integration via Docker, see [`_docs/02_document/deployment/containerization.md`](_docs/02_document/deployment/containerization.md).
|
||||
|
||||
## Build matrix
|
||||
|
||||
Four binaries built from this codebase: **airborne**, **research**, **operator-orchestrator**, **replay-cli**. CMake `BUILD_*` flags gate component inclusion per binary — see [`cmake/build_options.cmake`](cmake/build_options.cmake) and [`_docs/02_document/module-layout.md` § Build-Time Exclusion Map](_docs/02_document/module-layout.md#build-time-exclusion-map-adr-002).
|
||||
|
||||
@@ -1,175 +1,109 @@
|
||||
# Acceptance Criteria
|
||||
|
||||
> **Last revised**: 2026-05-01 (Phase 1 AC/restrictions assessment clarifications).
|
||||
> Changes vs. previous version (2026-04-25): AC-1.2 split into hard-floor + stretch; AC-1.4 made quantitative; AC-2.2 split per pipeline stage; AC-3.4 dual-trigger; AC-4.3 autopilot-pinned; AC-5.2 N pinned; AC-7.1 scoped to level flight; AC-8.2 freshness by sector; six new AC added (AC-NEW-1 … AC-NEW-6).
|
||||
> Changes 2026-04-26: AC-4.3 extended to dual-channel hybrid (GPS_INPUT primary + ODOMETRY auxiliary); AC-8.6 added (VPR retrieval-unit + change-robustness); AC-NEW-7 added with confirmed numeric thresholds (cache-poisoning safety budget).
|
||||
> Changes 2026-04-29: AC-3.5 and AC-NEW-8 added for temporary visual blackout/cloud occlusion during GPS spoofing, including IMU-only degraded navigation, covariance growth, and failover limits.
|
||||
> Changes 2026-05-01: AC-1.3 anchor-age reporting clarified; AC-2.1 split so the >95% rate applies to VO registration, not every satellite re-anchor; AC-5.2 and AC-NEW-2 now require ArduPilot Plane SITL trigger verification; AC-8.3 storage accounting and AC-NEW-7 Satellite Service ownership clarified.
|
||||
> Last revised 2026-05-07 (cleanup pass: stripped algorithm/library/parameter implementation details; renamed source label `vo_extrapolated` → `visual_propagated`; broadened FC scope to ArduPilot + iNav).
|
||||
> Subsequent revision 2026-05-07 (post-SQ6 research): AC-4.3 reworded to acknowledge that no single message type is accepted by both ArduPilot Plane and iNav — per-FC interface is named explicitly (MAVLink `GPS_INPUT` for ArduPilot Plane, MSP2 `MSP2_SENSOR_GPS` for iNav). Rationale and L1 sources in `_docs/00_research/02_fact_cards/SQ6_fc_external_positioning.md` / `_docs/00_research/01_source_registry/SQ6_external_positioning.md` Sources #4, #9, #10, #12, #13.
|
||||
> Subsequent revision 2026-05-09 (Plan Phase 2a.0 outcomes): AC-NEW-4 and AC-NEW-7 validation requirements relaxed from "≥100 flights" literal to Monte-Carlo-with-stated-CI over currently-available data corpus; multi-flight statistical headroom moved to Step 4 risk register (D-PROJ-3). AC-8.4 augmented with explicit in-air-no-upload security gate (flight-state process-level isolation; post-landing upload tool); local mid-flight tile format pinned to match `satellite-provider`'s on-disk format. AC-NEW-7 external-dependency note revised: parent-suite voting layer is not currently implemented; tracked as parent-suite design task D-PROJ-2.
|
||||
> See git history for prior versions.
|
||||
|
||||
## Position Accuracy
|
||||
|
||||
- **AC-1.1** — The system shall determine GPS coordinates of frame centers within **50 m** of true GPS for **≥80%** of photos in normal flight segments.
|
||||
- **AC-1.2** — The system shall determine GPS coordinates of frame centers within **20 m** of true GPS for **≥50%** of photos in normal flight segments.
|
||||
- **AC-1.3** — Maximum cumulative VO drift between two consecutive satellite-anchored fixes shall be **<100 m** (VO-only fallback) or **<50 m** (when IMU is fused). Drift is measured as ‖VO-extrapolated centre − next anchor centre‖ at the moment of the anchor fix. Every emitted estimate shall include `last_satellite_anchor_age_ms`; validation results shall be binned by anchor age, and the solution draft must define the maximum anchor age after which estimates are treated as degraded (`vo_extrapolated` or `dead_reckoned`) with monotonically growing covariance.
|
||||
- **AC-1.4** — The system shall report a **quantitative confidence score** per position estimate, comprising:
|
||||
- the 95% covariance ellipse semi-major axis in meters, AND
|
||||
- a categorical label `{satellite_anchored, vo_extrapolated, dead_reckoned}`.
|
||||
- **AC-1.1** — Frame-center GPS within **50 m** of true GPS for **≥80%** of normal-flight photos.
|
||||
- **AC-1.2** — Frame-center GPS within **20 m** of true GPS for **≥50%** of normal-flight photos.
|
||||
- **AC-1.3** — Cumulative drift between two consecutive satellite-anchored fixes: **<100 m** visual-only / **<50 m** with IMU fused. Measured as ‖propagated centre − next anchor centre‖ at anchor fix. Every estimate carries `last_satellite_anchor_age_ms`; validation binned by anchor age. The solution must define the max anchor age beyond which estimates degrade to `visual_propagated` / `dead_reckoned` with monotonically growing covariance.
|
||||
- **AC-1.4** — Each estimate reports: 95% covariance ellipse semi-major axis (m) AND a label `{satellite_anchored, visual_propagated, dead_reckoned}`.
|
||||
|
||||
## Image Processing Quality
|
||||
|
||||
- **AC-2.1** — Image registration rate is split by registration type:
|
||||
- **AC-2.1a — VO registration**: frame-to-frame visual registration shall succeed for **>95%** of normal flight segments (defined as: nadir flight ±10° bank / pitch, ≥40% overlap with prior frame, daytime, usable texture, no full visual blackout).
|
||||
- **AC-2.1b — Satellite-anchor registration**: cross-domain UAV-photo to satellite/cache registration is measured separately and is not hidden inside AC-2.1a. Satellite anchoring must satisfy AC-1.1 / AC-1.2 position accuracy, AC-2.2 cross-domain MRE, AC-8.2 freshness, and AC-8.6 retrieval behavior on season-matched tiles.
|
||||
- **AC-2.2** — Mean Reprojection Error (MRE):
|
||||
- **<1.0 px** for VO frame-to-frame homography on overlapping aerial pairs;
|
||||
- **<2.5 px** for satellite-anchored cross-domain (UAV photo ↔ ortho satellite tile) registration.
|
||||
- **AC-2.1a — Frame-to-frame registration**: succeeds for **>95%** of normal flight segments (defined: nadir ±10° bank/pitch, ≥40% prior-frame overlap, daytime, usable texture, no full visual blackout).
|
||||
- **AC-2.1b — Satellite-anchor registration**: measured separately from AC-2.1a; must satisfy AC-1.1/1.2 accuracy, AC-2.2 cross-domain MRE, AC-8.2 freshness, AC-8.6 retrieval behaviour.
|
||||
- **AC-2.2** — Mean Reprojection Error: **<1.0 px** frame-to-frame; **<2.5 px** satellite-anchored cross-domain.
|
||||
|
||||
## Resilience & Edge Cases
|
||||
|
||||
- **AC-3.1** — The system shall correctly continue work in the presence of up to **350 m** outliers between two consecutive photos (caused by airframe tilt up to ±20°).
|
||||
- **AC-3.2** — The system shall correctly continue work during sharp turns where the next photo overlaps **<5%** with the previous, drifts **<200 m**, and changes heading **<70°**. Sharp-turn frames are expected to fail VO and shall be handled by satellite-based re-localization (place recognition over the satellite tile cache).
|
||||
- **AC-3.3** — The system shall handle **≥3 disconnected segments** per flight, connecting each new segment to the previous trajectory via global descriptor retrieval + RANSAC pose-graph relocalization. This is a core capability, not a degraded mode.
|
||||
- **AC-3.4** — When the system cannot determine position for **≥3 consecutive frames AND ≥2 s**, it shall send a re-localization request to the ground station via telemetry. While waiting, it continues VO/IMU dead reckoning and the flight controller uses last known position + IMU extrapolation.
|
||||
- **AC-3.5** — During temporary **visual blackout** where the navigation camera provides no usable ground signal (e.g., clouds/occlusion/whiteout) while GPS is denied or spoofed, the system shall switch to `{dead_reckoned}` within **≤1 processed frame OR ≤400 ms**, reject the spoofed GPS as an estimator input, and propagate position solely from the last trusted state + flight-controller IMU/attitude/airspeed/altitude inputs until visual or satellite anchoring recovers. During this mode, covariance shall grow monotonically, `GPS_INPUT.horiz_accuracy` shall not under-report the 95% covariance semi-major axis, and QGroundControl shall receive a `VISUAL_BLACKOUT_IMU_ONLY` status at **1–2 Hz**.
|
||||
- **AC-3.1** — Tolerate up to **350 m** outliers between two consecutive photos (airframe tilt up to ±20°).
|
||||
- **AC-3.2** — Tolerate sharp turns: <5% overlap, <200 m drift, <70° heading change. Sharp-turn frames may fail frame-to-frame registration; recovery via satellite-reference re-localization.
|
||||
- **AC-3.3** — Handle **≥3 disconnected segments** per flight via satellite-reference re-localization. Core capability, not degraded mode.
|
||||
- **AC-3.4** — On ≥3 consecutive frames AND ≥2 s without a position, request operator re-loc via telemetry; continue dead-reckoned propagation; FC uses last known + IMU extrapolation.
|
||||
- **AC-3.5 — Visual blackout + spoofed GPS** (clouds/occlusion/whiteout while FC reports GPS denial/spoof):
|
||||
- Switch label to `{dead_reckoned}` within ≤1 processed frame OR ≤400 ms.
|
||||
- Reject spoofed GPS as estimator input.
|
||||
- Propagate from last trusted state + FC IMU/attitude/airspeed/altitude until visual or satellite anchoring recovers.
|
||||
- Covariance grows monotonically.
|
||||
- `horiz_accuracy` field of the GPS message to the FC must not under-report the 95% covariance semi-major axis.
|
||||
- `VISUAL_BLACKOUT_IMU_ONLY` STATUSTEXT to QGroundControl at 1–2 Hz.
|
||||
|
||||
## Real-Time Onboard Performance
|
||||
|
||||
- **AC-4.1** — End-to-end latency from camera capture to GPS coordinate output to the flight controller shall be **<400 ms p95**. Up to ~10% of frames may be dropped under sustained load (skip-allowed). Heavy global VPR / cross-domain re-ranking shall be conditional, not part of the steady-state per-frame path, unless profiling proves the full path stays inside the latency and memory budgets on the target Jetson.
|
||||
- **AC-4.2** — Memory usage shall remain below **8 GB** shared on Jetson Orin Nano Super (CPU and GPU share the same 8 GB LPDDR5 pool).
|
||||
- **AC-4.3** — The system shall output its position estimate to the flight controller via **two parallel MAVLink channels**, both emitted by **pymavlink** (general telemetry uses MAVSDK):
|
||||
- **Primary**: `GPS_INPUT` targeting **ArduPilot** with `GPS1_TYPE=14` (MAVLink GPS substitute). Matches the "replacement for the GPS module" framing of the build.
|
||||
- **Auxiliary** (when the EKF emits a fix with full 6-DoF covariance and quality > VISO_QUAL_MIN): `ODOMETRY` so EKF3 can fuse the richer covariance + native yaw error + quality field. ArduPilot's own dev docs designate ODOMETRY as the preferred external-nav channel for non-GPS substitution; we hybridise to keep AC-4.3's GPS-substitute framing while not throwing away the covariance fidelity that AC-NEW-4 depends on.
|
||||
- FC source priorities are configured so GPS_INPUT remains the failover path if ODOMETRY trips a parameter gate.
|
||||
- **v1 scope clause (added 2026-04-26 — see solution_draft03 finding M-30)**: v1 ships **GPS_INPUT only**; the ODOMETRY auxiliary channel is intentionally **disabled** in v1 because feeding both `GPS_INPUT` and `ODOMETRY` for overlapping axes triggers ArduPilot EKF3 double-fusion bugs (issues #30076 / #32506). `EK3_SRC1_*=GPS+Compass`; ODOMETRY emission re-enables in v1.1 once F-T9 SITL confirms PR #30080-class clean source-switching. Tests therefore assert v1 emits GPS_INPUT only and that ODOMETRY is *intentionally absent* on the wire.
|
||||
- (Decision rationale: MAVSDK has no native GPS_INPUT support — see `_docs/00_research/00_ac_assessment.md` Q-1; ODOMETRY hybrid rationale — see Mode B finding M-1 in `_docs/00_research/02_fact_cards.md`; v1 single-channel rationale — see Mode B round-2 finding M-30 in `_docs/00_research/02_fact_cards.md` / solution_draft03.)
|
||||
- **AC-4.4** — Position estimates are streamed to the flight controller frame-by-frame; the system shall not batch or delay output.
|
||||
- **AC-4.5** — The system may refine previously calculated positions and send corrections to the flight controller as updated estimates.
|
||||
- **AC-4.1** — End-to-end latency (camera capture → GPS to FC) **<400 ms p95**. Up to ~10% frames may drop under sustained load.
|
||||
- **AC-4.2** — Memory **<8 GB shared** on Jetson Orin Nano Super.
|
||||
- **AC-4.3 — FC output contract**: WGS84 coordinates delivered to each supported FC via that FC's documented external-positioning interface — MAVLink `GPS_INPUT` for ArduPilot Plane, MSP2 `MSP2_SENSOR_GPS` for iNav. Honest covariance is carried in the field each FC uses for outlier rejection (under-reported covariance is a defect, see AC-NEW-4). Source-label semantics per AC-1.4 are emitted out-of-band via the FC-appropriate channel (e.g. MAVLink `STATUSTEXT` / `NAMED_VALUE_FLOAT` for ArduPilot; MSP equivalent for iNav). Where the FC supports it, implementation may also emit an optional auxiliary external-odometry message when the estimator delivers full 6-DoF covariance + quality above a configured threshold. Per-FC parameter wiring (EKF source-set selection on ArduPilot; GPS provider / UART role on iNav), FDR-side message variants, and out-of-band channel choice remain design decisions.
|
||||
- **AC-4.4** — Estimates streamed frame-by-frame; no batching/delay.
|
||||
- **AC-4.5** — System may refine prior estimates and emit corrections.
|
||||
|
||||
## Startup & Failsafe
|
||||
|
||||
- **AC-5.1** — The system shall initialise using the last known valid GPS position from the flight controller's EKF, plus IMU-extrapolated position at the moment of GPS denial.
|
||||
- **AC-5.2** — If the system fails to produce any position estimate for **>3 s**, the flight controller shall fall back to IMU-only dead reckoning and the system shall log the failure. Because ArduPilot failsafe timing depends on vehicle type and parameters, this fallback behavior must be verified specifically in ArduPilot Plane SITL with the production parameter set; Copter defaults are reference evidence only.
|
||||
- **AC-5.3** — On companion computer reboot mid-flight, the system shall attempt to re-initialise from the flight controller's current IMU-extrapolated position. See AC-NEW-1 for the cold-start time-to-first-fix budget.
|
||||
- **AC-5.1** — Initialise from FC EKF's last valid GPS + IMU-extrapolated position at GPS denial.
|
||||
- **AC-5.2** — On >3 s without estimate, FC falls back to IMU-only dead reckoning; system logs failure. Verify in production param sets of each supported FC (ArduPilot Plane SITL + iNav SITL or equivalent).
|
||||
- **AC-5.3** — On companion reboot mid-flight, re-initialise from FC's current IMU-extrapolated position. Cold-start TTFF in AC-NEW-1.
|
||||
|
||||
## Ground Station & Telemetry
|
||||
|
||||
- **AC-6.1** — Position estimates and confidence scores shall be streamed to **QGroundControl** via the MAVLink telemetry link. High-rate (per-frame) content stays on the local link for forensics; the GCS link is downsampled to **1–2 Hz** for situational awareness.
|
||||
- **AC-6.2** — The ground station can send commands to the onboard system (e.g., operator-assisted re-localization hint with approximate coordinates) via STATUSTEXT, NAMED_VALUE_FLOAT, or a custom MAVLink dialect.
|
||||
- **AC-6.3** — Output coordinates are in **WGS84** format (matches GPS_INPUT spec).
|
||||
- **AC-6.1** — Position estimates + confidence stream to QGroundControl over MAVLink at **1–2 Hz** downsampled (high-rate stays on local FDR).
|
||||
- **AC-6.2** — GCS may send commands (e.g., operator re-loc hint) via standard MAVLink (`STATUSTEXT`, `NAMED_VALUE_FLOAT`) or a custom dialect.
|
||||
- **AC-6.3** — Output coordinates in WGS84.
|
||||
|
||||
## Object Localization (AI Camera)
|
||||
|
||||
- **AC-7.1** — Other onboard AI systems may request GPS coordinates of objects detected by the AI camera. Localization accuracy is **consistent with the frame-center accuracy of the GPS-Denied system in level flight (bank/pitch <5°)**. In maneuvering flight, ground-projection error is bounded by `altitude × |sin(unknown_bank_or_pitch)|` and the system shall publish that bound alongside the estimate.
|
||||
- **AC-7.2** — The system computes object coordinates trigonometrically using: current UAV GPS position (from GPS-Denied), known AI-camera gimbal angle, zoom, and current flight altitude. Flat-terrain assumption applies.
|
||||
- **AC-7.1** — AI systems may request GPS for AI-camera-detected objects. Accuracy consistent with frame-center accuracy in level flight (bank/pitch <5°). In maneuvering flight, error bounded by `altitude × |sin(unknown_bank_or_pitch)|` and that bound is published alongside the estimate.
|
||||
- **AC-7.2** — Object coordinates computed trigonometrically from current UAV position, AI-camera gimbal angle, zoom, and altitude. Flat-terrain assumption.
|
||||
|
||||
## Satellite Reference Imagery
|
||||
- **AC-8.1** — Imagery via Azaion Suite Satellite Service (offline cache interface; no direct commercial-provider calls). Cache-interface resolution ≥0.5 m/px, ideally 0.3 m/px.
|
||||
- **AC-8.2** — Tile freshness: <6 mo (active-conflict sectors), <12 mo (stable rear). Older → reject or downgrade (AC-NEW-6).
|
||||
- **AC-8.3** — Imagery pre-loaded onto companion before flight; offline preprocessing time not time-critical. Pre-extracted descriptors/indices count against the cache budget unless explicitly carved out.
|
||||
- **AC-8.4** — Mid-flight tile generation: continuously orthorectify nav-camera frames into basemap-projected tiles, deduplicated (latest/highest-quality wins). Tiles are written **only** to the local cache while airborne — in-air outbound writes to `satellite-provider` are **forbidden** for drone-security reasons; enforced by a `flight state` process-level gate (see `architecture.md`). Upload to `satellite-provider` happens **only after landing**, triggered by a separate operator-side post-landing upload tool. Local mid-flight tile format matches `satellite-provider`'s on-disk format so post-landing upload is byte-identical. Each uploaded tile carries quality metadata sufficient for the Service's ingest pipeline (AC-NEW-7).
|
||||
- **AC-8.5** — No raw nav-camera or AI-camera frames retained in normal operation; tiles are the only persistent imagery. Forensic exception: ≤0.1 Hz thumbnail log of frames that failed tile generation, within FDR budget (AC-NEW-3).
|
||||
- **AC-8.6 — Satellite-anchor relocalization robustness**:
|
||||
- **Scale-ratio**: any UAV-frame ground footprint at the deployment altitude band must be retrievable from the cache regardless of internal tiling/indexing.
|
||||
- **Scene change in active-conflict sectors**: cratering / building destruction / road realignment must not collapse retrieval recall, measured against a labelled change-pair dataset over season-matched tiles. No `satellite_anchored` label on stale-tile match (per AC-NEW-6).
|
||||
- **Compute & latency**: relocalization must remain inside AC-4.1 latency + AC-4.2 memory budgets under both steady-state and re-loc-trigger workloads.
|
||||
|
||||
- **AC-8.1** — Satellite reference imagery is provided by the **Azaion Suite Satellite Service** (a separate component of the Suite). The runtime onboard system consumes this service through an offline tile cache interface; it does **not** call commercial providers (Maxar, Airbus, Planet, etc.) directly. The Satellite Service is responsible for upstream sourcing and is out of scope for this build. Required resolution at the cache interface: **at least 0.5 m/pixel, ideally 0.3 m/pixel**.
|
||||
- **AC-8.2** — Satellite tiles consumed at runtime shall be:
|
||||
- **<6 months old** for active-conflict sectors;
|
||||
- **<12 months old** for stable rear sectors.
|
||||
System shall reject or downgrade-confidence on tiles older than these thresholds (see AC-NEW-6).
|
||||
- **AC-8.3** — Satellite imagery for the operational area shall be **pre-loaded and pre-processed** onto the companion computer before flight. Offline preprocessing time is not time-critical (minutes/hours). Pre-extracted tile descriptors (e.g., SuperPoint keypoints/descriptors and DINOv2-VLAD global descriptors) are part of the cache and count against the storage budget unless the solution draft explicitly defines a separate descriptor/index budget.
|
||||
- **AC-8.4** — **Mid-flight tile generation & write-back**: during flight, the system shall continuously orthorectify navigation-camera frames into tiles aligned with the basemap projection and store them in the local cache, **deduplicated** so each ground sector is stored at most once (latest / highest-quality tile wins). On landing, the companion computer shall upload newly generated tiles back to the Azaion Suite Satellite Service so that the next mission cache contains imagery refreshed by the previous flight.
|
||||
- **AC-8.5** — **Storage policy**: the system shall **not** retain raw navigation-camera frames or AI-camera frames as part of normal operation. Tiles are the only persistent imagery artifact. Forensic exception: a low-rate (≤0.1 Hz) thumbnail log of frames that **failed** tile generation may be retained for debugging within the FDR budget (AC-NEW-3).
|
||||
- **AC-8.6** — **VPR retrieval unit + change-robustness**:
|
||||
- The Visual Place Recognition (Component 2) FAISS index shall be built over **ground-footprint-sized "VPR chunks"** (~600–800 m at the deployment altitude band, with **40–50 % overlap** between adjacent chunks), **decoupled from the slippy-XYZ storage tile** (z=20). Any UAV frame footprint shall fall fully inside ≥1 chunk regardless of position.
|
||||
- The index shall be **multi-scale**: in addition to fine-scale chunks (derived from z=20 storage), a coarser-scale chunk descriptor set (z=17 or z=18 effective scale) shall be maintained for change-robust retrieval in **active-conflict sectors** where building destruction or major scene change is expected.
|
||||
- VPR top-K shall be **dynamically sized** by sector classification (AC-NEW-6) and EKF position covariance: K=5 in stable sectors with σ_xy ≤ 20 m; K=20 in active-conflict sectors; K=50 on expanding-window fallback.
|
||||
- VPR shall be **invoked conditionally**, not on every frame: in steady state (last anchor age < 2 s, σ_xy < 20 m, VO healthy), the system uses a geometric prior from IMU+VO predicted position to rank candidate chunks by distance alone. VPR's DINOv2 forward is invoked on **re-loc triggers** (cold start AC-NEW-1, sharp turn AC-3.2, disconnected segment AC-3.3, σ_xy > 50 m, or VO failure for ≥2 frames).
|
||||
## Additional AC
|
||||
|
||||
## New AC (added in Phase 1 assessment, expanded with rationale & validation)
|
||||
|
||||
### AC-NEW-1 — Time-to-first-fix on cold start
|
||||
|
||||
**Statement.** From companion-computer boot, the system shall emit its first valid `GPS_INPUT` message in **<30 s**, given an IMU-extrapolated initial position handed over from the flight controller's EKF.
|
||||
|
||||
**Why it matters.** A mid-flight reboot (brown-out, watchdog reset, OS panic) is a realistic scenario on a fixed-wing UAV running an 8-hour mission. The autopilot continues to fly on IMU dead reckoning during the gap; a 30 s budget keeps that drift under ~500 m at 60 km/h cruise, which the EKF can absorb when our first fix arrives.
|
||||
|
||||
**Implementation drivers.** TensorRT engines must be built at install time (not at first run); CUDA / TRT init <5 s; tile-cache mmap warm at start; FAISS index loaded before MAVLink connect; first VPR retrieval + cross-view match must succeed at full resolution within the remaining budget.
|
||||
|
||||
**Validation.** Bench: cold-boot the companion 50× with simulated FC-pose input; record time from boot to first valid `GPS_INPUT` MAVLink frame. Pass = 95% percentile <30 s.
|
||||
### AC-NEW-1 — Cold-start TTFF
|
||||
**Statement.** From companion boot, first valid external-position MAVLink frame **<30 s p95**, given an IMU-extrapolated initial position from FC EKF.
|
||||
**Why.** Mid-flight reboot is realistic on 8 h missions; FC dead-reckons during the gap, ~500 m drift max at 60 km/h.
|
||||
**Validation.** Cold-boot 50× with simulated FC pose; measure boot → first frame; pass = 95th percentile <30 s.
|
||||
|
||||
### AC-NEW-2 — Spoofing-promotion latency
|
||||
|
||||
**Statement.** When the flight controller signals GPS denial or spoofing (ArduPilot fix-loss / EKF lane-switch event; PX4 `EKF2_GPS_SPOOFED` flag if PX4 ever returns to scope), the GPS-Denied system shall promote its own estimate to the FC's primary GPS source within **<3 s**.
|
||||
|
||||
**Why it matters.** Without this gate, the FC may continue to follow a spoofed real-GPS source while our valid estimate sits idle. 3 s is short enough to keep the FC from acting on a malicious heading change but long enough to ride out a single-frame anomaly.
|
||||
|
||||
**Implementation drivers.** Subscribe to `GPS_RAW_INT`, `EKF_STATUS_REPORT`, `SYS_STATUS`, and any ArduPilot Plane EKF/GPS status messages available in the production firmware. Maintain an internal "real-GPS health" rolling average; switch to "primary" mode (raise our `GPS_INPUT` `fix_type` to 3D and assert) when the verified Plane-specific health trigger stays below threshold for >=1 s. Emit `STATUSTEXT` to QGC on every promotion / demotion.
|
||||
|
||||
**Validation.** ArduPilot Plane SITL: simulate spoofing (inject false `GPS_RAW_INT` from a malicious node); verify the exact trigger signals used by the production parameter set; measure time from spoof onset to our promotion. Pass = 95% percentile <3 s.
|
||||
**Statement.** When FC signals GPS denial/spoof, promote onboard estimate to FC's primary position source within **<3 s p95**.
|
||||
**Why.** Without this, FC may follow a spoofed source while a valid onboard estimate sits idle; 3 s rides out one-frame anomalies but blocks malicious heading changes.
|
||||
**Validation.** SITL on each supported FC (ArduPilot Plane + iNav, production param sets): inject false GPS, measure spoof onset → promotion; pass = 95th percentile <3 s on both.
|
||||
|
||||
### AC-NEW-3 — Flight Data Recorder
|
||||
|
||||
**Statement.** The system shall retain to non-volatile storage, per flight: per-frame position estimates with covariance and source-label, IMU traces from the FC at full rate, all emitted `GPS_INPUT` frames, MAVLink raw stream (tlog), system health (CPU / GPU / temp / throttle), tiles generated mid-flight (AC-8.4), and a low-rate (≤0.1 Hz) thumbnail log of frames that failed tile generation. **Raw nav-cam frames and AI-cam frames are NOT retained** (AC-8.5). Storage cap **64 GB / flight**; recorder rolls over (oldest segment dropped first) after cap.
|
||||
|
||||
**Why it matters.** Tiles, telemetry traces, and IMU are the operationally useful artifacts: they reproduce the mission, feed the next mission's cache (AC-8.4), and let post-mission analysis explain any false-position event (AC-NEW-4). Raw frames are large and redundant once tiles exist.
|
||||
|
||||
**Implementation drivers.** Per-day directory layout; fixed-size segment files; rollover policy on segment-close, not on every write. NVMe ≥64 GB on top of the persistent satellite-tile cache.
|
||||
|
||||
**Validation.** Bench: run an 8-hour synthetic load (3 Hz nav frames replayed from disk), assert the FDR ends ≤64 GB and no payload class is silently dropped without a logged rollover event.
|
||||
**Statement.** Per flight, retain to NVM: per-frame estimates with covariance + source-label; FC IMU traces (full rate); all emitted external-position MAVLink frames; raw MAVLink stream (tlog); system health (CPU/GPU/temp/throttle); mid-flight tiles (AC-8.4); ≤0.1 Hz thumbnail log of failed tile-gen frames. **No raw nav-cam/AI-cam frames** (AC-8.5). Cap **64 GB / flight**; oldest segment dropped first on rollover.
|
||||
**Why.** Tiles + telemetry + IMU reproduce the mission, feed next mission's cache (AC-8.4), explain false-position events (AC-NEW-4). Raw frames are large + redundant once tiles exist.
|
||||
**Validation.** 8 h synthetic load (3 Hz nav frames replayed); assert FDR ≤64 GB; no payload class silently dropped without a logged rollover.
|
||||
|
||||
### AC-NEW-4 — False-position safety budget
|
||||
|
||||
**Statement.**
|
||||
- P(reported estimate error > **500 m**) **<0.1 %** per flight.
|
||||
- P(reported estimate error > **1 km**) **<0.01 %** per flight.
|
||||
|
||||
**Why it matters.** A single 1-km-off `GPS_INPUT` frame can hand the FC a heading that flies the UAV outside the geofence in seconds. The covariance carried in `GPS_INPUT` (`h_acc`) is the FC's only defense; this AC bounds the **probability** of our covariance under-reporting reality.
|
||||
|
||||
**Implementation drivers.** EKF covariance must be calibrated, not optimistic. Cross-view fixes with low inlier ratio must be **rejected**, not down-weighted to "small but non-zero". Outlier rejection at the EKF stage (Mahalanobis gate) is mandatory.
|
||||
|
||||
**Validation.** Monte Carlo over the AerialVL public dataset (S03) and our own recorded Mavic flights, with synthetic IMU injection where applicable; report error CDF; pass = both probabilities below budget across ≥100 simulated flights worth of frames.
|
||||
**Statement.** Per flight: **P(error >500 m) <0.1 %**, **P(error >1 km) <0.01 %**.
|
||||
**Why.** A single 1-km-off frame can fly the UAV outside the geofence; covariance carried in the MAVLink message is the FC's only defense.
|
||||
**Validation.** Monte Carlo over the currently-available data corpus (Derkachi flight + 60 stills + synthetic perturbations); report error CDF with stated 95% confidence interval; pass = both probabilities below budget within the CI's lower bound. Multi-flight statistical headroom (originally framed as ≥100 flights) is residual risk tracked in the Step 4 risk register; **D-PROJ-3** reopens this validation when additional multi-flight data becomes available.
|
||||
|
||||
### AC-NEW-5 — Operational environmental envelope
|
||||
|
||||
**Statement.** Operating temperature **−20 °C to +50 °C**; vibration / shock per RTCA DO-160G low-altitude UAV-class envelope. The cooling solution shall sustain the **25 W** power mode at the upper temperature bound for the full **8-hour duty cycle** without thermal throttling.
|
||||
|
||||
**Why it matters.** Without this, all latency / accuracy ACs are conditional on a benign thermal day. Eastern/southern Ukraine summers easily exceed +35 °C ambient inside a UAV bay; without active cooling, the Jetson throttles to 15 W mode and our 400 ms latency budget collapses.
|
||||
|
||||
**Implementation drivers.** Forced-air or active heatsink sized for 25 W continuous at +50 °C ambient bay temperature; thermal sensors logged in FDR (AC-NEW-3); throttle event = automatic `STATUSTEXT` warning to QGC.
|
||||
|
||||
**Validation.** Hot-soak chamber test: 25 W workload at +50 °C ambient for 8 h; assert no throttle. Cold-soak: −20 °C cold-start to first fix within AC-NEW-1 budget.
|
||||
**Statement.** Operating temp **−20 °C to +50 °C**; vibration/shock per RTCA DO-160G low-altitude UAV-class. Cooling sustains **25 W** at the upper temp for the full **8-hour duty cycle** without throttling.
|
||||
**Why.** Without this, all latency/accuracy AC are conditional on a benign thermal day; +35 °C bay temps cause Jetson to throttle to 15 W, collapsing the 400 ms latency budget.
|
||||
**Validation.** Hot-soak: 25 W @ +50 °C for 8 h, no throttle. Cold-soak: −20 °C cold-start within AC-NEW-1.
|
||||
|
||||
### AC-NEW-6 — Imagery freshness enforcement
|
||||
|
||||
**Statement.** The system shall reject (or downgrade confidence on) any satellite tile whose capture date violates AC-8.2 (>6 months old in active-conflict sectors; >12 months old in stable rear sectors). Tiles generated mid-flight (AC-8.4) and not yet uploaded to the Suite Satellite Service are timestamped with the current flight date and treated as fresh.
|
||||
|
||||
**Why it matters.** Stale satellite tiles are the dominant cross-view-matching failure mode in active-conflict sectors (cratering, dam destruction, road realignment). A confident match against a stale tile is worse than no match.
|
||||
|
||||
**Implementation drivers.** Each tile carries `capture_date` metadata in the cache index. Sector classification (active vs stable) is part of the operational area definition handed in pre-flight. Confidence weight = 1.0 if within freshness budget, linearly decayed to 0.0 over a 30-day grace zone past the budget, hard reject beyond the grace.
|
||||
|
||||
**Validation.** Inject tiles with synthetic age into the cache; verify rejection / decay curve matches spec; verify a stale-tile match never produces a `satellite_anchored` source label.
|
||||
**Statement.** System rejects (or downgrades) any tile whose capture date violates AC-8.2. Mid-flight tiles (AC-8.4) not yet uploaded are timestamped current and treated as fresh.
|
||||
**Why.** Stale tiles are the dominant cross-view-matching failure mode in active-conflict sectors; a confident match on a stale tile is worse than no match.
|
||||
**Validation.** Inject synthetic-age tiles; verify rejection/decay matches spec; verify stale-tile match never produces `satellite_anchored`.
|
||||
|
||||
### AC-NEW-7 — Cache-poisoning safety budget
|
||||
**Statement.** Per flight, across all onboard tiles written (AC-8.4): **P(geo-misalign >30 m) <1 %**, **P(>100 m) <0.1 %**.
|
||||
**Why.** Onboard tiles feed back into the `satellite-provider` basemap when uploaded post-landing (AC-8.4). A bad onboard pose with optimistic covariance writes a misaligned tile that becomes the next flight's anchor — cross-flight error compounding that AC-NEW-4 doesn't capture.
|
||||
**External-dependency note.** The parent-suite `satellite-provider` is expected to operate a multi-flight ingest-side trust/voting layer that gates onboard-tile promotion to "trusted basemap" until multiple independent flights agree on geo-alignment. The ingest endpoint and voting layer are **not currently implemented in `satellite-provider`** and are tracked as a parent-suite design task (**D-PROJ-2**). Onboard's job (AC-8.4) is to publish per-tile quality metadata sufficient for that layer. End-to-end AC-NEW-7 evidence depends on the `satellite-provider` contract being added.
|
||||
**Validation.** Onboard-only Monte Carlo replay over the currently-available data corpus + synthetic over-confidence injection (deflate covariance ×1.5–3); report error CDF with stated 95% confidence interval; pass = both probabilities below budget within the CI's lower bound for the onboard-side contribution. Multi-flight statistical headroom and the `satellite-provider` voting-side contract verification are residual risks tracked in the Step 4 risk register; **D-PROJ-3** reopens onboard validation when additional multi-flight data becomes available; **D-PROJ-2** reopens cross-suite validation once the ingest + voting layer is built.
|
||||
|
||||
**Statement.** Per flight, across all onboard tiles written by Component 1b (in-flight ortho-tile generator):
|
||||
|
||||
- P(onboard tile geo-misaligned > **30 m**) **<1 %**.
|
||||
- P(onboard tile geo-misaligned > **100 m**) **<0.1 %**.
|
||||
|
||||
**Why it matters.** Onboard tiles feed back into the Suite Satellite Service's basemap (AC-8.4). Without this AC, a confidently-bad EKF pose can write a misaligned tile that, after Service ingest, becomes the next flight's satellite anchor — producing cross-flight error compounding that AC-NEW-4 (single-flight false-position budget) does not capture. This AC bounds the **probability** that an onboard tile's claimed geo-alignment is wrong by a margin that would propagate to a downstream flight.
|
||||
|
||||
**Implementation drivers.**
|
||||
- Service-source tiles are immutable within freshness budget (AC-8.2); onboard tiles overwrite only stale or other-onboard tiles.
|
||||
- The onboard GPS-Denied system writes tile-quality metadata required by the Suite Satellite Service. The Service-side ingest applies a **2-flight voting layer**: an onboard tile gets promoted to "trusted basemap" only after **N>=2 independent flights** confirm consistent geo-alignment within X m of each other. (Active sectors per AC-NEW-6 may use single-flight promotion when σ_xy <= 3 m AND OSM-road-overlap >= 70 %.) The voting layer is an external Suite Satellite Service dependency, not implemented inside this onboard build, but its contract is required for AC-NEW-7 to pass end-to-end.
|
||||
- The Component-1b parent-pose covariance is a **hard gate** in the local quality score: σ_xy ≤ 5 m for a hard write (`trust_level = candidate`); σ_xy ≤ 3 m for `trust_level = candidate` with full quality; tiles written in the σ_xy ∈ (3, 5] m band are marked `trust_level = soft` in the sidecar.
|
||||
- Eligibility check (Component 1b) tightens generation gate from σ_xy ≤ 10 m to σ_xy ≤ 5 m.
|
||||
|
||||
**Validation.** Multi-flight Monte Carlo replay over AerialVL + Mavic + AerialExtreMatch with **synthetic over-confidence injection** (artificially deflate EKF covariance by 1.5×–3×): assert both probabilities below budget across ≥100 simulated flights worth of frames. Independently, Service-side voting layer is exercised in F-T3 to verify candidate tiles are not promoted to trusted basemap before N-flight confirmation.
|
||||
|
||||
### AC-NEW-8 — Visual blackout + GPS spoofing degraded-mode budget
|
||||
|
||||
**Statement.** When the navigation camera is fully unusable for visual localization and the flight controller simultaneously reports GPS denial/spoofing, the onboard system shall:
|
||||
|
||||
- continue emitting `GPS_INPUT` from IMU-only propagation for **up to 30 s** after the last trusted visual/satellite anchor, unless the estimator covariance exceeds the fail threshold earlier;
|
||||
- label every estimate `{dead_reckoned}` and set `fix_type=2` or lower when the 95% covariance semi-major axis exceeds **100 m**;
|
||||
- emit `fix_type=0`, `horiz_accuracy=999.0`, and `STATUSTEXT: VISUAL_BLACKOUT_FAILSAFE` when the 95% covariance semi-major axis exceeds **500 m** OR visual blackout exceeds **30 s** without a trusted re-anchor;
|
||||
- never promote spoofed real-GPS measurements back into the estimator during blackout unless the FC GPS health has been stable and non-spoofed for **≥10 s** and a visual/satellite consistency check has succeeded.
|
||||
|
||||
**Why it matters.** A cloud/whiteout period removes all visual correction exactly when spoofed GPS cannot be trusted. The only safe behavior is honest IMU-only dead reckoning with rapidly growing uncertainty, not pretending that a stale visual position or spoofed GPS remains valid.
|
||||
|
||||
**Implementation drivers.** Add an image-quality/occlusion classifier before VO/VPR, a blackout state in the ESKF mode machine, covariance floors for IMU-only propagation, strict GPS health gating, and QGC/FDR logging for blackout start, every degraded estimate, and blackout recovery/failsafe.
|
||||
|
||||
**Validation.** SITL/replay: inject a 5 s, 15 s, and 35 s full-camera blackout while spoofing `GPS_RAW_INT`; assert mode transition ≤400 ms, spoofed GPS is ignored, covariance grows monotonically, `GPS_INPUT` fields degrade at the thresholds above, and recovery only occurs after a trusted visual/satellite anchor or the 10 s GPS-health + visual-consistency gate.
|
||||
### AC-NEW-8 — Visual blackout + GPS spoofing degraded mode
|
||||
**Statement.** When the navigation camera is fully unusable AND FC reports GPS denial/spoof:
|
||||
- continue emitting external-position MAVLink frames from IMU-only propagation for **≤30 s** after the last trusted anchor (or until covariance trips fail threshold);
|
||||
- label every estimate `{dead_reckoned}`; degrade MAVLink fix-quality to "2D fix or worse" when 95% covariance semi-major axis **>100 m**;
|
||||
- escalate to "no fix" (`horiz_accuracy=999.0`) + `VISUAL_BLACKOUT_FAILSAFE` STATUSTEXT when 95% covariance >**500 m** OR blackout >**30 s** without a trusted re-anchor;
|
||||
- never promote spoofed real-GPS back into the estimator unless FC GPS health stable + non-spoofed for **≥10 s** AND a visual/satellite consistency check has succeeded.
|
||||
**Why.** During cloud/whiteout + spoofing, no honest correction is available; only safe behaviour is IMU-only dead reckoning with rapidly-growing uncertainty, never pretending stale visual or spoofed GPS remains valid.
|
||||
**Validation.** 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 thresholds, recovery only via trusted anchor or 10-s GPS-health + visual-consistency gate.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
frame_index,image,expected_lat,expected_lon,max_error_m,threshold_50m_applies,threshold_20m_applies
|
||||
1,AD000001.jpg,48.275292,37.385220,100,yes,yes
|
||||
2,AD000002.jpg,48.275001,37.382922,100,yes,yes
|
||||
3,AD000003.jpg,48.274520,37.381657,100,yes,yes
|
||||
4,AD000004.jpg,48.274956,37.379004,100,yes,yes
|
||||
5,AD000005.jpg,48.273997,37.379828,100,yes,yes
|
||||
6,AD000006.jpg,48.272538,37.380294,100,yes,yes
|
||||
7,AD000007.jpg,48.272408,37.379153,100,yes,yes
|
||||
8,AD000008.jpg,48.271992,37.377572,100,yes,yes
|
||||
9,AD000009.jpg,48.271376,37.376671,100,yes,yes
|
||||
10,AD000010.jpg,48.271233,37.374806,100,yes,yes
|
||||
11,AD000011.jpg,48.270334,37.374442,100,yes,yes
|
||||
12,AD000012.jpg,48.269922,37.373284,100,yes,yes
|
||||
13,AD000013.jpg,48.269366,37.372134,100,yes,yes
|
||||
14,AD000014.jpg,48.268759,37.370940,100,yes,yes
|
||||
15,AD000015.jpg,48.268291,37.369815,100,yes,yes
|
||||
16,AD000016.jpg,48.267719,37.368469,100,yes,yes
|
||||
17,AD000017.jpg,48.267461,37.367255,100,yes,yes
|
||||
18,AD000018.jpg,48.266663,37.365888,100,yes,yes
|
||||
19,AD000019.jpg,48.266135,37.365460,100,yes,yes
|
||||
20,AD000020.jpg,48.265574,37.364211,100,yes,yes
|
||||
21,AD000021.jpg,48.264892,37.362998,100,yes,yes
|
||||
22,AD000022.jpg,48.264393,37.361086,100,yes,yes
|
||||
23,AD000023.jpg,48.263803,37.361028,100,yes,yes
|
||||
24,AD000024.jpg,48.263014,37.359878,100,yes,yes
|
||||
25,AD000025.jpg,48.262635,37.358277,100,yes,yes
|
||||
26,AD000026.jpg,48.261819,37.357116,100,yes,yes
|
||||
27,AD000027.jpg,48.261182,37.355907,100,yes,yes
|
||||
28,AD000028.jpg,48.260727,37.354723,100,yes,yes
|
||||
29,AD000029.jpg,48.260117,37.353469,100,yes,yes
|
||||
30,AD000030.jpg,48.259677,37.352165,100,yes,yes
|
||||
31,AD000031.jpg,48.258881,37.351376,100,yes,yes
|
||||
32,AD000032.jpg,48.258425,37.349964,100,yes,yes
|
||||
33,AD000033.jpg,48.258653,37.347004,100,yes,yes
|
||||
34,AD000034.jpg,48.257879,37.347711,100,yes,yes
|
||||
35,AD000035.jpg,48.256777,37.348444,100,yes,yes
|
||||
36,AD000036.jpg,48.255756,37.348098,100,yes,yes
|
||||
37,AD000037.jpg,48.255375,37.346549,100,yes,yes
|
||||
38,AD000038.jpg,48.254799,37.345603,100,yes,yes
|
||||
39,AD000039.jpg,48.254557,37.344566,100,yes,yes
|
||||
40,AD000040.jpg,48.254380,37.344375,100,yes,yes
|
||||
41,AD000041.jpg,48.253722,37.343093,100,yes,yes
|
||||
42,AD000042.jpg,48.254205,37.340532,100,yes,yes
|
||||
43,AD000043.jpg,48.252380,37.342112,100,yes,yes
|
||||
44,AD000044.jpg,48.251489,37.343079,100,yes,yes
|
||||
45,AD000045.jpg,48.251085,37.346128,100,yes,yes
|
||||
46,AD000046.jpg,48.250413,37.344034,100,yes,yes
|
||||
47,AD000047.jpg,48.249414,37.343296,100,yes,yes
|
||||
48,AD000048.jpg,48.249114,37.346895,100,yes,yes
|
||||
49,AD000049.jpg,48.250241,37.347741,100,yes,yes
|
||||
50,AD000050.jpg,48.250974,37.348379,100,yes,yes
|
||||
51,AD000051.jpg,48.251528,37.349468,100,yes,yes
|
||||
52,AD000052.jpg,48.251873,37.350485,100,yes,yes
|
||||
53,AD000053.jpg,48.252161,37.351491,100,yes,yes
|
||||
54,AD000054.jpg,48.252685,37.352343,100,yes,yes
|
||||
55,AD000055.jpg,48.253268,37.353119,100,yes,yes
|
||||
56,AD000056.jpg,48.253767,37.354246,100,yes,yes
|
||||
57,AD000057.jpg,48.254329,37.354946,100,yes,yes
|
||||
58,AD000058.jpg,48.254874,37.355765,100,yes,yes
|
||||
59,AD000059.jpg,48.255481,37.356501,100,yes,yes
|
||||
60,AD000060.jpg,48.256246,37.357485,100,yes,yes
|
||||
|
@@ -0,0 +1,34 @@
|
||||
# Derkachi camera
|
||||
|
||||
Camera model: **Topotek KHP20S30**
|
||||
Daylight sensor: 1/2.8" CMOS (Sony IMX291-class, 2.13 MP)
|
||||
Image resolution: Full HD 1920×1080 @ 30/60 fps
|
||||
Lens: 20× optical zoom, f = 4.7 mm – 94 mm
|
||||
|
||||
## Calibration
|
||||
|
||||
**File**: [`khp20s30_factory.json`](./khp20s30_factory.json)
|
||||
**Acquisition method**: `factory_sheet` (AZ-702 — factory-sheet approximation)
|
||||
**Assumed zoom setting**: wide-angle (f = 4.7 mm), HFOV ≈ 59.5°
|
||||
|
||||
Per-unit checkerboard refinement is **deferred** (no hardware access to the
|
||||
Derkachi unit). The factory-sheet calibration is the cheapest reasonable
|
||||
starting point. The residual focal-length error is expected to be in the
|
||||
**1–3 %** band; at high AGL this may push horizontal position error past the
|
||||
AC-3 100 m budget, in which case AZ-699 (T3 real-flight validation) reports
|
||||
the honest finding and a follow-up checkerboard task is filed.
|
||||
|
||||
### Why factory-sheet (not checkerboard or PnP-from-tlog)
|
||||
|
||||
* **Checkerboard**: needs physical access to the airframe + a known-geometry
|
||||
calibration target. Not in scope for AZ-696.
|
||||
* **PnP-from-tlog back-computation**: would require a 5-point task in its own
|
||||
right; deferred as an AZ-696 follow-up if the residual budget proves
|
||||
insufficient.
|
||||
|
||||
### Replay-test wiring
|
||||
|
||||
`tests/e2e/replay/conftest.py::_calibration_path()` prefers this file when
|
||||
present and falls back to `tests/fixtures/calibration/adti26.json` otherwise,
|
||||
so dev environments that don't carry the calibration file still exercise the
|
||||
AC-1 / AC-2 / AC-5 / AC-6 paths.
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"camera_id": "khp20s30_factory",
|
||||
"intrinsics_3x3": [
|
||||
[1680.4469, 0.0, 960.0],
|
||||
[0.0, 1680.4469, 540.0],
|
||||
[0.0, 0.0, 1.0]
|
||||
],
|
||||
"distortion": [0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
"body_to_camera_se3": [
|
||||
[1.0, 0.0, 0.0, 0.0],
|
||||
[0.0, 1.0, 0.0, 0.0],
|
||||
[0.0, 0.0, 1.0, 0.0],
|
||||
[0.0, 0.0, 0.0, 1.0]
|
||||
],
|
||||
"acquisition_method": "factory_sheet",
|
||||
"metadata": {
|
||||
"model": "Topotek KHP20S30",
|
||||
"sensor": "1/2.8\" CMOS (Sony IMX291-class), 2.13 MP",
|
||||
"image_resolution_px": [1920, 1080],
|
||||
"sensor_width_mm": 5.37,
|
||||
"sensor_height_mm": 3.02,
|
||||
"assumed_focal_length_mm": 4.7,
|
||||
"focal_length_range_mm": [4.7, 94.0],
|
||||
"assumed_zoom": "wide-angle (max FOV, f=4.7 mm)",
|
||||
"computed_hfov_deg": 59.48,
|
||||
"computed_vfov_deg": 35.62,
|
||||
"intrinsics_formula": "fx = fy = focal_mm * (image_width_px / sensor_width_mm); cx = width/2; cy = height/2",
|
||||
"body_to_camera_convention": "identity-down (nadir, camera-z aligned with aircraft body-z = down per FRD body frame)",
|
||||
"residual_budget_pct": 3.0,
|
||||
"note": "Factory-sheet approximation per AZ-702. The KHP20S30 is a 20x optical-zoom camera (f=4.7-94 mm); the wide-angle f=4.7 mm setting is assumed without per-flight EXIF confirmation. Per-unit checkerboard refinement is deferred — see _docs/00_problem/input_data/flight_derkachi/camera_info.md and the AZ-696 epic. AC-3 (<= 100 m horizontal error) may honestly fail if the assumed focal length is wrong by enough to swamp the 100 m budget at the Derkachi AGL band.",
|
||||
"task": "AZ-702",
|
||||
"epic": "AZ-696"
|
||||
}
|
||||
}
|
||||
@@ -1,59 +1,47 @@
|
||||
# Restrictions
|
||||
|
||||
> **Last revised**: 2026-05-01 (post Phase 1 AC/restrictions assessment clarifications).
|
||||
> Last revised 2026-05-07 (cleanup pass — design-independent, IEEE-830 style; only external dependencies, environmental constraints, integration boundaries).
|
||||
> Subsequent revision 2026-05-07 (post-SQ6 research): the FC-facing communication protocol entries below were corrected — iNav firmware (master, post-9.0) has no inbound MAVLink external-positioning handler; the project must use a per-FC adapter (MAVLink `GPS_INPUT` for ArduPilot Plane; MSP2 `MSP2_SENSOR_GPS` for iNav). Rationale and L1 sources in `_docs/00_research/02_fact_cards/SQ6_fc_external_positioning.md` / `_docs/00_research/01_source_registry/SQ6_external_positioning.md` Sources #4, #9, #10, #12, #13.
|
||||
|
||||
## UAV & Flight
|
||||
|
||||
- Photos are taken by airplane (fixed-wing) type UAVs only.
|
||||
- Photos are taken by the navigation camera pointing downwards and fixed (not gimbal-stabilized).
|
||||
- Operational area is the eastern and southern parts of Ukraine (east/left of the Dnipro River).
|
||||
- Mission profile: 8-hour flights at ~60 km/h cruise. Two route shapes coexist:
|
||||
- **Sector**: up to **10 × 15 km = 150 km²** of dense coverage.
|
||||
- **Transit corridor**: ~**50 km × 1 km = 50 km²** strip in/out of the sector.
|
||||
- **Total operational area: up to ~400 km²** of pre-cached satellite imagery per mission. Cache is **persistent across flights** (not redownloaded each mission). Storage budget **~10 GB** for the satellite tile cache; see AC-NEW-3 for flight-data-recorder budget.
|
||||
- Altitude: pre-defined, **≤1 km AGL**. Terrain is assumed flat (operational area is rolling steppe / agricultural land); height differences are negligible.
|
||||
- Weather: predominantly sunny daytime operations. Validation must still cover the seasonal/visibility classes that affect visual matching in the operational area: summer crop/field patterns, autumn/winter bare fields, cloud/smoke/haze, snow if missions can occur in winter, and low-texture agricultural repetition.
|
||||
- Sharp turns occur but are the exception, not the rule. Two consecutive photos may share <5% overlap during a turn (see AC-3.2).
|
||||
- **No photo-count cap.** The previously stated "up to 3000 photos per flight" was a legacy operator number from a Mavic-class workflow; it is dropped because (a) it is inconsistent with 8 h × 3 fps, and (b) the system does **not store raw photos at all** (see AC-8.5). Storage is bounded by the tile-cache + FDR caps (~10 GB persistent + 64 GB / flight, AC-NEW-3).
|
||||
- Fixed-wing UAVs only; navigation camera fixed downward (no gimbal).
|
||||
- Operational area: eastern/southern Ukraine (east of Dnipro).
|
||||
- Mission profile: 8-hour flights, ~60 km/h cruise. Sector ≤150 km² + transit corridor ~50 km². Total cached area ≤~400 km², persistent across flights.
|
||||
- Altitude ≤1 km AGL; terrain assumed flat (rolling steppe / agricultural).
|
||||
- Weather: predominantly sunny daytime; validation must cover seasonal/visibility classes (summer crops, autumn/winter bare fields, cloud/haze, snow if winter, low-texture repetition).
|
||||
- Sharp turns are exceptions; consecutive photos may share <5% overlap (AC-3.2).
|
||||
- No raw-photo storage (AC-8.5); storage bounded by tile cache + per-flight FDR (AC-NEW-3).
|
||||
|
||||
## Cameras
|
||||
|
||||
- The UAV carries **two cameras**:
|
||||
1. **Navigation camera** — fixed, downward-pointing, not autostabilized. Consumed by the GPS-Denied system for position estimation.
|
||||
2. **AI camera** — main mission camera with operator-controllable gimbal angle and zoom. Consumed by onboard AI detection systems.
|
||||
- **Navigation camera**: **ADTi 20MP 20L V1, APS-C sensor, ~5472 × 3648 px (≈20 MP)**. APS-C sensor (~23.6 × 15.7 mm). Lens TBD — selected during solution-draft phase to land GSD in the **10–20 cm/px band at 1 km AGL** (drives a frame ground footprint of ~470 m × 314 m to ~980 m × 655 m depending on focal length). Other intrinsics (focal length, exact sensor dimensions, distortion coefficients) are pinned at module-selection time and used by Component-1b orthorectification (pre-flight checkerboard calibration, F-F2).
|
||||
- **AI camera pose information available to the GPS-Denied system**: gimbal angle and zoom only. The UAV's instantaneous bank/pitch is **not** published from the autopilot to the AI-camera reasoning path. Object-localization accuracy is therefore scoped to level flight (AC-7.1).
|
||||
- Cameras connect to the companion computer over USB, MIPI-CSI, or GigE (specific interface TBD at solution-draft phase, dependent on chosen module).
|
||||
- **Navigation camera (pinned)**: ADTi 20MP 20L V1, APS-C ~23.6 × 15.7 mm, ~5472 × 3648 px (≈20 MP). Lens chosen so GSD lands in 10–20 cm/px @ 1 km AGL (frame footprint ~470×314 m to ~980×655 m). Intrinsics + camera-to-body calibration must be obtained pre-flight (e.g., checkerboard).
|
||||
- **AI camera**: operator-controlled gimbal angle + zoom (consumed by AI detection systems). The GPS-Denied system supports object localization (AC-7.x) using gimbal angle + zoom only — UAV bank/pitch is not published to that path; AI-camera object localization is therefore scoped to level flight (AC-7.1).
|
||||
- Camera-to-companion interface: USB / MIPI-CSI / GigE (lens-module dependent).
|
||||
|
||||
## Satellite Imagery
|
||||
|
||||
- **Source: Azaion Suite Satellite Service** (a separate component of the wider Suite). The onboard system is a **consumer** of this service, not a direct customer of commercial providers. Upstream sourcing (Maxar / Airbus / partner agencies / commissioned tasking) is the Satellite Service's concern, not this build's.
|
||||
- **Onboard interface to the Service is offline-only**: the companion computer holds a local cache populated **before flight** by syncing from the Service for the operational area (AC-8.3). No satellite imagery is fetched in-flight from the Service.
|
||||
- **Mid-flight tile generation (AC-8.4)**: during the mission the companion computer generates fresh tiles from the navigation camera, orthorectified into the basemap projection, deduplicated against the existing cache, and stored locally. On landing, those new tiles are uploaded back to the Suite Satellite Service for ingestion, so the next mission's cache is refreshed by the previous flight.
|
||||
- **No raw photo storage** (AC-8.5): the tile is the unit of persistence. Raw nav-camera and AI-camera frames are not retained (except a low-rate failure-thumbnail log for forensics).
|
||||
- **Resolution at the cache interface**: 0.5 m/pixel minimum, 0.3 m/pixel ideal (AC-8.1). The architecture is provider-agnostic at the cache boundary; whatever the Suite Satellite Service supplies must meet that bar.
|
||||
- **Storage tile resolution convention**: cache imagery is specified by source pixel size, not by assuming a universal zoom-to-meter mapping. The cache interface accepts **0.5 m/px minimum, 0.3 m/px ideal** imagery, and every tile manifest records CRS, tile matrix convention, tile dimension, latitude-adjusted meters-per-pixel, capture date, source, and compression. If an XYZ/WebMercator tile pyramid is used, its zoom level is documented as a provider convention rather than treated as proof of physical resolution. The matcher (Component 3) needs <=~4x scale ratio between the UAV frame (~12 cm/px GSD at 1 km AGL with the 20 MP APS-C camera) and the reference; 0.3-0.5 m/px reference imagery gives a ~2.5-4.2x ratio. Storage budget across the 400 km² operational area remains capped at **10 GB** for the persistent cache and must be validated against the final provider format/compression. The 10 GB budget includes cache imagery, manifests, overviews, and any precomputed global/local descriptors unless the solution draft explicitly splits a separate descriptor/index budget. **VPR retrieval unit is decoupled from the storage tile** (see AC-8.6 below): VPR chunks are derived from the tile cache at ground-footprint scale (~600-800 m chunks with 40-50 % overlap), independent of the storage tile convention.
|
||||
- **Freshness gates** (AC-8.2 / AC-NEW-6) are enforced at runtime: tiles older than 6 months (active-conflict sectors) or 12 months (stable rear sectors) are rejected or down-confidence-weighted. Tiles generated mid-flight are timestamped with the current flight date and treated as fresh.
|
||||
- **Free public imagery (Sentinel-2 etc.)** is not on the runtime path. If the Suite Satellite Service ever returns Sentinel-class tiles, the cache rejects them as below the 0.5 m/px floor.
|
||||
- **Source**: Azaion Suite Satellite Service (separate Suite component). Onboard system is a consumer; upstream sourcing is the Service's concern.
|
||||
- **Onboard interface is offline-only**: companion holds a local cache populated pre-flight from the Service for the operational area (AC-8.3). No in-flight Service calls.
|
||||
- **Mid-flight tile generation (AC-8.4)**: companion orthorectifies nav-camera frames into basemap-projected tiles, deduplicates, stores locally; uploads on landing.
|
||||
- **Storage policy**: tile is the unit of persistence; no raw frames retained (AC-8.5).
|
||||
- **Resolution at cache interface**: ≥0.5 m/px, ideally 0.3 m/px (AC-8.1).
|
||||
- **Tile manifest schema**: CRS, tile matrix, dimension, lat-adjusted m/px, capture date, source, compression. Slippy/XYZ zoom (if used) is a provider convention, not a resolution proof.
|
||||
- **Cache budget**: 10 GB persistent across the ~400 km² area, including manifests, overviews, and any precomputed indices unless the solution carves out a separate descriptor budget.
|
||||
- **Freshness**: enforced per AC-8.2 / AC-NEW-6 (6-month active-conflict / 12-month rear). Mid-flight tiles timestamped current and treated as fresh.
|
||||
- **Sentinel-2 / free public imagery**: not on runtime path; cache rejects below the 0.5 m/px floor.
|
||||
|
||||
## Onboard Hardware
|
||||
|
||||
- Processing platform: **Jetson Orin Nano Super** — 67 TOPS sparse INT8, **8 GB shared LPDDR5** (CPU and GPU share the same memory pool), **25 W TDP**.
|
||||
- Companion computer runs JetPack (Ubuntu-based) with CUDA / TensorRT available.
|
||||
- Sustained GPU load may cause thermal throttling; the processing pipeline must stay within the thermal envelope. The cooling solution shall sustain the 25 W power mode for the 8-hour duty cycle at the upper environmental-envelope temperature (AC-NEW-5).
|
||||
- Onboard non-volatile storage: budget at least the satellite-cache (~10 GB) **plus** the flight-data-recorder cap (64 GB / flight, AC-NEW-3). Reuse-across-flights tile cache stays resident; per-flight FDR rolls over after cap.
|
||||
- **Companion computer (pinned)**: Jetson Orin Nano Super — 67 TOPS sparse INT8, 8 GB shared LPDDR5, 25 W TDP. JetPack (Ubuntu) with CUDA / TensorRT.
|
||||
- Cooling sized for 25 W continuous over 8 h at the upper environmental temp (AC-NEW-5).
|
||||
- Storage budget ≥ tile cache (~10 GB) + per-flight FDR (64 GB, AC-NEW-3).
|
||||
|
||||
## Sensors & Integration
|
||||
|
||||
- High-rate **IMU** data is available from the flight controller via MAVLink.
|
||||
- The original still-image sample does **not** include synchronized IMU or ground-truth pose. The Derkachi representative fixture adds cropped nadir video plus synchronized `SCALED_IMU2` and `GLOBAL_POSITION_INT` telemetry, which is enough for replay, synchronization, latency, VIO smoke tests, and trajectory comparison against the tlog GPS path. Final production acceptance still requires camera intrinsics, lens distortion, exact camera-to-body calibration, and representative synchronized navigation-camera frames, FC IMU/attitude/airspeed/altitude, emitted MAVLink messages, and ground-truth trajectory from a representative flight or replay rig.
|
||||
- The system communicates with the flight controller via MAVLink. Telemetry plumbing uses **MAVSDK**; the `GPS_INPUT` injection path is implemented via **pymavlink**, since MAVSDK does not expose a native `GPS_INPUT` API.
|
||||
- **Autopilot target: ArduPilot only** (with `GPS1_TYPE=14` for MAVLink GPS injection). PX4 is out of scope for the build; if it ever returns to scope it will use `VISION_POSITION_ESTIMATE`, not `GPS_INPUT`. (See `_docs/00_research/00_ac_assessment.md` Q-1.)
|
||||
- The system outputs WGS84 GPS coordinates to the flight controller as a replacement for the real GPS module (MAVLink GPS_INPUT, AC-4.3).
|
||||
- **Ground station: QGroundControl** is the supported GCS. Mission Planner is not in scope. Telemetry link is bandwidth-limited and is not the primary output channel; per-frame data stays on the local FDR (AC-NEW-3), GCS sees a 1–2 Hz downsampled summary (AC-6.1).
|
||||
- **High-rate IMU** available from FC via MAVLink (both ArduPilot Plane and iNav expose IMU telemetry over MAVLink outbound).
|
||||
- **Communication protocol (pinned)**: MAVLink for the GCS link (QGroundControl). Companion ↔ FC interface is per-FC: MAVLink for ArduPilot Plane (inbound external positioning + outbound telemetry); MSP2 for iNav (inbound external positioning via `MSP2_SENSOR_GPS`); MAVLink outbound from iNav for telemetry to the GCS is preserved.
|
||||
- **Supported flight controllers**: ArduPilot Plane, iNav. PX4 out of scope.
|
||||
- **Output to FC**: WGS84 GPS coordinates as a real-GPS replacement, via each supported FC's documented external-positioning interface — MAVLink `GPS_INPUT` for ArduPilot Plane, MSP2 `MSP2_SENSOR_GPS` for iNav (companion is the sole GPS source on iNav; iNav has no dual-GPS arbitration). Per-FC parameter wiring (EKF source-set on ArduPilot; GPS provider/UART selection on iNav) and source-label out-of-band channel are design choices; outcome contract is AC-4.3.
|
||||
- **Ground station**: QGroundControl (Mission Planner out of scope). Telemetry link bandwidth-limited; per-frame data stays on local FDR (AC-NEW-3); GCS sees 1–2 Hz downsampled summary (AC-6.1).
|
||||
- **Representative data**: see `input_data/` (still images), `input_data/flight_derkachi/` (cropped nadir video + synchronized `SCALED_IMU2` + `GLOBAL_POSITION_INT`). Production acceptance still requires camera intrinsics, distortion, camera-to-body calibration, and synchronized representative flight data (frames + FC IMU/attitude/airspeed/altitude + emitted MAVLink + ground-truth trajectory).
|
||||
|
||||
## Failsafe & Safety
|
||||
|
||||
- If the GPS-Denied system fails to produce any position estimate for **>3 s**, the autopilot falls back to IMU-only dead reckoning (AC-5.2). N=3 s rides through one sharp turn at cruise speed without tripping the failsafe.
|
||||
- The system must satisfy the false-position safety budget in AC-NEW-4 (P(error >500 m) <0.1%, P(error >1 km) <0.01% per flight).
|
||||
- Cold-start time-to-first-fix budget is **<30 s** from companion-computer boot (AC-NEW-1); spoofing-promotion latency is **<3 s** from FC's GPS-loss signal (AC-NEW-2).
|
||||
- If no estimate produced for >3 s → autopilot falls back to IMU-only dead reckoning (AC-5.2). 3 s rides through one sharp turn at cruise.
|
||||
- False-position safety budget: AC-NEW-4 (P(>500 m) <0.1 %, P(>1 km) <0.01 % per flight).
|
||||
- Cold-start TTFF <30 s (AC-NEW-1); spoofing-promotion latency <3 s (AC-NEW-2).
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# Acceptance Criteria Assessment
|
||||
|
||||
Accessed: 2026-05-01. Rerun after user-approved clarifications: 2026-05-01.
|
||||
|
||||
## Research Scope
|
||||
|
||||
- **Output class**: Technical-component selection support.
|
||||
- **Novelty sensitivity**: High for VPR, embedded AI, and autopilot integration; source preference is current papers and official docs.
|
||||
- **Boundary**: Fixed-wing UAV, nadir navigation camera, ArduPilot Plane, Jetson Orin Nano Super, offline Azaion Suite Satellite Service cache, eastern/southern Ukraine terrain.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
| Criterion | Current Values | Researched Values / Evidence | Cost / Timeline Impact | Status |
|
||||
|-----------|----------------|------------------------------|------------------------|--------|
|
||||
| AC-1.1 / AC-1.2 frame-center accuracy | <=50 m for >=80%, <=20 m for >=50% in normal segments | Plausible only with periodic satellite anchoring plus VO/IMU propagation. Aerial VPR papers show the mechanism is viable but sensitive to weather, scale, repetition, and tile overlap. | High validation cost. | Keep, high-risk |
|
||||
| AC-1.3 drift | VO-only <100 m, IMU-fused <50 m between anchors, anchor age reported | Updated AC now requires `last_satellite_anchor_age_ms`, binned validation, and degraded covariance after a solution-defined max anchor age. | Medium. | Updated |
|
||||
| AC-1.4 confidence | 95% covariance ellipse + source label | `GPS_INPUT` supports accuracy fields; source labels must be carried in telemetry/FDR because `GPS_INPUT` has no semantic label field. | Medium. | Keep |
|
||||
| AC-2.1 registration | VO >95%; satellite anchoring measured separately | Split is correct: VO success is not the same as cross-domain satellite anchor success. | Medium-high. | Updated |
|
||||
| AC-2.2 reprojection | <1 px VO, <2.5 px satellite anchor | Reasonable image-space gates, with coordinate error still dependent on calibration, orthorectification, and satellite georegistration. | Medium. | Keep |
|
||||
| AC-3.x resilience | Outliers, sharp turns, disconnected segments, blackout | Technically feasible only through mode switching: VO failure triggers VPR/relocalization, blackout triggers IMU-only propagation with honest covariance growth. | High test cost. | Keep |
|
||||
| AC-4.1 latency | <400 ms p95, <=10% frame drops, heavy VPR conditional | Aerial VPR survey reports some re-ranking paths too slow for steady-state use; solution must keep global VPR off the per-frame hot path. | High optimization cost. | Updated |
|
||||
| AC-4.2 memory | <8 GB shared | Feasible if descriptors are compressed/pruned and indices are memory-mapped or loaded selectively. | Medium-high. | Keep |
|
||||
| AC-4.3 MAVLink | v1 GPS_INPUT only via pymavlink | ArduPilot docs require `GPS1_TYPE=14`; MAVLink defines required lat/lon, velocity, fix, and accuracy fields. MAVSDK should remain telemetry-oriented. | Medium. | Keep |
|
||||
| AC-5.2 failsafe | >3 s no estimate triggers fallback, Plane SITL verified | Copter docs are reference only. Plane-specific production parameters must be verified in SITL. | Medium. | Updated |
|
||||
| AC-7 object localization | Level-flight AI-camera object GPS | Realistic under level-flight clause; maneuvering estimates must publish conservative bound. | Medium. | Keep |
|
||||
| AC-8.x satellite cache | 0.3-0.5 m/px, freshness, offline descriptors, VPR chunks | Resolution is feasible through commercial/service imagery. Storage must count descriptors unless separately budgeted. | Medium-high. | Updated |
|
||||
| AC-NEW-1 / 2 startup and spoofing | <30 s first fix, <3 s promotion | Feasible only with prebuilt engines, warmed indices, and verified Plane GPS-health triggers. | Medium-high. | Keep with SITL gate |
|
||||
| AC-NEW-3 FDR | <=64 GB per flight, no raw frames | Feasible with segment files and rollover. | Medium. | Keep |
|
||||
| AC-NEW-4 / 7 safety budgets | False-position and cache-poisoning probabilities | Appropriate safety gates, but require Monte Carlo and representative flight/replay data. | High. | Keep |
|
||||
| AC-NEW-5 environment | -20 C to +50 C, 25 W for 8 h | NVIDIA confirms 25 W mode; thermal design must prevent throttling. | Medium-high. | Keep |
|
||||
|
||||
## Restrictions Assessment
|
||||
|
||||
| Restriction | Current Values | Researched Values / Evidence | Cost / Timeline Impact | Status |
|
||||
|-------------|----------------|------------------------------|------------------------|--------|
|
||||
| Camera source of truth | `restrictions.md` pins ADTi 20MP ~5472 x 3648 | User confirmed `restrictions.md` is authoritative. Lens/FOV remains a design parameter. | Medium during module selection. | Updated |
|
||||
| Fixed nadir camera | No gimbal stabilization | Good for orthorectification; turn/tilt requires attitude compensation and failure detection. | Medium. | Keep |
|
||||
| Terrain/weather | Flat steppe/agricultural, seasonal classes included | Repetitive fields and seasonal changes are VPR hazards; validation must include those classes. | High validation cost. | Updated |
|
||||
| Satellite Service boundary | Offline consumer of Suite Satellite Service | Strong separation; cache manifest and ingest-voting contract are required. | Medium. | Keep |
|
||||
| 10 GB cache | Includes imagery, manifests, overviews, descriptors unless split | Plausible at 0.5 m/px with compression; 0.3 m/px plus descriptors may exceed unless pruned. | Medium. | Updated |
|
||||
| Jetson Orin Nano Super | 67 TOPS INT8, 8 GB, 25 W | Official specs support the restriction; thermal throttling remains a risk. | Medium-high. | Keep |
|
||||
| Test data gap | Sample imagery lacks IMU/ground truth | Public datasets help prototype, but final acceptance needs synchronized representative data. | High. | Updated |
|
||||
|
||||
## Key Findings
|
||||
|
||||
1. Use a hybrid estimator: VO/IMU for frame propagation, satellite/VPR anchors for absolute correction, ESKF covariance as the safety gate.
|
||||
2. Do not run heavy VPR/re-ranking every frame; invoke it on cold start, VO failure, covariance growth, sharp turns, and disconnected segments.
|
||||
3. Avoid GPL libraries in production dependencies unless the project accepts GPL obligations. GPL VIO/SLAM tools should be benchmarks or references, not selected production components.
|
||||
4. The cache must be designed as imagery + metadata + descriptor index, not just raster tiles.
|
||||
5. ArduPilot Plane SITL and representative camera+IMU data are blocking validation dependencies, but not blockers for solution drafting.
|
||||
|
||||
## Sources
|
||||
|
||||
See `_docs/00_research/01_source_registry.md` for the detailed source list.
|
||||
@@ -1,145 +1,253 @@
|
||||
# Question Decomposition
|
||||
|
||||
## Classification
|
||||
> Mode A Phase 2 (Initial Research — Problem & Solution Draft).
|
||||
> Phase 1 (AC & Restrictions Assessment) was skipped per user decision after a cleanup pass that stripped implementation details from `acceptance_criteria.md` and `restrictions.md` (commit `12cc5a4`); AC/restrictions are treated as fixed inputs.
|
||||
|
||||
- **Original question**: Design a GPS-denied onboard localization system for a fixed-wing UAV using a nadir camera, IMU, preloaded satellite imagery, and ArduPilot `GPS_INPUT`.
|
||||
- **Active mode**: Mode A Phase 2, initial solution research.
|
||||
- **Research output class**: Technical-component selection.
|
||||
- **Question type**: Decision support with knowledge organization.
|
||||
- **Timeliness sensitivity**: High for VPR, embedded AI inference, and MAVLink/ArduPilot integration; medium for geometry and filtering fundamentals.
|
||||
## Original Question
|
||||
|
||||
## Research Boundary
|
||||
Design the GPS-denied onboard navigation system for a fixed-wing UAV operating in eastern/southern Ukraine, satisfying every AC in `_docs/00_problem/acceptance_criteria.md` under the constraints in `_docs/00_problem/restrictions.md`. Recommend a concrete component-by-component architecture and tech stack.
|
||||
|
||||
## Research Output Class
|
||||
|
||||
**Technical-component selection.** All technical-component gates apply (per-mode API capability verification, Component Applicability Gate, Restrictions × Candidate-Mode sub-matrix, MVE evidence, mandatory `context7` lookups for every lead library/SDK candidate).
|
||||
|
||||
## Question Type
|
||||
|
||||
**Decision Support** (per Mode A Phase 2 default). Sub-flavour: multi-component decision support — weighing trade-offs across ~10 interlocking component areas under hard real-time + memory + safety budgets.
|
||||
|
||||
## Project Context Summary (from `_docs/00_problem/`)
|
||||
|
||||
- **What is being built**: an onboard companion-PC system that replaces real GPS for a fixed-wing UAV when GPS is denied/spoofed, by combining nav-camera frames + FC IMU + a pre-cached satellite tile basemap, and emits standard MAVLink external-positioning messages to ArduPilot or iNav at frame rate.
|
||||
- **Operating area**: eastern/southern Ukraine, active-conflict zones (war-zone scene change is a first-class concern, not an edge case).
|
||||
- **Mission profile**: 8-hour fixed-wing flights, ~60 km/h cruise, ≤1 km AGL, ~400 km² operational area.
|
||||
- **Pinned external deps**: ADTi 20MP 20L V1 nav camera (APS-C); Jetson Orin Nano Super 8 GB / 25 W; MAVLink protocol; ArduPilot + iNav as supported FCs; QGroundControl as GCS; Azaion Suite Satellite Service (offline cache interface ≥0.5 m/px).
|
||||
- **Hard runtime envelope**: <400 ms p95 end-to-end latency (camera → MAVLink), <8 GB shared CPU+GPU RAM, 25 W TDP at +50 °C ambient for 8 h continuous, no in-flight network, 10 GB persistent tile cache + 64 GB per-flight FDR.
|
||||
- **Hard safety envelope**: P(error >500 m) <0.1 % per flight, P(error >1 km) <0.01 % per flight; honest covariance reporting; explicit `dead_reckoned` failsafe under simultaneous GPS spoof + visual blackout; cache-poisoning probability bounds for tiles written back to the Service.
|
||||
|
||||
## Project Constraint Matrix
|
||||
|
||||
| Dimension | Binding constraint |
|
||||
|---|---|
|
||||
| **Inputs available** | Nav camera frames @ 3 fps (5472×3648, ~12 cm/px GSD @ 1 km AGL); FC IMU (high rate via MAVLink); FC attitude/airspeed/altitude; pre-cached satellite tiles ≥0.5 m/px (offline); operator re-loc hint via GCS (rare). |
|
||||
| **Outputs required** | WGS84 position to FC via MAVLink external-positioning message(s) accepted by ArduPilot AND iNav; per-frame estimate carrying honest 95 % covariance, source label `{satellite_anchored, visual_propagated, dead_reckoned}`, and `last_satellite_anchor_age_ms`; mid-flight ortho-tiles written to local cache with quality metadata; 1–2 Hz GCS summary; FDR records per AC-NEW-3. |
|
||||
| **Hardware fixed** | Jetson Orin Nano Super (67 TOPS sparse INT8, 8 GB shared LPDDR5, 25 W TDP, JetPack/CUDA/TensorRT). |
|
||||
| **Lifecycle** | Real-time embedded; offline (no in-flight network); 8 h continuous; persistent tile cache across flights; FDR rollover. |
|
||||
| **Non-functional** | <400 ms p95 latency; <8 GB shared RAM; ≤25 W power at +50 °C ambient; AC-1.1/1.2 accuracy; AC-2.1/2.2 registration & MRE; AC-3.x resilience; AC-NEW-1 cold-start <30 s; AC-NEW-2 spoof promotion <3 s; AC-NEW-4 false-position safety; AC-NEW-7 cache-poisoning safety; AC-NEW-8 blackout failsafe. |
|
||||
| **Hard disqualifiers** | Anything requiring >8 GB RAM peak (CPU+GPU shared); anything not runnable under JetPack on Orin Nano Super; anything requiring in-flight cloud calls; anything that cannot honestly report covariance; anything that does not have a runnable example for monocular nadir UAV input over season-matched satellite tiles; anything whose license blocks military / dual-use deployment. |
|
||||
|
||||
## Research Subject Boundary
|
||||
|
||||
| Dimension | Boundary |
|
||||
|-----------|----------|
|
||||
| Population | Fixed-wing UAV missions; not multirotor hover workflows. |
|
||||
| Geography | Eastern/southern Ukraine operational areas east/left of the Dnipro River. |
|
||||
| Timeframe | Current implementation target with 2024-2026 component evidence where possible. |
|
||||
| Level | Onboard real-time production system, not offline post-processing. |
|
||||
| Operating context | 8 h flight, 60 km/h, <=1 km AGL, 3 fps nav camera, Jetson Orin Nano Super, GPS denied/spoofed. |
|
||||
| Required interfaces | Offline Satellite Service cache in; MAVLink `GPS_INPUT`, QGC telemetry, FDR records, and object-coordinate API out. |
|
||||
| Non-functional envelope | <400 ms p95, <8 GB shared memory, 10 GB persistent cache target, 64 GB FDR cap, safety covariance and false-position budgets. |
|
||||
|---|---|
|
||||
| **Population** | Fixed-wing UAVs, downward-fixed monocular nav camera, Jetson-class edge HW, ArduPilot or iNav autopilot. Excludes: multirotors, gimbal-stabilised nav cams, server/cloud GPS-denied stacks, PX4 (out of scope), commercial sat-imagery direct integration (Service handles upstream). |
|
||||
| **Geography** | Eastern/southern Ukraine — agricultural steppe, active-conflict scene change. Validation must include this geography or representative analogues (low-texture cropland, snow, war-zone destruction). |
|
||||
| **Timeframe** | Production deployment 2026; tools / libraries / models considered must be currently maintained (commits/releases in last 18 months OR explicit long-term-stable status). Critical-novelty domain — see Step 0.5 timeliness assessment. |
|
||||
| **Operating context** | Real-time embedded; offline in-flight; 8 h continuous duty; 25 W power envelope; 8 GB shared CPU+GPU memory; thermal envelope to +50 °C ambient. |
|
||||
| **Required interfaces** | Inputs: ADTi 20MP nav cam, FC IMU (MAVLink), satellite tile cache. Outputs: MAVLink external-positioning to ArduPilot AND iNav; QGroundControl summary; FDR; tile write-back to Suite Service on landing. |
|
||||
| **Non-functional envelope** | Per AC-1 to AC-8 plus AC-NEW-1 to AC-NEW-8. Hardest binding constraints: 400 ms p95 end-to-end; 8 GB shared RAM; AC-NEW-4 false-position probability bounds; AC-NEW-7 cache-poisoning probability bounds. |
|
||||
|
||||
## Project Constraint Matrix Summary
|
||||
## Sub-Questions
|
||||
|
||||
| Constraint Area | Binding Constraint |
|
||||
|-----------------|-------------------|
|
||||
| Camera | ADTi 20MP 20L V1, APS-C, ~5472 x 3648, fixed nadir, no gimbal stabilization. |
|
||||
| Sensors | FC IMU/attitude/airspeed/altitude available over MAVLink; original still-image sample lacks synchronized IMU, while Derkachi replay data now provides synchronized IMU and `GLOBAL_POSITION_INT` trajectory. |
|
||||
| Reference imagery | Offline cache only, 0.5 m/px minimum and 0.3 m/px ideal, freshness gates, no in-flight provider fetch. |
|
||||
| Runtime | Jetson Orin Nano Super, CUDA/TensorRT available, 25 W thermal envelope. |
|
||||
| Autopilot | ArduPilot only, v1 emits `GPS_INPUT` only; ODOMETRY intentionally disabled. |
|
||||
| Storage | No raw frame retention; tiles + FDR only. Descriptor/index storage must be budgeted. |
|
||||
| Safety | Reject weak anchors, never under-report covariance, fail/degrade honestly in blackout and spoofing. |
|
||||
| Hard disqualifiers | Per-frame heavy VPR without profiling, runtime dependence on external network, stale-tile confident anchors, GPL production dependency unless licensing is accepted. |
|
||||
| ID | Sub-question |
|
||||
|---|---|
|
||||
| SQ1 | What existing/competitor GPS-denied UAV navigation systems exist (academic + open-source + commercial + military), and which of them have been validated on fixed-wing UAVs in active-conflict environments? What works, what fails? |
|
||||
| SQ2 | What is the canonical decomposition of "monocular nadir UAV ↔ pre-cached satellite basemap localization" into pipeline components? Is the decomposition below complete, or are there industry-standard components missing? |
|
||||
| SQ3 | For each component (VO/VIO, VPR, cross-domain registration, single-frame orthorectification, sensor-fusion estimator, tile cache + spatial index, on-Jetson inference runtime, MAVLink FC adapter, dataset/SITL validation infrastructure): what option families exist (simple baseline / production / open-source / commercial / SOTA / adjacent-domain / no-build), and what are the leading candidates as of 2026? |
|
||||
| SQ4 | For each lead candidate per component: what are the documented runtime/memory/latency/license/maintenance constraints, and how do they bind against the Project Constraint Matrix? Per-mode API capability verification with `context7` for every library/SDK lead. |
|
||||
| SQ5 | What are the documented failure modes and real-world deployment lessons for each component family? In particular: VPR collapse under cropland repetition, DINOv2/foundation-model cost on Jetson at int8, RANSAC degeneracy at sharp turns / low texture, EKF over-confidence on cross-domain matches, ortho geometric error from unknown bank/pitch. |
|
||||
| SQ6 | How do **ArduPilot Plane** (current stable) and **iNav** (current stable) each accept external positioning input via MAVLink? What message types does each support? Where do their interfaces diverge, and what is the documented status of each interface (stable / experimental / known bugs)? |
|
||||
| SQ7 | What public datasets, benchmarks, and SITL/replay environments exist for cross-validating monocular nadir UAV navigation against satellite basemaps in season-matched + change-affected conditions? AerialVL, AerialExtreMatch, others? |
|
||||
| SQ8 | What are the security and safety considerations specific to the AC-NEW-4 (false-position) and AC-NEW-7 (cache-poisoning) safety budgets, including spoofing-detection signals from FC, ortho-tile geo-alignment quality estimation, and write-back cache-poisoning controls? |
|
||||
| SQ9 | What does the system look like end-to-end — wiring, scheduling, threading model, inference scheduling on shared CPU+GPU memory, cold-start sequencing, FDR rotation, and pre-flight cache provisioning workflow? (synthesis question, answered in Step 8) |
|
||||
|
||||
## Perspectives
|
||||
## Component Areas (search plan)
|
||||
|
||||
| Perspective | Focus |
|
||||
|-------------|-------|
|
||||
| Operator / mission user | Does the system keep the UAV navigable and report honest confidence under spoofing/blackout? |
|
||||
| Embedded implementer | Can the pipeline fit <400 ms p95 and <8 GB on Jetson with maintainable interfaces? |
|
||||
| Safety reviewer | Are false-position and cache-poisoning paths gated before they can steer the FC or poison future caches? |
|
||||
| Field practitioner | Will seasonal agricultural repetition, turns, haze/smoke, and stale imagery break the architecture? |
|
||||
| Contrarian | Which attractive libraries or SOTA models fail because of licensing, memory, latency, or input mismatch? |
|
||||
For each component below, the search plan covers all option families per `Component Option Search Plan` rules (`research/steps/03_engine-investigation.md` → "Component Option Breadth").
|
||||
|
||||
## Sub-Questions And Query Variants
|
||||
| # | Component area | Required outputs | Key option families to enumerate |
|
||||
|---|----------------|------------------|----------------------------------|
|
||||
| C1 | **Visual / Visual-Inertial Odometry** (frame-to-frame motion when satellite anchor is unavailable) | Relative 6-DoF pose between consecutive frames or short windows; output frequency ≥3 Hz; metric scale (with IMU) | Classical (VINS-Mono / VINS-Fusion / OpenVINS), Kimera, ORB-SLAM3, OKVIS2, MSCKF-class, learning-based (DROID-SLAM, DPVO), pure VO baseline (KLT + RANSAC homography), no-build (skip and rely on pure satellite re-anchor every frame) |
|
||||
| C2 | **Visual Place Recognition (VPR)** — UAV nadir frame → top-K satellite chunks | Compact global descriptor per UAV frame and per cache chunk; cosine-rank top-K candidates | NetVLAD class, MixVPR, EigenPlaces, BoQ, AnyLoc (DINOv2 + VLAD), CricaVPR, foundation-model direct retrieval (DINOv2/DINOv3/SAM 2 / SuperGlobal) |
|
||||
| C3 | **Cross-domain registration** (UAV nadir ↔ ortho satellite tile, after VPR top-K) | Sub-pixel alignment + 6-DoF camera pose w.r.t. tile, with inlier ratio + covariance | Local-feature matching (SuperPoint+SuperGlue / LightGlue / DISK+LightGlue / ALIKED+LightGlue / XFeat), dense matchers (LoFTR / RoMa / DKM / MASt3R), classical (SIFT+RANSAC), specialized cross-domain (CMRNet+, CroCoMatch class), templating (mutual-information / ECC), no-build (skip cross-domain; rely on direct frame-to-tile homography from VPR retrieval) |
|
||||
| C4 | **Single-frame orthorectification** (nav frame → basemap-aligned tile, given current pose) | Ortho-rectified tile chunk with geo metadata + quality score | Single-frame perspective warp with flat-earth assumption; OpenCV homography; bundled-DEM-aware (rare for flat steppe — likely overkill); GDAL warp utilities; custom GPU shader on Jetson |
|
||||
| C5 | **State estimator / sensor fusion** (VO + IMU + sat anchors → fused estimate with covariance) | WGS84 position + 3D velocity + attitude + 6×6 covariance, frame-rate output, honest covariance, source label | EKF (manual), ESKF (manual or via library), MSCKF, factor-graph (GTSAM, iSAM2), particle filter, learned (out-of-scope for safety budget). Supporting: Mahalanobis outlier gates |
|
||||
| C6 | **Tile cache + spatial index** (storage + retrieval of basemap tiles + descriptors, with manifests, freshness, dedup, and write-back) | mmap-friendly storage; ANN over global descriptors; spatial query for geographic prior; manifest schema per AC | Storage: GeoTIFF + COG, MBTiles, custom flat layout. ANN: FAISS (IVF/PQ/HNSW), hnswlib, ScaNN, brute-force (small index). Spatial: R-tree / KD-tree / GeoPandas / SQLite+SpatiaLite. Manifest: SQLite, JSON-per-tile, Parquet sidecar |
|
||||
| C7 | **On-Jetson inference runtime** | INT8/FP16 inference of the chosen VPR + matcher models within latency + memory budget | TensorRT (native), Torch-TensorRT, ONNX Runtime + TRT EP, NVIDIA Triton (probably overkill), pure PyTorch fp16, NVIDIA DeepStream (for video), CUDA-Python custom kernels |
|
||||
| C8 | **MAVLink FC adapter** (per-FC external-positioning emission + spoofing-signal subscription, for ArduPilot AND iNav) | MAVLink frames consumed by ArduPilot Plane and iNav as external position; spoofing signals consumed from each FC | Libraries: `pymavlink` (per-message), MAVSDK (high-level), ArduPilot/iNav SITL for verification. Per-FC choice of message: `GPS_INPUT` vs `ODOMETRY` vs `VISION_POSITION_ESTIMATE` vs `GLOBAL_POSITION_INT` (documented capability per FC must be verified, not assumed) |
|
||||
| ~~C9~~ | ~~**Datasets + SITL / replay**~~ — **DROPPED from research scope per 2026-05-08 restructure (user choice A)**; deferred to **Test Spec (greenfield Step 5)**. See "C9 / SQ7 Restructure" section below. | — | — |
|
||||
| C10 | **Pre-flight cache provisioning + sector classification + freshness pipeline** (RESEARCH SCOPE NARROWED 2026-05-08 to cross-coupling minimal — see "C10 Scope Restructure" section below) | (in research scope) confirmed orchestration mechanism for descriptor-cache rebuild (D-C6-3) + TensorRT engine build (D-C7-7) at pre-flight; on-disk artifact format(s); time/memory budget; failure-mode + retry behavior. (deferred to Plan-phase) operator CLI/desktop tool design, sector classification heuristics, freshness pipeline workflow. | (in research scope) FAISS Python API for write_index/read_index orchestration; TensorRT build orchestration `trtexec` CLI vs Python `IBuilderConfig` vs Polygraphy. (deferred) custom CLI/desktop, QGC plan files, MAVProxy, Mission Planner integration patterns. |
|
||||
|
||||
1. What architecture bounds drift while GPS is denied?
|
||||
- fixed-wing UAV GPS-denied satellite image matching visual odometry
|
||||
- visual odometry satellite imagery accumulated error fixed wing UAV
|
||||
- monocular VIO aerial navigation scale ambiguity satellite anchor
|
||||
- GPS spoofed UAV visual inertial navigation covariance failover
|
||||
## Perspectives Chosen (≥3 mandatory)
|
||||
|
||||
2. Which VO/VIO approach fits one nadir camera + IMU?
|
||||
- OpenVINS monocular visual inertial odometry Jetson
|
||||
- ORB-SLAM3 monocular inertial Jetson UAV limitations
|
||||
- VINS-Fusion fixed wing monocular IMU outdoor aerial
|
||||
- homography visual odometry nadir UAV IMU fusion
|
||||
1. **Implementer / Engineer** — Will the chosen stack actually compile, link, and run on the pinned Jetson within the latency + memory budget? Pitfalls of MAVLink GPS injection on each FC. Sub-pixel registration on UAV-nadir × ortho satellite. Inference-scheduler contention on shared CPU+GPU memory.
|
||||
2. **Practitioner / Field** — What do UAV teams actually report from GPS-denied missions in real war-zone deployments? (Ukraine context if findable; otherwise analogous high-stakes deployments.) Real-world VPR collapse on agricultural cropland / snow / season change. Real-world FDR usefulness for post-mission forensics.
|
||||
3. **Domain expert / Academic** — Recent (2024–2026) VPR + cross-domain matching benchmarks and their relative ranks under cross-season / cross-domain / cross-altitude conditions. Foundation-model-based VPR (AnyLoc, BoQ, MASt3R) — academic claims vs reproducibility. Recent factor-graph vs ESKF comparisons.
|
||||
4. **Contrarian / Devil's advocate** — Why might foundation-model VPR fail on the Jetson budget? Where does cross-domain matching degrade silently? When does ortho-tile write-back amplify bad poses? When does honest covariance turn into "system never trusts itself" (over-cautious failure)?
|
||||
|
||||
3. Which satellite retrieval and matching approach fits offline cache + <400 ms?
|
||||
- aerial visual place recognition survey DINOv2 FAISS
|
||||
- DINOv2 VLAD aerial VPR embedded memory
|
||||
- LightGlue SuperPoint DISK ALIKED TensorRT Jetson
|
||||
- cross-view UAV satellite matching failure modes farmland
|
||||
## Search Query Variants per Sub-Question
|
||||
|
||||
4. How should the estimator and safety modes work?
|
||||
- ESKF visual inertial GPS denied UAV covariance
|
||||
- GPS_INPUT horiz_accuracy covariance external GPS ArduPilot
|
||||
- visual blackout IMU dead reckoning UAV covariance growth
|
||||
- false position rejection Mahalanobis gate visual localization
|
||||
(Detailed query lists are appended below per sub-question; these will be executed in Step 2 and saved to the `01_source_registry/` folder, indexed by `01_source_registry/00_summary.md`. The shape is shown here so the search plan is auditable; the full execution log will populate downstream files.)
|
||||
|
||||
5. What cache format and data contract fit the onboard/Satellite Service boundary?
|
||||
- COG PMTiles MBTiles offline raster cache embedded
|
||||
- satellite tile descriptor index storage FAISS PMTiles
|
||||
- cloud optimized geotiff local update limitations
|
||||
- PMTiles read only update PostgreSQL/PostGIS-backed raster cache
|
||||
**SQ1** (existing systems / competitors): "GPS-denied UAV navigation 2025", "visual GPS denied fixed wing UAV", "satellite map matching UAV localization 2024 2025", "Ukraine UAV GPS spoofing countermeasures", "ARL ANT Project visual navigation", "vision-based GPS replacement UAV production", "UAV GPS spoofing real-world deployment 2025".
|
||||
|
||||
6. How should MAVLink output integrate with ArduPilot Plane?
|
||||
- ArduPilot GPS_INPUT GPS1_TYPE 14 Plane SITL
|
||||
- pymavlink gps_input_send external GPS example
|
||||
- MAVSDK GPS_INPUT support raw MAVLink
|
||||
- ArduPilot EKF GPS glitch spoof failsafe Plane parameters
|
||||
**SQ2** (canonical pipeline): "visual aerial localization pipeline survey", "UAV satellite map matching architecture", "monocular UAV global localization pipeline 2024 2025".
|
||||
|
||||
7. What validation datasets and tests are needed?
|
||||
- AerialVL UAV satellite visual localization dataset
|
||||
- VPAir aerial visual place recognition dataset
|
||||
- EuRoC MAV visual inertial odometry dataset
|
||||
- ArduPilot Plane SITL fake GPS spoofing simulation
|
||||
**SQ3 / SQ4** (per-component candidates + binding): per-component query templates (5+ variants each) — see Step 2 plan in `01_source_registry/00_summary.md` once initialised. Each lead library/SDK candidate triggers the mandatory `context7` per-mode capability verification per `research/steps/03_engine-investigation.md`.
|
||||
|
||||
## Component Option Search Plan
|
||||
**SQ5** (failure modes): "VPR cropland failure", "DINOv2 Jetson Orin Nano latency", "SuperGlue LightGlue Jetson Orin", "ESKF cross-domain over-confidence", "RANSAC homography low-texture failure UAV", "ortho photo geometric error airframe tilt".
|
||||
|
||||
| Component Area | Option Families / Candidates | Evidence Needed |
|
||||
|----------------|------------------------------|-----------------|
|
||||
| Camera calibration and geometry | OpenCV calibration/homography; custom NumPy geometry; ROS camera pipeline | Official API for intrinsics, distortion, homography, RANSAC; permissive licensing; Jetson compatibility. |
|
||||
| VO / VIO propagation | OpenVINS, ORB-SLAM3, VINS-Fusion, custom homography+IMU ESKF | Exact monocular+IMU input fit, output pose/covariance, licensing, runtime, initialization behavior. |
|
||||
| VPR global retrieval | DINOv2-VLAD/AnyLoc, MixVPR/SALAD/SelaVPR, classical NetVLAD/BoW | Aerial benchmark evidence, descriptor size, offline index fit, embedded feasibility. |
|
||||
| Local cross-domain matching | LightGlue + DISK/ALIKED, SuperPoint+LightGlue, LoFTR/XFeat, SIFT/ORB baseline | Inputs/outputs, match coordinates, license, runtime knobs, TensorRT/Jetson feasibility. |
|
||||
| Vector index | FAISS CPU/GPU, PostgreSQL/pgvector metadata-assisted search, Annoy/HNSWLIB | Top-K retrieval, saved index, memory/compression knobs, ARM/Jetson feasibility. |
|
||||
| Estimator | Custom ESKF, factor graph, robot_localization | Covariance output, mode labels, Mahalanobis gates, source-specific update control. |
|
||||
| Cache/storage | COG, PostgreSQL/PostGIS manifest, PMTiles, MBTiles, raw tile folders | Offline read/update behavior, storage efficiency, metadata/manifest support. |
|
||||
| MAVLink integration | pymavlink, MAVSDK, MAVProxy bridge | `GPS_INPUT` support, ArduPilot `GPS1_TYPE=14`, telemetry subscriptions, QGC status. |
|
||||
| FDR | PostgreSQL event index, Parquet export, CBOR segment files | Streaming writes, rollover, compact typed records, replayability. |
|
||||
**SQ6** (ArduPilot vs iNav external positioning): "ArduPilot Plane GPS_INPUT external", "ArduPilot ODOMETRY EKF3 source switching", "iNav external positioning MAVLink GPS_INPUT", "iNav MAVLink GPS substitute", "iNav GPS denied flight 2025", "ArduPilot vs iNav external nav comparison".
|
||||
|
||||
**SQ7** (datasets): "AerialVL dataset", "AerialExtreMatch", "VPR-Bench cross-season aerial", "Mid-Air UAV dataset", "Mavic Mavik UAV public flight dataset", "satellite-aerial cross-view localization benchmark".
|
||||
|
||||
**SQ8** (safety): "MAVLink GPS_RAW_INT spoofing detection", "EKF lane switch ArduPilot", "covariance under-reporting risk EKF", "geo-misalign detection ortho tile".
|
||||
|
||||
## Completeness Audit
|
||||
|
||||
- **Cost/resources**: covered by Jetson, cache, thermal, and descriptor storage constraints.
|
||||
- **Legal/licensing**: covered; GPL VIO/SLAM tools are not selected for production.
|
||||
- **Dependencies**: Satellite Service cache contract, ArduPilot Plane SITL, and synchronized validation data are explicit dependencies.
|
||||
- **Operating environment**: fixed-wing, altitude, terrain, seasonal/visibility classes, and blackout cases covered.
|
||||
- **Failure modes**: VO failure, stale tiles, spoofing, blackout, thermal throttling, false anchors, cache poisoning covered.
|
||||
- **Practitioner concerns**: real-time embedded performance and dataset mismatch covered through survey and benchmark sources.
|
||||
- **Change over time**: DINOv2/VPR models and Jetson/TensorRT assumptions require version-pinned profiling during implementation.
|
||||
Probes (per `references/comparison-frameworks.md` → Decomposition Completeness Probes — applied here without re-reading the full file; will reconcile during Step 2):
|
||||
|
||||
## Mode B Round 2 Addendum — User-Requested Technology Check
|
||||
| Probe | Coverage |
|
||||
|---|---|
|
||||
| Functional decomposition complete? | C1–C10 cover all data flows from camera in to MAVLink out + back. ✓ |
|
||||
| Non-functional dimensions covered? | Latency, memory, accuracy, safety, freshness, security all in Project Constraint Matrix. ✓ |
|
||||
| Failure-mode dimension covered? | SQ5 explicitly. ✓ |
|
||||
| Cost / TCO dimension? | Hardware is pinned (Jetson Orin Nano Super); Service-side cost is out of scope; SW cost = mostly open-source candidates. Will revisit during Phase 3 (tech stack consolidation) if commercial options emerge. ✓ |
|
||||
| Maintenance / community-health dimension? | SQ4 binds it per candidate. ✓ |
|
||||
| Adjacent-domain dimension? | Robot SLAM, AGV warehouse navigation, aerial photogrammetry will be searched as analogues. ✓ |
|
||||
| Validation / dataset coverage? | **Deferred to Test Spec (greenfield Step 5) per 2026-05-08 C9 / SQ7 restructure** — fixture-class, not research-class. Dataset shortlist preserved for handoff. |
|
||||
| Integration / boundary coverage? | SQ6 (FC adapters) + C8 + C10 (pre-flight provisioning). ✓ |
|
||||
| Operational/human-factors? | Pre-flight cache provisioning (C10) and operator re-loc hint (AC-3.4) covered. Mission-planning UX is out of scope. ✓ |
|
||||
| Security / threat model? | SQ8. Will deepen in Phase 4 (Security Deep Dive) if invoked. ✓ |
|
||||
|
||||
### Research Output Class
|
||||
No major gap detected at decomposition time. If domain-discovery searches in Step 2 surface a missed dimension, a "gap-fill" entry will be appended here.
|
||||
|
||||
Technical-component selection. The addendum verifies two implementation choices before autodev proceeds to planning:
|
||||
## Notes on Output-Class Mode-Verification
|
||||
|
||||
1. Whether OpenVINS should replace the custom OpenCV-based VO/ESKF direction.
|
||||
2. Whether DINOv2-VLAD + ALIKED/LightGlue is still the right satellite retrieval and anchor-verification stack.
|
||||
Because this is **Technical-component selection**, every lead library/SDK candidate triggers:
|
||||
- Pinned mode/configuration sentence in `02_fact_cards/Cx_*.md` (per-component sub-files).
|
||||
- `context7` lookup with the three mandatory queries (mode enumeration; project's exact mode runnable example; disqualifier probe).
|
||||
- MVE block per candidate.
|
||||
- Per-numbered-Restriction and per-numbered-AC binding (`Pass` / `Fail` / `Verify` / `N/A`).
|
||||
- Two modes of one library = two distinct candidates.
|
||||
|
||||
### Boundary Clarification
|
||||
## Step 0.5 — Novelty Sensitivity Assessment
|
||||
|
||||
"Custom OpenCV" is treated as OpenCV for calibration, undistortion, feature geometry, homography/RANSAC, and MRE measurement, plus a project-owned ESKF/mode machine. It is not treated as a naive OpenCV-only replacement for VIO.
|
||||
**Classification: Critical sensitivity.**
|
||||
|
||||
### Additional Query Variants Executed
|
||||
Justification:
|
||||
- Foundation-model VPR is moving fast: DINOv2 (Apr 2023), AnyLoc (Aug 2023), BoQ (CVPR 2024), MASt3R (May 2024), MASt3R-SfM / new VPR-leader candidates 2025; rankings on cross-season aerial benchmarks have shifted multiple times since 2023.
|
||||
- ArduPilot Plane / iNav external-positioning interfaces have moved: ArduPilot EKF3 source-switching parameters and known double-fusion bugs between `GPS_INPUT` and `ODOMETRY` were a moving target through 2024–2025; iNav GPS-denied support has matured separately.
|
||||
- TensorRT / JetPack stacks on Jetson Orin Nano Super have version-dependent INT8 quantisation behaviour and runtime tooling differences worth verifying against current releases.
|
||||
- Public aerial-localization datasets (AerialVL, AerialExtreMatch, etc.) have had multiple revisions and added splits.
|
||||
|
||||
- OpenVINS GPL-3 license MSCKF visual inertial odometry documentation monocular IMU 2026
|
||||
- OpenVINS visual inertial odometry GPS denied UAV MSCKF limitations monocular high altitude nadir camera
|
||||
- why not use OpenVINS production GPL ROS dependency visual inertial odometry limitations
|
||||
- OpenCV license BSD 3-Clause camera calibration findHomography RANSAC documentation 4.x
|
||||
- custom visual odometry OpenCV homography IMU EKF fixed wing UAV satellite imagery GPS denied 2024
|
||||
- DINOv2 VLAD AnyLoc visual place recognition aerial satellite retrieval benchmark 2024 2025
|
||||
- DINOv2 VLAD limitations visual place recognition storage compute AnyLoc limitations
|
||||
- DINOv2 TensorRT Jetson performance issue embedding accuracy visual place recognition
|
||||
- ALIKED LightGlue license local feature matching aerial image registration 2024 2025
|
||||
- ALIKED LightGlue ONNX TensorRT Jetson performance benchmark local feature matching
|
||||
- aerial visual place recognition survey 2024 runtime memory re-ranking SuperGlue LightGlue satellite UAV retrieval
|
||||
Source-time-window rules for this run:
|
||||
- **Lead-candidate selection / SOTA claims**: prioritise sources from **last 6 months**; allow up to **18 months** if no newer source covers the same claim and the older source is the official authority.
|
||||
- **Established baselines / classical algorithms** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window — canonical references are fine.
|
||||
- **Library/SDK API behaviour**: must be verified against the **currently shipped version** at the time of search (`context7` mandatory per lead candidate; release notes / changelog cross-checked).
|
||||
- **Cross-validation**: every Critical-sensitivity claim that drives a candidate selection must have **≥2 independent sources** or one official + one runnable MVE; single-source SOTA claims must be downgraded to `Experimental only` at Step 7.5 unless cross-validated.
|
||||
|
||||
### Addendum Conclusion
|
||||
## SQ2 Closure — Pipeline-component coverage table (Mode A Phase 2, Step 3 result)
|
||||
|
||||
OpenVINS is better than a pure custom OpenCV-only VIO implementation, but the production architecture should keep OpenCV as the utility layer and keep the project-owned ESKF/mode machine as the shipped estimator. OpenVINS becomes a mandatory benchmark/reference because it does not own the satellite anchor, spoofing/blackout, source-label, cache-write, and MAVLink semantics required by the acceptance criteria, and GPLv3 remains a production dependency blocker.
|
||||
The C1–C10 decomposition was sanity-checked against five independent surveys/benchmarks (Skoltech aerial-VPR survey, U.Maine cross-view survey, OrthoLoC benchmark, AnyVisLoc benchmark, NUDT 2026 absolute-VL survey — all logged in `01_source_registry/SQ2_canonical_pipeline.md` as Sources #38–#42). The canonical hierarchical framework `retrieval → matching → pose-estimation` is unanimously confirmed; project's split is **canonical, not novel**. Two augmentations are required.
|
||||
|
||||
DINOv2-VLAD + CPU-first FAISS + ALIKED/LightGlue remains the preferred anchor stack, with two non-negotiable constraints: retrieval is trigger-based rather than per-frame, and TensorRT/ONNX optimizations are accepted only after descriptor-fidelity and Jetson latency tests.
|
||||
| Survey/benchmark canonical stage | Project component | Coverage status | Required action |
|
||||
|---|---|---|---|
|
||||
| Image retrieval (global VPR) | **C2 — VPR** | ✅ covered | None |
|
||||
| Re-ranking (top-N inlier-based) | (implicit, inside C2/C3) | ⚠️ implicit | Promote to explicit sub-stage in `solution_draft01` |
|
||||
| Local image matching (2D-2D, sparse or dense) | **C3 — Cross-domain registration** | ✅ covered | Add Top-N inlier re-rank requirement |
|
||||
| AdHoP-style perspective preconditioning | (not represented) | ❌ missing | Add as optional sub-stage between C3 and C4, gated on Jetson latency budget |
|
||||
| 2D-3D lift via DSM | (not represented; current cache is 2D ortho only) | ❌ architectural decision required | **Decision required from user** — see "Open architectural decisions" below |
|
||||
| Pose estimation (PnP + RANSAC + LM) | **C4 — Pose estimation** | ✅ covered | None |
|
||||
| State estimator / fusion | **C5 — Estimator / fusion** | ✅ covered | Augmented with covariance-honesty contract (already from AC-NEW-4) |
|
||||
| IMU + VIO contract | **C1 (VIO)** + **C6 (Tile cache)** ⁂ | ✅ covered | Add yaw σ ≤ 5°, pitch σ ≤ 5° hard contract (Fact #24) |
|
||||
| Tile cache + scheduler | **C6 (Tile cache + spatial index)** | ✅ covered | Add 20% covisibility runtime invariant (Fact #27) |
|
||||
| On-Jetson runtime | **C7 — On-Jetson inference runtime** | ✅ covered | Pre-screen prunes non-viable candidates (Fact #26) |
|
||||
| Anti-spoof / FC adapter | **C8 — MAVLink FC adapter** | ✅ covered | Already addressed by SQ6 |
|
||||
| Datasets / SITL / replay | **Deferred to Test Spec (greenfield Step 5)** per 2026-05-08 C9 / SQ7 restructure | ⚠️ moved out of research scope | Test Spec owns dataset-corpus selection, SITL framework choice (ArduPilot Plane SITL + iNav SITL/HITL), and replay framework choice |
|
||||
| Pre-flight cache provisioning | **C10 — Pre-flight cache + sector classification** | ✅ covered | None |
|
||||
|
||||
⁂ The "IMU integration" concern lives in C1 (VIO) and partially flows from FC IMU; there is no separately numbered IMU component in the original C1–C10 split. SQ2 confirms this was correct — IMU is best owned by C1 (VIO) which already produces the yaw/pitch attitude. The σ ≤ 5° contract belongs on C1's output interface.
|
||||
|
||||
### SQ2 — Architectural decisions (resolved by user, 2026-05-07)
|
||||
|
||||
| # | Decision | Choice | Implication for SQ3+SQ4 |
|
||||
|---|---|---|---|
|
||||
| 1 | DSM dependency on Suite Sat Service tile cache (Fact #23) | **(a) 3-DoF acceptance** — fix attitude from IMU/VIO, ignore DSM; current 2D-ortho cache contract preserved. | C6 (Tile cache) candidate matrix excludes DSM-dependent storage formats. C3 (matcher) candidates evaluated on 2D-2D output (homography) only. Yaw/pitch σ ≤ 5° (Fact #24) is **noted as an empirical requirement on C1's output but NOT bound as a hard interface contract** — emerges as an output of C1 candidate selection in SQ3+SQ4. AC-1.1.1 (≤80 m at 1 km AGL) likely satisfied per DSMAC-class lineage in Fact #17; if AC ever tightens, revisit option (b). |
|
||||
| 2 | AdHoP refinement loop (Fact #22) | **(b) Conditional** — only invoked when initial reprojection error exceeds a threshold. | C3 (matcher) latency budget = base (single-pass) + AdHoP-conditional overhead (worst-case 2× when triggered). Per-frame Jetson MVE must measure both modes. The reprojection-error threshold becomes a SQ3+SQ4 hyperparameter. |
|
||||
| 3 | Top-N re-rank promotion (Fact #25) | **(a) Promote** to an explicit named sub-stage between C2 and C3. | SQ3+SQ4 will hyperparameter-sweep N ∈ {5, 10, 15, 20}; C2 candidates evaluated jointly with re-rank cost. Top-N re-rank by inlier-count is now a hard pipeline component, not implicit. |
|
||||
|
||||
### SQ2 — Component-pruning carried into SQ3+SQ4 (Jetson-pre-screen result)
|
||||
|
||||
Per Fact #26 (RTX-3090-measured runtime → conservative Jetson-Orin-Nano translation):
|
||||
|
||||
- **C2 candidates entering SQ3+SQ4 with mandatory Jetson MVE**: MixVPR, SALAD, SelaVPR, EigenPlaces, NetVLAD.
|
||||
- **C2 candidates entering SQ3+SQ4 conditional on INT8 quantization path**: AnyLoc, BoQ, DINOv2-VLAD.
|
||||
- **C2 candidates pruned outright**: SuperGlue-as-reranker (latency).
|
||||
- **C3 candidates entering SQ3+SQ4 with mandatory Jetson MVE**: LightGlue, XFeat, XFeat*, SP+LightGlue (NGPS template confirmed).
|
||||
- **C3 candidates pruned outright**: RoMa, MASt3R, DKM (dense-matcher latency on Jetson).
|
||||
- **C3 candidates as "AerialExtreMatch reference points" only**: GIM+DKM, GIM+LightGlue (per Source #40 — accuracy benchmark, not for production deployment).
|
||||
|
||||
## C9 / SQ7 Restructure (2026-05-08, user choice A)
|
||||
|
||||
**Decision**: drop C9 (Datasets + SITL / replay) entirely from the research scope. Defer dataset-corpus selection, SITL framework choice (ArduPilot Plane SITL + iNav SITL/HITL), and replay framework choice (custom vs PX4-Avionics-Replay-style) to **Test Spec (greenfield Step 5)**. Pull D-C7-1 (calibration-dataset-strategy) back inside C7 batch 1 and close it there.
|
||||
|
||||
**Rationale**: datasets are test fixtures, not architectural commitments. They feed into Test Spec → Decompose Tests → Implement Tests, not into the deployed pipeline on the Jetson. They don't bind against the AC-4.1 / AC-4.2 / R-NEW-2 / R-NEW-4 envelope. Choosing among AerialVL S03 vs AerialExtreMatch vs VPR-Bench vs MahalNotchVPR / Mid-Air UAV vs the project's own Mavic + Derkachi flight footage is a "what evidence proves the system meets AC-X" question, not a "what gets implemented on the Orin Nano" question. SITL and replay framework choice are test-infra commitments rather than runtime commitments; SITL framework is largely deterministic at this point (ArduPilot Plane SITL + iNav SITL/HITL are the canonical paths the locked C8 closure already implies).
|
||||
|
||||
**Effective changes**:
|
||||
- **Component Areas table**: C9 removed; remaining components are C1–C8 + C10.
|
||||
- **Sub-Questions table**: SQ7 is deferred to Test Spec (Step 5) — its query variants and dataset shortlist remain documented here for handoff but are not researched in this Mode A run.
|
||||
- **SQ2 closure table**: "Datasets / SITL / replay" row → "Deferred to Test Spec".
|
||||
- **D-C7-1 (calibration-dataset-strategy)**: closed inside C7 batch 1. Strategy = prefer real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles as the calibration corpus distribution; specific fixture-file selection (AerialVL S03 vs project's Mavic + Derkachi clips vs other corpora) is fixture-class and delegated to Test Spec. Synthetic-tile augmentation via random homography is a documented low-data fallback, only invoked if real flight footage is insufficient for Recall@K-target calibration.
|
||||
- **Cross-component gates**: D-C7-1 is no longer cross-coupled to C9; owner narrows to Plan-phase architect (closed at research time).
|
||||
- **Cross-row dependencies in C7 / C8 fact cards and fit-matrix files**: every "C9 datasets / SITL / replay row when opened" reference becomes "Test Spec (Step 5) when opened".
|
||||
|
||||
**Carryforward to Test Spec (Step 5)** — preserved here so Test Spec's first invocation has the handoff payload ready:
|
||||
- **Dataset shortlist**: AerialVL (VISTA / NTU), AerialExtreMatch, VPR-Bench, MahalNotchVPR / Mid-Air UAV, project's own Mavic + Derkachi flights.
|
||||
- **SITL frameworks**: ArduPilot Plane SITL (canonical), iNav SITL/HITL (canonical); Gazebo / Webots noted-and-rejected as overkill for the spoof-promotion + visual-blackout failsafe scenarios that AC-NEW-2 and AC-NEW-8 actually exercise.
|
||||
- **Replay frameworks**: PX4-Avionics-Replay-style canonical reference; custom Python harness as the lightweight default if PX4 replay's MAVLink-injection point doesn't cleanly match the C8 closure's per-FC injection cadence (5 Hz GPS_INPUT for AP / 5 Hz MSP2_SENSOR_GPS for iNav).
|
||||
- **SQ7 query variants** (carried forward verbatim from above): "AerialVL dataset", "AerialExtreMatch", "VPR-Bench cross-season aerial", "Mid-Air UAV dataset", "Mavic Mavik UAV public flight dataset", "satellite-aerial cross-view localization benchmark".
|
||||
- **Test-coverage obligations Test Spec must answer**:
|
||||
- Which corpora exercise which AC (AC-1.1 / AC-1.2 / AC-2.1 / AC-2.2 / AC-3.1 / AC-3.2 / AC-3.3 / AC-3.4 / AC-NEW-1 / AC-NEW-2 / AC-NEW-4 / AC-NEW-7 / AC-NEW-8).
|
||||
- SITL test-harness shape exercising AC-NEW-2 spoof-promotion <3 s end-to-end on **both** ArduPilot Plane SITL **and** iNav SITL/HITL (per locked C8 batch 1 closure cross-component decision D-C8-2).
|
||||
- Replay-fixture format compatible with both C8 injection paths (pymavlink GPS_INPUT for AP, YAMSPy MSP2_SENSOR_GPS for iNav).
|
||||
- INT8 calibration corpus pin (specific files satisfying the C7 batch 1 D-C7-1 strategy = real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles).
|
||||
|
||||
## C10 Scope Restructure (2026-05-08, user choice C — cross-coupling minimal)
|
||||
|
||||
**Decision**: narrow C10 (Pre-flight cache provisioning + sector classification + freshness pipeline) research scope to the two cross-coupling confirmation sub-areas. Defer the operator-side CLI/desktop tool, sector classification heuristics, and tile age-stamping/freshness schema to Plan-phase as `operator tooling design` out-of-research-scope.
|
||||
|
||||
**In-scope (C10 batch 1)**:
|
||||
1. **D-C6-3 confirmation** — descriptor-cache rebuild trigger pipeline. Recommendation inherited from C6 batch 1 (Fact #92 + D-C6-3) = `periodic rebuild during C10 pre-flight provisioning + faiss.write_index serialize + load-at-takeoff in <5 s`. Confirmation work: pin the orchestration tool (FAISS Python API vs subprocess invocation), the trigger semantics (manifest hash change vs operator-manual vs new-tile-delivered), the on-disk file format, the rebuild time budget at pre-flight, and the failure-mode + retry behavior.
|
||||
2. **D-C7-7 confirmation** — TensorRT engine-build pipeline. Recommendation inherited from C7 batch 1 (Fact #94 + D-C7-7) = `primary build-on-deployed-Jetson during pre-flight + reference-Jetson-built engines as fallback`. Confirmation work: pin the build-orchestration tool (`trtexec` CLI vs Python `IBuilderConfig` vs Polygraphy), the calibration-corpus shipping mechanism into the pre-flight build (per D-C7-1 closure: real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles), the per-model build-duration budget, the retry/fallback logic on build failure, and the on-disk engine cache layout.
|
||||
|
||||
**Out-of-research-scope (deferred to Plan-phase)**:
|
||||
- Operator-side CLI/desktop tool design (mission-prep tooling shape; CLI vs GUI; integration with QGC plan files / MAVProxy / Mission Planner equivalents).
|
||||
- Sector classification (active-conflict vs stable rear) heuristics + interface — used to decide AC-8.2 freshness threshold (6 mo vs 12 mo).
|
||||
- Tile age-stamping + freshness schema beyond what AC-8.2 + AC-NEW-6 already mandate.
|
||||
|
||||
**Rationale for narrowing**:
|
||||
- The C6 and C7 closures already locked architectural recommendations (`periodic rebuild during pre-flight` and `build-on-deployed-Jetson at pre-flight`). What remains is mechanism confirmation, not candidate enumeration.
|
||||
- The deferred items are fixture/operator-tooling-class concerns. Their cross-coupling with the runtime architecture is mediated entirely by the descriptor-cache file and the TensorRT engine cache file — both fixed by the in-scope confirmations. Operator tool design can iterate freely at Plan-phase without touching runtime contracts.
|
||||
- Aligns with the C9-restructure precedent: keep research focused on architecture-binding decisions; push fixture/tooling decisions to the phases that own them.
|
||||
|
||||
**Effective changes**:
|
||||
- **Component Areas table**: C10 row preserved with reduced scope. Per-FC details below.
|
||||
- **`Required outputs` for C10 in the table**: narrows from `Tooling (operator-side) to pull tiles from Suite Sat Service for an operational area, classify active-conflict vs stable rear, age-stamp, populate descriptor index` to `Confirmed orchestration mechanism for descriptor-cache rebuild + TensorRT engine build at pre-flight; on-disk artifact format(s); time/memory budget; failure-mode + retry behavior`.
|
||||
- **Cross-component gates**: D-C6-3 and D-C7-7 remain owned jointly with C10; new C10-internal decisions D-C10-x will be added at C10 batch 1 closure.
|
||||
- **SQ5 interleaving**: limited C10 SQ5 facts (failure modes during pre-flight build/rebuild) collected during this batch.
|
||||
|
||||
**Carryforward to Plan-phase** — operator-tooling design issues preserved here so Plan-phase has a starting list:
|
||||
- Tool shape: integrate as a sub-command of Mission Planner / QGC plan-file workflow vs standalone CLI vs lightweight desktop GUI.
|
||||
- Sector-classification source: operator-marked geofence polygons vs Suite Sat Service metadata vs hybrid.
|
||||
- Tile age-stamping: per-tile capture date in manifest (already mandated by restrictions.md) vs additional sector-class tag vs full audit trail per AC-NEW-7.
|
||||
- Freshness pipeline: when to re-pull from Suite Sat Service (every flight, weekly, on operator demand, on sector-class change).
|
||||
|
||||
## Next Step
|
||||
|
||||
SQ1 ✓ → SQ2 ✓ (with three architectural decisions resolved) → **SQ3+SQ4 per component (C1→C8)** ✓ → **C10 batch 1 in progress (cross-coupling minimal scope, 2 sub-areas: D-C6-3 + D-C7-7 confirmation)** → SQ5 interleaved → SQ8 → SQ9 synthesis at engine Step 8.
|
||||
|
||||
(SQ7 deferred to Test Spec per C9 restructure; C9 dropped; C10 operator-tooling-design deferred to Plan-phase per the C10 scope restructure above.)
|
||||
|
||||
Pipeline shape (final, post-C10-restructure): `C1 (VIO) → C2 (VPR) → Top-N re-rank by inlier count → C3 (matcher) → AdHoP-conditional refinement → C4 (PnP+RANSAC+LM) → C5 (estimator) → C8 (FC adapter)` with C6 (cache, 2D ortho) + C7 (Jetson runtime) + C10 (pre-flight orchestration: descriptor-cache rebuild + TensorRT engine build) cross-cutting.
|
||||
|
||||
First C1 (VIO) candidate batch: VINS-Mono / VINS-Fusion / OpenVINS / OKVIS2 / DROID-SLAM / DPVO / pure-VO baseline (RTAB-Map and ORB-SLAM3 already pruned by Fact #16). Per-mode `context7` capability verification mandatory for every lead library/SDK candidate.
|
||||
|
||||
@@ -1,419 +0,0 @@
|
||||
# Source Registry
|
||||
|
||||
## Source #1
|
||||
- **Title**: Visual Odometry in GPS-Denied Zones for Fixed-Wing UAV with Reduced Accumulative Error Based on Satellite Imagery
|
||||
- **Link**: https://www.mdpi.com/2076-3417/14/16/7420
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: UAV visual localization researchers/implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Demonstrates fixed-wing high-altitude monocular VO corrected by satellite imagery; highlights scale ambiguity and accumulated drift.
|
||||
- **Related Sub-question**: Architecture / drift bounding
|
||||
|
||||
## Source #2
|
||||
- **Title**: Visual place recognition for aerial imagery: A survey
|
||||
- **Link**: https://arxiv.org/abs/2406.00885
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Aerial VPR researchers/implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Reviews aerial VPR, retrieval/re-ranking, overlap/scale effects, memory/runtime issues, and georeference recall.
|
||||
- **Related Sub-question**: VPR / validation
|
||||
|
||||
## Source #3
|
||||
- **Title**: OpenVINS documentation
|
||||
- **Link**: https://docs.openvins.com/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2023 latest noted release
|
||||
- **Timeliness Status**: Needs verification before implementation
|
||||
- **Target Audience**: VIO researchers/implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: OpenVINS is an EKF/MSCKF visual-inertial estimator supporting monocular tracking, calibration, evaluation, and covariance-aware estimation; GPL-3 license.
|
||||
- **Related Sub-question**: VO/VIO
|
||||
|
||||
## Source #4
|
||||
- **Title**: ORB-SLAM3 README
|
||||
- **Link**: https://raw.githubusercontent.com/UZ-SLAMLab/ORB_SLAM3/master/README.md
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2021 README, still repository source
|
||||
- **Timeliness Status**: Needs verification before implementation
|
||||
- **Target Audience**: SLAM implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: ORB-SLAM3 supports monocular visual-inertial SLAM and multi-map operation, requires calibration, and is GPLv3.
|
||||
- **Related Sub-question**: VO/VIO alternatives
|
||||
|
||||
## Source #5
|
||||
- **Title**: OpenCV 4.x documentation via Context7
|
||||
- **Link**: https://docs.opencv.org/4.x/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Computer vision implementers
|
||||
- **Research Boundary Match**: Full match for utility layer
|
||||
- **Summary**: Documents camera calibration, undistortion, and `findHomography` with RANSAC for robust geometry.
|
||||
- **Related Sub-question**: Calibration / geometry
|
||||
|
||||
## Source #6
|
||||
- **Title**: LightGlue README and Context7 docs
|
||||
- **Link**: https://raw.githubusercontent.com/cvg/LightGlue/main/README.md
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Feature-matching implementers
|
||||
- **Research Boundary Match**: Full match for local matching
|
||||
- **Summary**: LightGlue accepts local keypoints/descriptors and returns matched coordinates/scores; supports SuperPoint, DISK, ALIKED, SIFT, adaptive pruning, CUDA, and Apache-2 for code/weights while SuperPoint has restrictive licensing.
|
||||
- **Related Sub-question**: Local matching
|
||||
|
||||
## Source #7
|
||||
- **Title**: AnyLoc README
|
||||
- **Link**: https://github.com/AnyLoc/AnyLoc
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2023 repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Needs profiling verification
|
||||
- **Target Audience**: VPR implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Provides DINOv2 + VLAD API examples and notes substantial storage/compute requirements for full experiments.
|
||||
- **Related Sub-question**: VPR descriptors
|
||||
|
||||
## Source #8
|
||||
- **Title**: DINOv2 repository
|
||||
- **Link**: https://github.com/facebookresearch/dinov2
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2023 repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Vision model implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Meta's DINOv2 implementation and models, Apache-2.0 / CC-BY-4.0 license notices.
|
||||
- **Related Sub-question**: VPR descriptors
|
||||
|
||||
## Source #9
|
||||
- **Title**: FAISS documentation and Context7 docs
|
||||
- **Link**: https://faiss.ai/index.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Vector search implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: FAISS supports dense vector search, top-k retrieval, CPU/GPU indexes, product quantization, and save/load APIs; GPU indexes must be converted to CPU before saving.
|
||||
- **Related Sub-question**: Descriptor retrieval
|
||||
|
||||
## Source #10
|
||||
- **Title**: MAVSDK documentation via Context7
|
||||
- **Link**: https://github.com/mavlink/mavsdk
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: MAVLink application implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: MAVSDK provides telemetry APIs including raw GPS, GPS info, status text, position/velocity, and odometry subscriptions; `GPS_INPUT` emission should use raw MAVLink/pymavlink for this project.
|
||||
- **Related Sub-question**: MAVLink integration
|
||||
|
||||
## Source #11
|
||||
- **Title**: ArduPilot MAVProxy GPSInput
|
||||
- **Link**: https://ardupilot.org/mavproxy/docs/modules/GPSInput.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: ArduPilot integrators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: External GPS input requires `GPS1_TYPE=14` and accepts MAVLink `GPS_INPUT` fields including WGS84 lat/lon, velocity, fix type, and accuracy.
|
||||
- **Related Sub-question**: MAVLink output
|
||||
|
||||
## Source #12
|
||||
- **Title**: MAVLink common message spec: GPS_INPUT
|
||||
- **Link**: https://mavlink.io/en/messages/common.html#GPS_INPUT
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current spec, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: MAVLink implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Defines `GPS_INPUT` fields, fix type semantics, `horiz_accuracy`, and ignore flags.
|
||||
- **Related Sub-question**: MAVLink output / confidence
|
||||
|
||||
## Source #13
|
||||
- **Title**: ArduPilot GPS failsafe and glitch protection
|
||||
- **Link**: https://ardupilot.org/copter/docs/gps-failsafe-glitch-protection.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Reference only for Plane
|
||||
- **Target Audience**: ArduPilot operators
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Documents GPS glitch protection and notes inertial-only position degrades quickly; Copter-specific defaults must not be assumed for Plane.
|
||||
- **Related Sub-question**: Failsafe / spoofing
|
||||
|
||||
## Source #14
|
||||
- **Title**: ArduPilot EKF failsafe
|
||||
- **Link**: https://ardupilot.org/copter/docs/ekf-inav-failsafe.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Reference only for Plane
|
||||
- **Target Audience**: ArduPilot operators
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Explains EKF variance failsafe behavior and why spoof/glitch tests must be parameterized.
|
||||
- **Related Sub-question**: Failsafe / spoofing
|
||||
|
||||
## Source #15
|
||||
- **Title**: Jetson Orin Nano Super Developer Kit
|
||||
- **Link**: https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/nano-super-developer-kit/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current page, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Embedded AI implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Confirms 67 INT8 TOPS, 8 GB LPDDR5, 102 GB/s, and 7-25 W power range.
|
||||
- **Related Sub-question**: Runtime
|
||||
|
||||
## Source #16
|
||||
- **Title**: NVIDIA JetPack 6.2 Super Mode blog
|
||||
- **Link**: https://developer.nvidia.com/blog/nvidia-jetpack-6-2-brings-super-mode-to-nvidia-jetson-orin-nano-and-jetson-orin-nx-modules/
|
||||
- **Tier**: L2
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Jetson developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Explains 25 W and MAXN Super modes and warns thermal design must accommodate the new power modes or throttling occurs.
|
||||
- **Related Sub-question**: Runtime / thermal
|
||||
|
||||
## Source #17
|
||||
- **Title**: PMTiles Concepts
|
||||
- **Link**: https://docs.protomaps.com/pmtiles/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Geospatial storage implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: PMTiles is single-file tiled archive, efficient for reads, but read-only and not update-in-place.
|
||||
- **Related Sub-question**: Cache storage
|
||||
|
||||
## Source #18
|
||||
- **Title**: GDAL COG driver
|
||||
- **Link**: https://gdal.org/en/stable/drivers/raster/cog.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Geospatial raster implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Defines COG creation options for tiled, compressed, overview-enabled GeoTIFFs.
|
||||
- **Related Sub-question**: Cache storage
|
||||
|
||||
## Source #19
|
||||
- **Title**: AerialVL dataset
|
||||
- **Link**: https://github.com/hmf21/AerialVL
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Aerial visual localization researchers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Public aerial localization benchmark with UAV sequences, reference maps, and geo-referenced evaluation data.
|
||||
- **Related Sub-question**: Validation
|
||||
|
||||
## Source #20
|
||||
- **Title**: EuRoC MAV Dataset
|
||||
- **Link**: http://projects.asl.ethz.ch/datasets/euroc-mav/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2016
|
||||
- **Timeliness Status**: Stable benchmark
|
||||
- **Target Audience**: VIO researchers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Stereo camera + IMU + ground truth benchmark useful for VIO sanity tests but not representative of high-altitude nadir fixed-wing imagery.
|
||||
- **Related Sub-question**: Validation
|
||||
|
||||
## Source #21
|
||||
- **Title**: NVIDIA/TensorRT issue: DINOv2 TensorRT performance/precision on Jetson
|
||||
- **Link**: https://github.com/NVIDIA/TensorRT/issues/4348
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Needs verification
|
||||
- **Target Audience**: Jetson/TensorRT implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Reports limited mixed-precision gains for DINOv2-S on Jetson/RTX, suggesting DINOv2 optimization is not automatically beneficial.
|
||||
- **Related Sub-question**: Mode B performance risk
|
||||
|
||||
## Source #22
|
||||
- **Title**: NVIDIA Developer Forum: DINOv2 TensorRT model performance issue
|
||||
- **Link**: https://forums.developer.nvidia.com/t/dinov2-tensorrt-model-performance-issue/312251
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Needs verification
|
||||
- **Target Audience**: Jetson/TensorRT implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Reports DINOv2 embedding distance changes after TensorRT conversion on Jetson Orin Nano; requires embedding-fidelity validation before relying on TensorRT descriptors.
|
||||
- **Related Sub-question**: Mode B performance/quality risk
|
||||
|
||||
## Source #23
|
||||
- **Title**: LightGlue license issue discussions
|
||||
- **Link**: https://github.com/cvg/LightGlue/issues/120
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently relevant
|
||||
- **Target Audience**: Feature-matching implementers
|
||||
- **Research Boundary Match**: Full match for licensing
|
||||
- **Summary**: Community discussion highlights restrictive SuperPoint licensing inside the LightGlue ecosystem and supports avoiding SuperPoint as default production extractor.
|
||||
- **Related Sub-question**: Mode B licensing risk
|
||||
|
||||
## Source #24
|
||||
- **Title**: ArduPilot issue: GPS_INPUT velocity ignore flag pitfall
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/issues/19633
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2021
|
||||
- **Timeliness Status**: Needs SITL verification
|
||||
- **Target Audience**: ArduPilot integrators
|
||||
- **Research Boundary Match**: Full match for GPS_INPUT caution
|
||||
- **Summary**: Reports EKF3 may use zero velocity when `GPS_INPUT_IGNORE_FLAG_VEL_HORIZ` is set, so velocity-source parameters must be tested rather than relying only on ignore flags.
|
||||
- **Related Sub-question**: Mode B MAVLink pitfall
|
||||
|
||||
## Source #25
|
||||
- **Title**: FAISS install documentation
|
||||
- **Link**: https://github.com/facebookresearch/faiss/blob/main/INSTALL.md
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Vector search implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: FAISS CPU conda package supports aarch64, while GPU package availability is x86-64 focused; Jetson design should assume CPU FAISS unless a custom build is proven.
|
||||
- **Related Sub-question**: Mode B FAISS deployment
|
||||
|
||||
## Source #26
|
||||
- **Title**: GNSS-denied geolocalization of UAVs by visual matching of onboard camera images with orthophotos
|
||||
- **Link**: https://ar5iv.labs.arxiv.org/html/2103.14381
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2021
|
||||
- **Timeliness Status**: Stable mechanism reference
|
||||
- **Target Audience**: UAV visual geolocalization researchers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Demonstrates visual matching with orthophotos and Monte Carlo/local planarity ideas; supports using orthorectified reference maps but does not cover all adversarial visual attacks.
|
||||
- **Related Sub-question**: Mode B alternative / security limits
|
||||
|
||||
## Source #27
|
||||
- **Title**: OpenVINS LICENSE
|
||||
- **Link**: https://github.com/rpng/open_vins/blob/master/LICENSE
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: VIO implementers / product owners
|
||||
- **Research Boundary Match**: Full match for licensing
|
||||
- **Summary**: OpenVINS is GPLv3-licensed; this is a production dependency constraint, not a technical capability limitation.
|
||||
- **Related Sub-question**: Mode B round 2 — OpenVINS vs custom production estimator
|
||||
|
||||
## Source #28
|
||||
- **Title**: OpenVINS documentation and Context7 lookup
|
||||
- **Link**: https://docs.openvins.com/index.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: VIO implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: OpenVINS is a strong EKF/MSCKF VIO system for monocular camera + IMU reference runs, with calibration and covariance-aware state estimation, but it does not own the project-specific satellite anchor, GPS_INPUT, source-label, spoofing, blackout, and cache-poisoning state machine.
|
||||
- **Related Sub-question**: Mode B round 2 — OpenVINS vs custom production estimator
|
||||
|
||||
## Source #29
|
||||
- **Title**: OpenCV 4.x calibration/homography documentation and Context7 lookup
|
||||
- **Link**: https://docs.opencv.org/4.x/
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Computer vision implementers
|
||||
- **Research Boundary Match**: Full match for geometry utility layer
|
||||
- **Summary**: OpenCV 4.x provides calibration, undistortion, homography estimation, RANSAC/USAC robust estimation, and reprojection-error primitives under a permissive license; it is a utility layer rather than a complete GPS-denied estimator.
|
||||
- **Related Sub-question**: Mode B round 2 — custom OpenCV boundary
|
||||
|
||||
## Source #30
|
||||
- **Title**: AnyLoc: Towards Universal Visual Place Recognition
|
||||
- **Link**: https://arxiv.org/html/2308.00688
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2023; ICRA 2024
|
||||
- **Timeliness Status**: Currently valid, profiling required before deployment
|
||||
- **Target Audience**: VPR implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: AnyLoc combines DINOv2 features with VLAD aggregation for broad VPR, including aerial data, and supports the selected DINOv2-VLAD retrieval family while leaving runtime/storage tuning as a deployment gate.
|
||||
- **Related Sub-question**: Mode B round 2 — satellite retrieval
|
||||
|
||||
## Source #31
|
||||
- **Title**: ALIKED-LightGlue-ONNX and LightGlue ONNX/TensorRT deployment reports
|
||||
- **Link**: https://github.com/ikeboo/ALIKED-LightGlue-ONNX
|
||||
- **Tier**: L2
|
||||
- **Publication Date**: Current repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Promising but needs Jetson verification
|
||||
- **Target Audience**: Local feature matching implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: ONNX/optimized variants show a credible deployment path for ALIKED + LightGlue, but public evidence is not enough to assume Jetson Orin Nano p95 latency without project profiling.
|
||||
- **Related Sub-question**: Mode B round 2 — local matcher deployability
|
||||
|
||||
## Source #32
|
||||
- **Title**: Visual place recognition for aerial imagery: A survey
|
||||
- **Link**: https://arxiv.org/abs/2406.00885
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Aerial VPR researchers / implementers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Aerial VPR performance depends materially on tile scale, overlap, weather, repetitive patterns, and re-ranking cost; this supports overlapped VPR chunks, dynamic top-K, and conditional local verification.
|
||||
- **Related Sub-question**: Mode B round 2 — satellite retrieval and anchor verification
|
||||
|
||||
## Source #33
|
||||
- **Title**: BASALT repository and documentation
|
||||
- **Link**: https://github.com/VladyslavUsenko/basalt
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current repository, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: VIO implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: BASALT provides visual-inertial odometry and mapping, camera/IMU calibration tools, EuRoC/TUM VI support, and a BSD-style production-friendly licensing path.
|
||||
- **Related Sub-question**: Mode B round 3 — Kimera vs BASALT vs OpenVINS
|
||||
|
||||
## Source #34
|
||||
- **Title**: HybVIO: Pushing the Limits of Real-time Visual-inertial Odometry
|
||||
- **Link**: https://arxiv.org/pdf/2106.11857
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2021
|
||||
- **Timeliness Status**: Stable benchmark reference
|
||||
- **Target Audience**: VIO researchers / embedded implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Reports EuRoC RMS ATE comparisons including BASALT mean about 0.051 m online stereo and Kimera mean about 0.12 m, plus notes that optimization-based methods often lack direct uncertainty quantification compared with filters.
|
||||
- **Related Sub-question**: Mode B round 3 — VIO error and confidence comparison
|
||||
|
||||
## Source #35
|
||||
- **Title**: OpenVINS issue #402 — up-to-date ATE and RTE metrics
|
||||
- **Link**: https://github.com/rpng/open_vins/issues/402
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Community benchmark, verify in our replay harness
|
||||
- **Target Audience**: VIO implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Community EuRoC comparison reports BASALT average ATE about 0.072 m with 100% completion, and OpenVINS average ATE about 0.091 m with about 88.55% completion and a divergence on one hard sequence.
|
||||
- **Related Sub-question**: Mode B round 3 — BASALT vs OpenVINS error/completion
|
||||
|
||||
## Source #36
|
||||
- **Title**: Kimera-VIO mono-inertial parameter issues
|
||||
- **Link**: https://github.com/MIT-SPARK/Kimera-VIO/issues/254
|
||||
- **Tier**: L4
|
||||
- **Publication Date**: 2024
|
||||
- **Timeliness Status**: Relevant implementation caveat
|
||||
- **Target Audience**: VIO implementers
|
||||
- **Research Boundary Match**: Partial overlap
|
||||
- **Summary**: Kimera-VIO stereo path remains strong, but mono-inertial configurations had documented poor default performance; parameter changes improved one EuRoC mono setup to less than about +/-0.2 m per axis.
|
||||
- **Related Sub-question**: Mode B round 3 — Kimera mono/nadir risk
|
||||
|
||||
## Source #37
|
||||
- **Title**: RaD-VIO and downward-facing VIO literature
|
||||
- **Link**: https://arxiv.org/abs/1810.08704
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2018
|
||||
- **Timeliness Status**: Stable mechanism reference
|
||||
- **Target Audience**: MAV downward-camera VIO researchers
|
||||
- **Research Boundary Match**: Full match for nadir-camera caveat
|
||||
- **Summary**: Downward-facing monocular VIO has planar-scene and observability challenges; range/altitude and IMU constraints are important when the camera sees mostly ground plane.
|
||||
- **Related Sub-question**: Mode B round 3 — nadir support and limitations
|
||||
|
||||
## Source #38
|
||||
- **Title**: OpenVINS covariance documentation and StateHelper APIs
|
||||
- **Link**: https://docs.openvins.com/dev-index.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: Current docs, accessed 2026-05-01
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: VIO implementers
|
||||
- **Research Boundary Match**: Full match for covariance/confidence output
|
||||
- **Summary**: OpenVINS maintains EKF covariance and exposes full/marginal covariance helpers, making it the strongest reference for covariance consistency even if GPLv3 blocks default production use.
|
||||
- **Related Sub-question**: Mode B round 3 — confidence/covariance support
|
||||
@@ -0,0 +1,172 @@
|
||||
# Source Registry — Summary & Index
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> Investigation order saved in `../00_question_decomposition.md` → "Next Step": SQ6 → SQ1 → SQ2 → SQ3+SQ4 per component (C1→C8) ✓ → C10 next → SQ5 interleaved → SQ8 → SQ9 synthesis at engine Step 8. **SQ7 (datasets / SITL / replay) deferred to Test Spec (greenfield Step 5) per 2026-05-08 C9 / SQ7 restructure** — see `../00_question_decomposition.md` → "C9 / SQ7 Restructure" section.
|
||||
>
|
||||
> This folder replaces the previous monolithic `01_source_registry.md`. The full per-source description for any source `#N` in the table below lives in the category file linked in its row.
|
||||
|
||||
## Category Index
|
||||
|
||||
| Category | File | Sources | Status |
|
||||
|---|---|---|---|
|
||||
| SQ6 — ArduPilot Plane vs iNav external positioning | [`SQ6_external_positioning.md`](SQ6_external_positioning.md) | #1–#24 | Saturated for protocol-level architectural decision |
|
||||
| SQ1 — Existing GPS-denied UAV systems | [`SQ1_existing_systems.md`](SQ1_existing_systems.md) | #25–#37 | Saturated |
|
||||
| SQ2 — Canonical pipeline decomposition | [`SQ2_canonical_pipeline.md`](SQ2_canonical_pipeline.md) | #38–#42 | Saturated |
|
||||
| C1 — VIO candidates | [`C1_vio.md`](C1_vio.md) | #43–#56 | Closed at documentary level |
|
||||
| C2 — VPR candidates | [`C2_vpr.md`](C2_vpr.md) | #57–#68 | Mandatory pre-screen complete (5/5) |
|
||||
| C3 — Matcher candidates | [`C3_matchers.md`](C3_matchers.md) | #69–#81 | Closed at documentary level |
|
||||
| C4 — Pose estimation candidates | [`C4_pose_estimation.md`](C4_pose_estimation.md) | #82–#87 | Closed at 3/N |
|
||||
| C5 — State estimator / sensor fusion candidates | [`C5_state_estimator.md`](C5_state_estimator.md) | #88–#91 | Closed at 2/N (batch 1 closed) |
|
||||
| C6 — Tile cache + spatial index candidates | [`C6_tile_cache_spatial_index.md`](C6_tile_cache_spatial_index.md) | #92–#98 | Closed at 2/N (batch 1 closed) — Cand 1 (mirror-suite-pattern) RECOMMENDED PRIMARY; Cand 2 (PostGIS+pgvector) DEFERRED secondary |
|
||||
| C7 — On-Jetson inference runtime candidates | [`C7_inference_runtime.md`](C7_inference_runtime.md) | #99–#105 | Closed at 3/N (batch 1 closed 2026-05-08) — Cand 1 (TensorRT native) RECOMMENDED PRIMARY; Cand 2 (ONNX Runtime + TRT EP) modern-competitive-lead-cross-architecture-portability; Cand 3 (pure PyTorch FP16) mandatory simple-baseline |
|
||||
| C8 — MAVLink / MSP2 FC adapter candidates | [`C8_fc_adapter.md`](C8_fc_adapter.md) | #106–#113 | Closed at 3/N (batch 1 closed 2026-05-08) — Cand 1 (pymavlink → MAVLink GPS_INPUT) RECOMMENDED PRIMARY for ArduPilot Plane; Cand 2 (MSP2_SENSOR_GPS via Python MSP V2) RECOMMENDED PRIMARY for iNav (locked SQ6 + AC-4.3 transport); Cand 3 (UBX impersonation via pyubx2 NAV-PVT) DEFERRED secondary for iNav after comparative-improvement verdict |
|
||||
| C10 — Pre-flight cache provisioning (CROSS-COUPLING MINIMAL scope per 2026-05-08 user choice C; D-C6-3 + D-C7-7 confirmation pipelines only, operator tooling deferred to Plan-phase) | [`C10_preflight_provisioning.md`](C10_preflight_provisioning.md) | #114–#121 | Closed at 2/N (batch 1 closed 2026-05-08) — D-C6-3 confirmation: direct `faiss.write_index`/`faiss.read_index` Python API + `python-atomicwrites` + content-hash verification gate at takeoff (FAISS MIT, atomicwrites MIT); D-C7-7 confirmation: hybrid Polygraphy CLI primary + `trtexec` for cache-reuse fast rebuilds + direct `IBuilderConfig` Python API escape hatch (Polygraphy + TensorRT 10.x Apache-2.0 throughout) |
|
||||
| **Mode B addendum (2026-05-08)** — solution_draft01 assessment | [`MODEB_addendum.md`](MODEB_addendum.md) | **#122–#131** (10 sources) | New sources gathered for Mode B findings F1–F20: VINS-Mono GPL-3.0 LICENCE confirmation (#122), MegaLoc + UltraVPR + AirZoo aerial-VPR successor candidates (#123, #124, #125), CVE-2026-1579 MAVLink no-default-auth + CVE-2025-53644 OpenCV crafted-JPEG (#126, #127), ArduPilot MAVLink2 message-signing + iNav signing-gap (#128, #129), ArduPilot `MAV_CMD_SET_EKF_SOURCE_SET` no-deployed-GCS-implementer re-verification (#130), XoFTR + 2026 SAR-optical 24-matcher benchmark (#131). |
|
||||
|
||||
## Investigation Status
|
||||
|
||||
| Sub-question | Status | Notes |
|
||||
|---|---|---|
|
||||
| SQ6 — ArduPilot vs iNav external positioning | **Saturated for protocol-level architectural decision** (further detail deferred to SQ8 for spoofing-side fields and to design phase for SITL parameter tuning) | Major finding: iNav has no inbound external-positioning MAVLink handler; AC-4.3 wording must be revised. See `../02_fact_cards/SQ6_fc_external_positioning.md` "SQ6 Conclusions". |
|
||||
| SQ1 — Existing GPS-denied UAV systems | **Saturated.** 13 sources logged across academic / open-source / commercial / defense-program / Ukraine-practitioner. Closest peer system: Twist Robotics OSCAR (deployed in Ukraine). Closest open-source pipeline-match: snktshrma/ngps_flight (NGPS, ArduPilot GSoC 2024 — LightGlue+SuperPoint+UKF+VISION_POSITION_ESTIMATE). Closest deployed commercial: Auterion Artemis (Skynode N + Visual Navigation, Ukraine-tested, 1000-mile range). | See `../02_fact_cards/SQ1_existing_systems.md` cluster + working summary. |
|
||||
| SQ2 — Canonical pipeline decomposition | **Saturated.** 5 surveys/benchmarks logged (Skoltech aerial VPR, U.Maine cross-view, OrthoLoC 2.5D geodata, AnyVisLoc low-altitude multi-view, NUDT 2026 sciopen survey). All converge on **`retrieval → matching → pose-estimation`** hierarchical framework with VIO/IMU as auxiliary. Two new architectural facts added to C1–C10: (a) **AdHoP-style perspective-refinement loop** between matching and PnP (+63% translation accuracy, method-agnostic), (b) **DSM 2.5D dependency** for full 6-DoF on aerial-to-satellite (must be resolved with the Suite Sat Service or accepted as a 3-DoF degraded mode). Practitioner runtime evidence: AnyLoc on RTX 3090 = 0.63s/descriptor, SuperGlue re-rank = 17–25s; on Jetson Orin Nano these are non-viable for our 400 ms p95 budget — must restrict to lightweight VPR (e.g., MixVPR / SALAD class) + LightGlue/XFeat-class matchers. See `../02_fact_cards/SQ2_canonical_pipeline.md` "SQ2 Conclusions". |
|
||||
| SQ3+SQ4 — Per-component candidates (C1–C10) | **In progress** — C1 (VIO) **CLOSED** at documentary level (Sources #43–#56). C2 (VPR) — **mandatory pre-screen COMPLETE at documentary level (5 of 5 candidates)**: MixVPR (Sources #57+#58), SALAD (Sources #59+#60+#61), SelaVPR (Sources #62+#63), NetVLAD (Sources #64+#65+#66), **EigenPlaces (Sources #67+#68 — closure 2026-05-08)**. All five mandatory candidates have per-mode API capability verification ✅, per-numbered-Restriction × per-numbered-AC sub-matrix written, and `../06_component_fit_matrix/C2_vpr.md` rows populated. **Conditional pre-screen candidates (AnyLoc / BoQ / DINOv2-VLAD)** are GATED on a prerequisite **INT8 quantization survey** before they can be added to per-mode rows (per Fact #26 pre-screen rule). C3 closed at documentary level (Sources #69–#81). C4 closed at 3/N (Sources #82–#87). **C5 CLOSED at 2/N — batch 1 closed 2026-05-08** (mandatory simple-baseline = Manual ESKF Solà 2017 [Sources #88–#89]; modern-competitive-lead-factor-graph = GTSAM iSAM2 + ImuFactor + smart factors + Marginals [Sources #90–#91]). **C6 CLOSED at 2/N — batch 1 closed 2026-05-08** (Cand 1 RECOMMENDED PRIMARY = mirror-of-suite-satellite-provider pattern: PostgreSQL btree + bytea + FAISS HNSW + filesystem [Sources #92+#96+#97+#98]; Cand 2 DEFERRED secondary = PostGIS GiST + pgvector HNSW + filesystem [Sources #94+#95]; Source #93 = PostgreSQL btree multicolumn-indexes docs cross-cite). **C7 CLOSED at 3/N — batch 1 closed 2026-05-08** (Cand 1 RECOMMENDED PRIMARY = TensorRT native [Sources #99+#104+#105]; Cand 2 modern-competitive-lead-cross-architecture-portability = ONNX Runtime + TRT EP [Source #100 + #103]; Cand 3 mandatory simple-baseline = pure PyTorch FP16 [Source #101]; Source #102 = YOLO26 Jetson Orin Nano Super benchmark; Source #103 = LightGlue+TRT+FP8 quantization-sensitivity finding driving D-C7-6 cross-component precision policy). **C8 CLOSED at 3/N — batch 1 closed 2026-05-08** (Cand 1 RECOMMENDED PRIMARY for ArduPilot = pymavlink → MAVLink GPS_INPUT msg 232 cooperative-path [Sources #106+#107 + cross-cite SQ6 Source #4 AP_GPS_MAV.cpp ingestion-path]; Cand 2 RECOMMENDED PRIMARY for iNav = MSP2_SENSOR_GPS id 7939 / 0x1F03 via Python MSP V2 implementation [Sources #111+#112+#113 + cross-cite SQ6 Source #12+#13]; Cand 3 DEFERRED secondary for iNav = UBX impersonation via pyubx2 NAV-PVT [Sources #108+#109+#110 + cross-cite SQ6 Fact #10] with comparative-improvement verdict that does NOT clear user's "significant-improvement-only" bar over Cand 2; mid-batch correction via c8_inav_recovery=B preserved locked SQ6 + AC-4.3 + restrictions.md verdicts). **C9 DROPPED** from research scope per 2026-05-08 SQ7/C9 restructure (datasets/SITL/replay deferred to Test Spec greenfield Step 5). **C10 CLOSED at 2/N — batch 1 closed 2026-05-08** under CROSS-COUPLING MINIMAL scope per 2026-05-08 user choice C (operator CLI/desktop tooling, sector classification, freshness pipeline deferred to Plan-phase): D-C6-3 confirmation = direct `faiss.write_index`/`faiss.read_index` Python API + `python-atomicwrites` + content-hash (SHA-256) verification gate at takeoff load + `IO_FLAG_MMAP_IFC` mmap [Sources #114+#115+#116]; D-C7-7 confirmation = hybrid Polygraphy CLI primary for INT8-calibrating builds + `trtexec` for cache-reuse fast rebuilds + direct `IBuilderConfig` Python API escape hatch [Sources #117+#118+#119+#120+#121]; **no further C10 batches required at the research layer** — operator tooling design enters at Plan-phase. | See `../02_fact_cards/C1_vio.md` + `../02_fact_cards/C2_vpr.md` + `../02_fact_cards/C3_matchers.md` + `../02_fact_cards/C4_pose_estimation.md` + `../02_fact_cards/C5_state_estimator.md` + `../02_fact_cards/C6_tile_cache_spatial_index.md` + `../02_fact_cards/C7_inference_runtime.md` clusters; `../06_component_fit_matrix/C{1..7}_*.md` rows. |
|
||||
| SQ5 — Failure modes / deployment lessons | Not started (interleaved with SQ3/SQ4) | |
|
||||
| SQ7 — Datasets, SITL, replay environments | **Deferred to Test Spec (greenfield Step 5)** per 2026-05-08 C9 / SQ7 restructure | Fixture-class / test-infra-class — not researched in this Mode A run. Carryforward payload preserved in `../00_question_decomposition.md` → "C9 / SQ7 Restructure" section. |
|
||||
| SQ8 — Safety considerations (AC-NEW-4 / AC-NEW-7) | Not started | Carries the AP_GPS spoofing-signal probe deferred from SQ6. |
|
||||
| SQ9 — End-to-end synthesis | Step 8 of engine (deferred) | |
|
||||
|
||||
---
|
||||
|
||||
## Source Summary Table
|
||||
|
||||
Compact one-line index across all 121 sources. For full per-source description, follow the **File** link.
|
||||
|
||||
| # | Title | Tier | File |
|
||||
|---|---|---|---|
|
||||
| 1 | Non-GPS Navigation — Plane documentation | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 2 | GPS / Non-GPS Transitions — Plane documentation | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 3 | EKF Source Selection and Switching — Plane documentation | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 4 | ArduPilot AP_GPS_MAV.cpp (master) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 5 | ArduPilot PR #28750 — AP_NavEKF3 EK3_OPTION bits (GPS-denied testing) | L2 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 6 | ArduPilot Issue #15859 — EKF3 source switching (GPS↔NonGPS) | L4 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 7 | ArduPilot Issue #27193 — EK3 Source Switching wrong frame for GUIDED | L4 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 8 | ArduPilot Issue #23485 — fuse only External Nav Velocities | L4 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 9 | iNavFlight/inav telemetry/mavlink.c (master inbound switch) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 10 | iNav Wiki — MAVLink (frogmane edited 2025-12-11) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 11 | iNav Wiki — GPS and Compass setup | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 12 | iNavFlight/inav docs/development/msp/README.md (MSP message reference) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 13 | iNavFlight/inav src/main/io/gps.c + target/common.h (master) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 14 | iNav Issue #10141 — dual GPS support | L4 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 15 | iNav docs/GPS_fix_estimation.md (master) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 16 | iNav docs/Settings.md (master) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 17 | iNav Issue #10588 — DeadReckoning weird behaviour during GPS outage | L4 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 18 | iNav Release 8.0.0 (highlights, Dec 2024) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 19 | iNav Release 9.0.0 / 9.0.1 + Release Notes wiki | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 20 | MAVLink common message set — GPS_RAW_INT (24) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 21 | MAVLink PR #2110 — gps: add status and integrity information | L2 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 22 | AirDroper — GNSS Spoofing Filter companion device | L3 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 23 | ArduPilot PR #24135 — EKF3 robust to bad IMU and lane-switching | L2 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 24 | ArduPilot AP_NavEKF3 — VehicleStatus.cpp + AP_NavEKF3.cpp (master) | L1 | [SQ6](SQ6_external_positioning.md) |
|
||||
| 25 | Twist Robotics OSCAR — visual navigation system (Ukraine deployment) | L2 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 26 | Ukraine Drones with Vision-Based Navigation Past Heavy Jamming (TWZ) | L2 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 27 | Ukraine's Ruta Missile Drone EW-Immune Navigation (Defense Express) | L2 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 28 | Kilometer-Scale GNSS-Denied UAV Navigation via Heightmap Gradients | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 29 | Hierarchical Image Matching for UAV Absolute Visual Localization | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 30 | Raptor — GPS-Denied UAV Navigation & Coordinate Extraction (Vantor) | L2 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 31 | Auterion Artemis program — long-range deep-strike completion | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 32 | Auterion Skynode N — AI/CV for small autonomous systems | L2 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 33 | snktshrma/ngps_flight — NGPS for ArduPilot (GSoC 2024) | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 34 | AerialExtreMatch — benchmark for extreme-view image matching/localization | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 35 | DARPA Fast Lightweight Autonomy (FLA) program page + T&E review | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 36 | DSMAC / TERCOM lineage — DTIC ADA315439 | L1 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 37 | Electronic Warfare in Ukraine — Ukraine War Analytics | L3 | [SQ1](SQ1_existing_systems.md) |
|
||||
| 38 | VPR for Aerial Imagery: A Survey (Skoltech, Moskalenko et al.) | L1 | [SQ2](SQ2_canonical_pipeline.md) |
|
||||
| 39 | Cross-View Geo-Localization: A Survey (U. Maine) | L1 | [SQ2](SQ2_canonical_pipeline.md) |
|
||||
| 40 | OrthoLoC: UAV 6-DoF Localization with Orthographic Geodata | L1 | [SQ2](SQ2_canonical_pipeline.md) |
|
||||
| 41 | AnyVisLoc — UAV visual localization, low-altitude multi-view | L1 | [SQ2](SQ2_canonical_pipeline.md) |
|
||||
| 42 | NUDT 2026 — survey on absolute visual localization for low-altitude UAV | L1 | [SQ2](SQ2_canonical_pipeline.md) |
|
||||
| 43 | VINS-Mono — robust monocular visual-inertial state estimator | L1 | [C1](C1_vio.md) |
|
||||
| 44 | VINS-Fusion — optimization-based multi-sensor state estimator | L1 | [C1](C1_vio.md) |
|
||||
| 45 | OpenVINS — open-source VI navigation research platform | L1 | [C1](C1_vio.md) |
|
||||
| 46 | Run VIO on NVIDIA Jetson — KAIST benchmark | L1 | [C1](C1_vio.md) |
|
||||
| 47 | OKVIS2 — realtime scalable VI-SLAM with loop closure | L1 | [C1](C1_vio.md) |
|
||||
| 48 | OKVIS2-X — open keyframe VI-SLAM with dense depth | L1 | [C1](C1_vio.md) |
|
||||
| 49 | Kimera-VIO — VIO with SLAM + 3D mesh (MIT-SPARK, BSD) | L1 | [C1](C1_vio.md) |
|
||||
| 50 | DROID-SLAM — deep visual SLAM (princeton-vl) | L1 | [C1](C1_vio.md) |
|
||||
| 51 | DPVO / DPV-SLAM — deep patch visual odometry | L1 | [C1](C1_vio.md) |
|
||||
| 52 | DPVO-QAT++ — heterogeneous QAT + CUDA kernel fusion for DPVO | L2 | [C1](C1_vio.md) |
|
||||
| 53 | Pure-VO baseline — KLT optical flow + 5-point/homography RANSAC (OpenCV) | L1 | [C1](C1_vio.md) |
|
||||
| 54 | OpenVINS — context7 per-mode capability lookup (`/rpng/open_vins`) | L1 | [C1](C1_vio.md) |
|
||||
| 55 | VINS-Mono README + VINS-Fusion context7 per-mode lookup | L1 | [C1](C1_vio.md) |
|
||||
| 56 | OKVIS2 — official README (`smartroboticslab/okvis2`, main) | L1 | [C1](C1_vio.md) |
|
||||
| 57 | OpenVPRLab — open-source VPR framework (MixVPR / BoQ / NetVLAD / GeM) | L1 | [C2](C2_vpr.md) |
|
||||
| 58 | MixVPR canonical paper (WACV 2023, arXiv:2303.02190) | L1 | [C2](C2_vpr.md) |
|
||||
| 59 | SALAD canonical implementation (`serizba/salad`, GPL-3.0) | L1 | [C2](C2_vpr.md) |
|
||||
| 60 | SALAD canonical paper — Optimal Transport Aggregation (CVPR 2024) | L1 | [C2](C2_vpr.md) |
|
||||
| 61 | OpenVPRLab DinoV2 backbone — context7 cross-source for ViT-B/14 | L1 | [C2](C2_vpr.md) |
|
||||
| 62 | SelaVPR canonical implementation (`Lu-Feng/SelaVPR`, MIT) | L1 | [C2](C2_vpr.md) |
|
||||
| 63 | SelaVPR canonical paper (ICLR 2024, arXiv:2402.14505) | L1 | [C2](C2_vpr.md) |
|
||||
| 64 | NetVLAD canonical implementation `Relja/netvlad` v1.03 (MIT) | L1 | [C2](C2_vpr.md) |
|
||||
| 65 | NetVLAD modern PyTorch reproduction `Nanne/pytorch-NetVlad` | L2 | [C2](C2_vpr.md) |
|
||||
| 66 | NetVLAD canonical paper (CVPR 2016 / TPAMI 2018, arXiv:1511.07247) | L1 | [C2](C2_vpr.md) |
|
||||
| 67 | EigenPlaces canonical implementation (`gmberton/EigenPlaces`, MIT) | L1 | [C2](C2_vpr.md) |
|
||||
| 68 | EigenPlaces canonical paper (ICCV 2023, arXiv:2308.10832) | L1 | [C2](C2_vpr.md) |
|
||||
| 69 | LightGlue — context7 per-mode capability lookup (`/cvg/lightglue`) | L1 | [C3](C3_matchers.md) |
|
||||
| 70 | LightGlue canonical implementation (`cvg/LightGlue`) | L1 | [C3](C3_matchers.md) |
|
||||
| 71 | LightGlue canonical paper (ICCV 2023, arXiv:2306.13643) | L1 | [C3](C3_matchers.md) |
|
||||
| 72 | LightGlue HuggingFace Transformers integration | L1 | [C3](C3_matchers.md) |
|
||||
| 73 | LightGlue-ONNX — `fabio-sim/LightGlue-ONNX` (Jetson TensorRT path) | L2 | [C3](C3_matchers.md) |
|
||||
| 74 | ALIKED canonical implementation (`Shiaoming/ALIKED`) | L1 | [C3](C3_matchers.md) |
|
||||
| 75 | ALIKED canonical paper (TIM 2023, arXiv:2304.03608) | L1 | [C3](C3_matchers.md) |
|
||||
| 76 | DISK canonical implementation (`cvlab-epfl/disk`, Apache-2.0) | L1 | [C3](C3_matchers.md) |
|
||||
| 77 | DISK canonical paper — RL-trained local features (NeurIPS 2020) | L1 | [C3](C3_matchers.md) |
|
||||
| 78 | SuperGlue canonical implementation (`magicleap/SuperGluePretrainedNetwork`) | L1 | [C3](C3_matchers.md) |
|
||||
| 79 | SuperGlue canonical paper — graph-NN feature matching (CVPR 2020) | L1 | [C3](C3_matchers.md) |
|
||||
| 80 | XFeat canonical implementation (`verlab/accelerated_features`, Apache-2.0) | L1 | [C3](C3_matchers.md) |
|
||||
| 81 | XFeat canonical paper — accelerated features (CVPR 2024) | L1 | [C3](C3_matchers.md) |
|
||||
| 82 | OpenCV canonical implementation — `opencv/opencv` (calib3d module) | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 83 | OpenCV 4.x calib3d module canonical documentation | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 84 | OpenGV canonical implementation (`laurentkneip/opengv`) | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 85 | OpenGV canonical Doxygen documentation portal | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 86 | GTSAM canonical implementation (`borglab/gtsam`, BSD-3) | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 87 | GTSAM canonical Python documentation via context7 | L1 | [C4](C4_pose_estimation.md) |
|
||||
| 88 | Solà 2017 — "Quaternion kinematics for the error-state Kalman filter" (arXiv:1711.02508) | L1 | [C5](C5_state_estimator.md) |
|
||||
| 89 | Reference open-source ESKF implementations (canonical-paper-derived) | L2 | [C5](C5_state_estimator.md) |
|
||||
| 90 | GTSAM `ImuFactor` / `CombinedImuFactor` / `PreintegratedImuMeasurements` / `PreintegratedCombinedMeasurements` (context7 indexed) | L1 | [C5](C5_state_estimator.md) |
|
||||
| 91 | GTSAM `ISAM2` / `IncrementalFixedLagSmoother` / `Marginals` with iSAM2 results (context7 indexed) | L1 | [C5](C5_state_estimator.md) |
|
||||
| 92 | Parent-suite `satellite-provider` existing pattern (PostgreSQL + Dapper + filesystem tile storage; verified directly) | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 93 | PostgreSQL 16 official documentation — Multicolumn Indexes + btree access method | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 94 | PostGIS official documentation — GiST + KNN distance ordering + ST_DWithin | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 95 | pgvector official documentation — HNSW index API (context7 + canonical README) | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 96 | FAISS official documentation — IndexFlatL2 / IndexHNSWFlat / IndexIVFFlat (context7 indexed) | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 97 | Postgres on NVIDIA Jetson Orin Nano — March 2026 Medium article + Coding Steve minimal-config guide | L2 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 98 | Slippy Map Tilenames — OpenStreetMap canonical specification (Web Mercator XYZ) | L1 | [C6](C6_tile_cache_spatial_index.md) |
|
||||
| 99 | NVIDIA TensorRT 10.x official documentation portal (context7-indexed `/nvidia/tensorrt`) | L1 | [C7](C7_inference_runtime.md) |
|
||||
| 100 | Microsoft ONNX Runtime official documentation (context7-indexed `/microsoft/onnxruntime`) + Jetson AI Lab community wheel index | L1 | [C7](C7_inference_runtime.md) |
|
||||
| 101 | PyTorch official documentation (context7-indexed `/pytorch/pytorch`) + Jetson AI Lab PyTorch wheel availability for JetPack 6 | L1 | [C7](C7_inference_runtime.md) |
|
||||
| 102 | Ultralytics YOLO26 benchmark suite on Jetson Orin Nano Super (April 2026) | L2 | [C7](C7_inference_runtime.md) |
|
||||
| 103 | LightGlue ONNX Runtime + TensorRT acceleration + FP8 ModelOpt quantization findings (Fabio Sim's Journal) | L2 | [C7](C7_inference_runtime.md) |
|
||||
| 104 | JetPack SDK release notes (NVIDIA official) — JetPack 6.0 / 6.1 / 6.2 version matrix | L1 | [C7](C7_inference_runtime.md) |
|
||||
| 105 | TensorRT-on-Jetson canonical install constraints (Ultralytics issue reports + NVIDIA forum) | L2 | [C7](C7_inference_runtime.md) |
|
||||
| 106 | ArduPilot Pymavlink (context7-indexed `/ardupilot/pymavlink`) — canonical Python MAVLink stack | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 107 | ArduPilot Plane Non-GPS Position Estimation + MAVProxy GPS Input module dev docs (`GPS1_TYPE=14`, `EK3_SRC1_POSXY=3`) | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 108 | pyubx2 (context7-indexed `/semuconsulting/pyubx2`) — canonical Python UBX/NMEA/RTCM3 parser | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 109 | u-blox NEO-M9N Integration Manual (UBX-19014286) + u-blox 8/M8 Receiver Description (UBX-13003221) — UBX-NAV-PVT canonical specification | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 110 | iNav `gps_ublox.c` source (master) — UBX validation gates `gpsMapFixType()` requires `flags & 0x01 = 1` AND `fixType ∈ {2,3}` | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 111 | iNav `docs/development/msp/README.md` (master) — `MSP2_SENSOR_GPS (7939 / 0x1F03)` canonical 36-byte payload spec | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 112 | Python MSP2 implementations: YAMSPy + INAV-Toolkit `inav_msp.py` (MSP V2 `msp_v2_encode` with CRC-8 DVB-S2) | L2 | [C8](C8_fc_adapter.md) |
|
||||
| 113 | iNav `src/main/msp/msp_protocol_v2_sensor.h` (master) — MSP V2 sensor command-ID range (0x1F00-0x1FFF) | L1 | [C8](C8_fc_adapter.md) |
|
||||
| 114 | FAISS `write_index` / `read_index` Python API + on-disk format + security warning (canonical wiki + context7) | L1 | [C10](C10_preflight_provisioning.md) |
|
||||
| 115 | FAISS IndexHNSWFlat per-vector memory + on-disk file size formula (Discussions #3953 + C++ API docs) | L2 | [C10](C10_preflight_provisioning.md) |
|
||||
| 116 | Python atomic file write pattern (gocept blog + python-atomicwrites docs + Python Issue 8604) | L2 | [C10](C10_preflight_provisioning.md) |
|
||||
| 117 | Polygraphy `polygraphy convert` CLI for TensorRT INT8 engine build with calibration cache reuse (NVIDIA TensorRT repo + context7) | L1 | [C10](C10_preflight_provisioning.md) |
|
||||
| 118 | Polygraphy `Calibrator` class API — algo defaults + dynamic-shapes calibration profile + warning behavior (NVIDIA TRT/Polygraphy SDK docs) | L1 | [C10](C10_preflight_provisioning.md) |
|
||||
| 119 | `trtexec` CLI for one-off engine builds — INT8/FP16 flags + calibration cache support (NVIDIA TRT SDK docs) | L1 | [C10](C10_preflight_provisioning.md) |
|
||||
| 120 | TensorRT INT8 calibration corpus size guidance (~500-1000 images) — Jetson AGX Orin (vendor engineering guide) | L2 | [C10](C10_preflight_provisioning.md) |
|
||||
| 121 | Direct TensorRT `IBuilderConfig` + `IInt8EntropyCalibrator2` Python API (NVIDIA TRT Python API docs, cross-cite from C7 #105) | L1 | [C10](C10_preflight_provisioning.md) |
|
||||
@@ -0,0 +1,119 @@
|
||||
# Source Registry — C10: Pre-flight cache provisioning (cross-coupling minimal scope)
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation). Sources for C10 batch 1 (cross-coupling minimal: D-C6-3 descriptor-cache rebuild trigger pipeline + D-C7-7 TensorRT engine-build pipeline). Sibling registries: [SQ1](SQ1_existing_systems.md), [SQ2](SQ2_canonical_pipeline.md), [SQ6](SQ6_external_positioning.md), [C1](C1_vio.md), [C2](C2_vpr.md), [C3](C3_matchers.md), [C4](C4_pose_estimation.md), [C5](C5_state_estimator.md), [C6](C6_tile_cache_spatial_index.md), [C7](C7_inference_runtime.md), [C8](C8_fc_adapter.md). Index: [`00_summary.md`](00_summary.md).
|
||||
>
|
||||
> Source-tier definitions per `references/source-tiering.md`: L1 = official primary docs / source code / canonical specs; L2 = official blog posts, vendor SDK docs, peer-reviewed papers; L3 = community Q&A, tutorial sites, secondary commentary; L4 = forum posts, mailing-list threads, single-author blog posts.
|
||||
|
||||
---
|
||||
|
||||
## Source #114 — FAISS `write_index` / `read_index` Python API + on-disk format + security warning (L1 official)
|
||||
|
||||
**URL**: <https://github.com/facebookresearch/faiss/wiki/Index-IO,-cloning-and-hyper-parameter-tuning> + context7 indexed at `/facebookresearch/faiss` (Benchmark Score consistent with C6 batch 1 Source #96 lookup)
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L1** — canonical FAISS GitHub Wiki + canonical context7-indexed documentation
|
||||
|
||||
**Relevance**: Confirms `faiss.write_index(index, path)` + `faiss.read_index(path)` Python API for serializing IndexHNSWFlat to disk and loading it back; confirms `IO_FLAG_MMAP_IFC` enables memory-mapped loading for HNSW + IndexFlatCodes-derived classes (zero-copy load — important for the project's <5 s takeoff load budget); documents the explicit security warning "No attempt is made to check the correctness of loaded data. A faulty or malicious file could lead to out-of-memory errors or code execution. Users are responsible for verifying that files loaded with `read_index` have not been altered since being written by `write_index`." This warning binds directly to AC-NEW-7 (cache-poisoning safety) and motivates the project-side content-hash verification gate before takeoff load. Confirms FAISS C++ signature: `void write_index(Index* index, const char* filename)` / `Index* read_index(const char* filename)`.
|
||||
|
||||
**Evidence quality**: ✅ High — L1 canonical FAISS docs. Direct API verification.
|
||||
|
||||
---
|
||||
|
||||
## Source #115 — FAISS IndexHNSWFlat per-vector memory + on-disk file size formula (L2 community + L1 cross-cite)
|
||||
|
||||
**URL**: <https://github.com/facebookresearch/faiss/discussions/3953> + cross-cite <https://faiss.ai/cpp_api/struct/structfaiss_1_1IndexHNSWFlat.html>
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L2** — FAISS GitHub Discussions thread (maintainer-confirmed answer) + L1 canonical FAISS C++ API docs cross-cite
|
||||
|
||||
**Relevance**: Confirms IndexHNSWFlat per-vector on-disk + RAM cost formula: `(vector_dim × 4 bytes) + (M × 4 bytes × 2) + overhead from graph layers and geometric reallocation`. For project's pinned VPR descriptor candidates (per D-C2-9 / D-C2-10 / D-C2-6 / D-C6-1 = halfvec): at 2048-D float32 + M=32 → 8192 + 256 = **8448 bytes/vector** (~845 MB on disk for 100K tiles); at 2048-D halfvec (2-byte storage per descriptor element) → 4096 + 256 = **4352 bytes/vector** (~430 MB on disk for 100K tiles); at 512-D halfvec + M=32 → 1024 + 256 = **1280 bytes/vector** (~130 MB on disk for 100K tiles); at 256-D halfvec + M=32 → 512 + 256 = **768 bytes/vector** (~80 MB on disk for 100K tiles). All variants well within AC-8.3 10 GB cache budget (assuming D-C2-10 EigenPlaces 512-D path or D-C6-1 halfvec mitigation). Supplementary cross-cite to C6 Fact #92 evidence base. **Load latency**: Issue #622 confirms post-load search performance is "slightly slower initially due to memory layout and cache effects" but identical results — implies a warmup-search-pass at takeoff after `read_index` would smooth p99 latency; aligns with the <5 s takeoff load budget (pure file read at ~430 MB / SATA SSD ~500 MB/s = <1 s; mmap path eliminates the read entirely).
|
||||
|
||||
**Evidence quality**: ✅ High — formula matches FAISS source code in `IndexHNSW.cpp`; multiple maintainer-confirmed reproductions; conservative for project's pinned descriptor dimensions per D-C2-9/10/6 closures.
|
||||
|
||||
---
|
||||
|
||||
## Source #116 — Python atomic file write pattern: write-to-temp + fsync + atomic rename (L2 reference + L1 POSIX standard cross-cite)
|
||||
|
||||
**URL**: <https://blog.gocept.com/2013/07/15/reliable-file-updates-with-python/> + <https://python-atomicwrites.readthedocs.io/en/stable> + Python tracker Issue 8604 <https://bugs.python.org/issue8604>
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L2** — well-known engineering blog reference + canonical Python package docs + Python core developer issue tracker
|
||||
|
||||
**Relevance**: Documents the canonical Python crash-safe atomic file write pattern required for the project's pre-flight FAISS index file write (and TensorRT engine file write). The pattern is: (1) write to a temporary file in the same directory as target (ensures same filesystem so `os.rename` is atomic), (2) call `fsync(temp_fd)` to flush content + metadata to disk, (3) atomically rename via `os.rename(temp_path, target_path)`, (4) call `fsync` on the parent directory to flush the filename change to disk. Without this pattern, a power loss or process kill mid-write leaves a truncated/partial file that `faiss.read_index` will load successfully (no internal integrity check per Source #114 warning) and produce silently-wrong descriptor matches at takeoff — direct violation of AC-NEW-7 (cache-poisoning safety) + AC-3.3 (re-localization stability). The `python-atomicwrites` package provides this pattern with a simple API: `with atomic_write(path, overwrite=True) as f: ...`; pure-Python; trivially auditable; cross-platform (Windows + POSIX + macOS). On macOS specifically, must use `fcntl.fcntl(fd, fcntl.F_FULLFSYNC)` instead of `os.fsync()` to handle Apple's user-space write buffers — not relevant for the Jetson deployment target (Linux/JetPack). Project-side wrapper around `faiss.write_index` should use this pattern to safely write the FAISS cache file alongside content-hash verification.
|
||||
|
||||
**Evidence quality**: ✅ High — pattern matches POSIX `rename(2)` atomicity guarantee; extensively documented; multiple production Python packages (atomicwrites, ruamel-yaml, etc.) implement it.
|
||||
|
||||
---
|
||||
|
||||
## Source #117 — Polygraphy `polygraphy convert` CLI for TensorRT INT8 engine build with calibration cache reuse (L1 official)
|
||||
|
||||
**URL**: <https://github.com/NVIDIA/TensorRT/blob/main/tools/Polygraphy/examples/cli/convert/01_int8_calibration_in_tensorrt/README.md> + context7 indexed at `/websites/nvidia_deeplearning_tensorrt_static_polygraphy` (1041 code snippets, Benchmark Score 67.2, Source Reputation High)
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L1** — official NVIDIA TensorRT source repository documentation + canonical Polygraphy docs
|
||||
|
||||
**Relevance**: Confirms Polygraphy as the canonical NVIDIA-blessed orchestration wrapper around TensorRT's engine build pipeline. Documents the canonical INT8 calibration workflow: first build with `--data-loader-script ./data_loader.py --calibration-cache identity_calib.cache` (computes scales + writes cache); subsequent builds with `--calibration-cache identity_calib.cache` (skips calibration step entirely — cache contains scales). Confirms Polygraphy's `Calibrator` class API: `data_loader` parameter (generator/iterable yielding `{input_name: numpy.ndarray}` dicts), `cache` parameter (calibration cache file path), `BaseClass` parameter (defaults to `trt.IInt8EntropyCalibrator2` — matches project's D-C7-2 + D-C7-6 lock), `algo` parameter (defaults to `trt.CalibrationAlgoType.MINMAX_CALIBRATION`). CLI supports `--int8 --fp16` mixed precision flags directly per project's D-C7-2 = (b) per-family precision policy. The full CLI invocation pattern for project: `polygraphy convert <model>.onnx --int8 --fp16 --data-loader-script ./calib_data_loader.py --calibration-cache <model>_calib.cache -o <model>_sm87_jp62_trt103_int8fp16.engine`. Polygraphy is bundled inside the TensorRT distribution (no separate install on Jetson — `pip install nvidia-pyindex && pip install polygraphy` or via TensorRT installer). Production-mature and cross-referenced from canonical TensorRT documentation.
|
||||
|
||||
**Evidence quality**: ✅ High — official NVIDIA repository docs, multi-snippet context7 coverage, production-mature tooling.
|
||||
|
||||
---
|
||||
|
||||
## Source #118 — Polygraphy `Calibrator` class API — algo defaults + dynamic-shapes calibration profile + warning behavior (L1 official)
|
||||
|
||||
**URL**: <https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/polygraphy/backend/trt/calibrator.html> + <https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/polygraphy/backend/trt/config.html>
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L1** — canonical NVIDIA TensorRT/Polygraphy SDK documentation
|
||||
|
||||
**Relevance**: Confirms `Calibrator(data_loader, cache=None, BaseClass=IInt8EntropyCalibrator2, algo=CalibrationAlgoType.MINMAX_CALIBRATION, batch_size=None, quantile=None, regression_cutoff=None)` full signature. Documents two algorithm choices: `IInt8EntropyCalibrator2` (entropy-based; project D-C7-2 default; Polygraphy default) vs `IInt8MinMaxCalibrator` (min-max scaling). Documents dynamic-shapes behavior: "if calibration is run and the model has dynamic shapes, the last optimization profile will be used as the calibration profile" — relevant for project's matchers if any of them export with dynamic input shapes (D-C3-2 LightGlue ONNX export pathway). Documents `--data-loader-script` / `--data-loader-func-name` CLI flags for supplying custom calibration data. Documents the "Int8 Calibration is using randomly generated input data" warning that fires when `--int8` is set but neither `--data-loader-script` nor an existing `--calibration-cache` is supplied — operationalizes the D-C7-1 closure (real UAV nadir flight footage corpus) as a pre-flight build prerequisite. CLI also supports `--load-tactics` / `--save-tactics` for replaying tactic-search results across multiple builds (faster than re-running tactic profiling each build) — useful for the reference-Jetson-prebuilt-engine fallback path per D-C7-7.
|
||||
|
||||
**Evidence quality**: ✅ High — canonical NVIDIA documentation, directly cited from polygraphy/tools/args/backend/trt/config source code.
|
||||
|
||||
---
|
||||
|
||||
## Source #119 — `trtexec` CLI for one-off engine builds — INT8/FP16 flags + calibration cache support (L1 official)
|
||||
|
||||
**URL**: <https://docs.nvidia.com/deeplearning/tensorrt/latest/getting-started/quick-start-guide.html> + <https://docs.nvidia.com/deeplearning/tensorrt/latest/reference/command-line-programs.html>
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L1** — canonical NVIDIA TensorRT SDK documentation
|
||||
|
||||
**Relevance**: Confirms `trtexec` as the simpler-but-less-flexible TensorRT engine build CLI bundled with every TensorRT installation. Canonical invocation: `trtexec --onnx=model.onnx --saveEngine=model.engine --fp16 --int8 --calib=calibration.cache --shapes=input:1x3x224x224`. Supports `--int8 --fp16` mixed precision (matches project's D-C7-2). Supports `--calib=<cache_path>` for INT8 calibration cache reuse (cache file format identical to Polygraphy's; the two tools are interoperable on the calibration cache layer). **Critical limitation vs Polygraphy**: `trtexec --int8` without `--calib` causes TRT to use random data for calibration (per TRT docs warning) — this collapses INT8 accuracy by ~5-15%. **Strength**: single-binary; no Python imports; no calibration data loader script required; perfect for emergency rebuilds when an existing calibration cache is available; perfect for ad-hoc benchmarking via `--iterations=N --useCudaGraph --noDataTransfers`. **Recommended role for project**: fallback orchestration tool when Polygraphy is unavailable OR when calibration cache is already shipped from a reference build (e.g., the prebuilt-engine fallback per D-C7-7).
|
||||
|
||||
**Evidence quality**: ✅ High — canonical NVIDIA documentation; trtexec is bundled with TensorRT distributions and has been the canonical TensorRT CLI since TensorRT 5.x.
|
||||
|
||||
---
|
||||
|
||||
## Source #120 — TensorRT INT8 INT8 calibration corpus size guidance (~500-1000 images) — Jetson AGX Orin specific (L2 vendor)
|
||||
|
||||
**URL**: <https://nvnexus.com/tensorrt-jetson-agx-orin-optimization-guide/>
|
||||
|
||||
**Date accessed**: 2026-05-08
|
||||
|
||||
**Tier**: **L2** — vendor-aligned engineering guide (TensorRT-on-Jetson specialist content), cross-cited from official NVIDIA Developer Forum patterns
|
||||
|
||||
**Relevance**: Independent confirmation of the project's D-C7-1 closure: "INT8 optimization can double inference throughput on Jetson AGX Orin with minimal accuracy loss; calibration on representative input data (500-1000 images recommended)". Aligns with project's pinned 500-1500 sample range from C7 batch 1 Fact #94. Cross-cite to AGX Orin (server-class Jetson) — the project's deployment target is Orin Nano Super (smaller class), but the calibration-corpus-size guidance is governed by the model + INT8 entropy-statistics requirement, not by the Jetson SKU. **Conservative confirmation**: project's calibration corpus target of 500-1500 samples per D-C7-1 closure is sufficient by community-confirmed benchmarks.
|
||||
|
||||
**Evidence quality**: ⚠️ Medium-High — L2 vendor-aligned source; aligns with multiple independent confirmations including NVIDIA Developer Forum threads and the canonical TensorRT INT8 calibration documentation; project's D-C7-1 closure already pinned this range from L1 sources.
|
||||
|
||||
---
|
||||
|
||||
## Source #121 — Direct TensorRT `IBuilderConfig` + `IInt8EntropyCalibrator2` Python API (L1 official, cross-cite from C7 Source #105)
|
||||
|
||||
**URL**: <https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/python/api/infer/Core/BuilderConfig.html> (cross-cite from C7 batch 1 Source #105 + Source #102)
|
||||
|
||||
**Date accessed**: 2026-05-08 (cross-cite)
|
||||
|
||||
**Tier**: **L1** — canonical NVIDIA TensorRT Python API documentation
|
||||
|
||||
**Relevance**: Already cited in C7 batch 1 Source #102 + Source #105 (mode pinning for D-C7-2). Re-cited here for the C10 D-C7-7 confirmation context: confirms direct `IBuilderConfig` + `IInt8EntropyCalibrator2` Python API as the most-flexible-but-most-engineering-cost orchestration option. Pattern: instantiate `trt.Builder(logger)` → `builder.create_network(...)` → parse ONNX via `trt.OnnxParser` → instantiate `builder.create_builder_config()` → `config.set_flag(trt.BuilderFlag.INT8)` + `config.set_flag(trt.BuilderFlag.FP16)` → assign custom `Int8EntropyCalibrator2` subclass instance to `config.int8_calibrator` → `config.max_workspace_size = 1 << 30` (1 GB per D-C7-8) → `serialized_engine = builder.build_serialized_network(network, config)` → `with open(path, 'wb') as f: f.write(serialized_engine)`. **Used in C10 only as the per-model fallback path for the reference-Jetson-prebuilt-engine generation** (D-C7-7 fallback) when Polygraphy's data-loader-script abstraction is too rigid for an unusual model (e.g., LightGlue with dynamic-shape inputs requiring a custom calibration profile).
|
||||
|
||||
**Evidence quality**: ✅ High — canonical NVIDIA Python API; cross-cite from existing C7 Source #105 reduces redundancy.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,192 @@
|
||||
# Source Registry — C1 — Visual / Visual-Inertial Odometry candidates
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> This file replaces a section of the previous monolithic `01_source_registry.md`. See `00_summary.md` for the full category index. Investigation order is tracked in `../00_question_decomposition.md` and the cross-category Investigation Status table in `00_summary.md`.
|
||||
|
||||
---
|
||||
|
||||
### Source #43
|
||||
- **Title**: VINS-Mono — A Robust and Versatile Monocular Visual-Inertial State Estimator (HKUST-Aerial-Robotics)
|
||||
- **Link**: https://github.com/HKUST-Aerial-Robotics/VINS-Mono ; LICENCE: https://github.com/HKUST-Aerial-Robotics/VINS-Mono/blob/master/LICENCE
|
||||
- **Tier**: L1 (canonical reference implementation; published in IEEE T-RO 2018 by Qin, Li, Shen)
|
||||
- **Publication Date**: original 2018; repository last meaningful update 2024-02-25 (per GitHub commit log; 2024-05-23 simulation-data commit only)
|
||||
- **Timeliness Status**: ⚠️ **Borderline.** ~24 months since the last meaningful master-branch commit at access time (2026-05-07). Established baseline that does NOT trigger Step 0.5's 18-month timeliness rejection because (a) IEEE T-RO publication is the canonical authority for the algorithm, (b) downstream forks (vins-mono-android, embedded variants) keep the algorithm class actively deployed.
|
||||
- **Version Info**: No GitHub releases / tags (master-branch-only project). Stars 5,829.
|
||||
- **Target Audience**: Mono+IMU VIO implementers; UAV state estimation researchers
|
||||
- **Research Boundary Match**: **Full match for the candidate's pinned mode** — monocular camera + IMU producing 6-DoF metric pose. The VINS-Mono README explicitly names this configuration as primary.
|
||||
- **Summary**: Optimization-based sliding-window monocular VIO. Features: efficient IMU pre-integration (Forster et al. 2017), automatic initialization, online camera-IMU extrinsic calibration, online camera-IMU temporal calibration, failure detection + recovery, loop detection (DBoW2-based), global pose graph optimization. Output is metric-scale 6-DoF pose at IMU rate (typically 100–200 Hz) with covariance from the optimization Hessian. **License: GPL-3.0 (copyleft viral)** — every binary distribution requires source disclosure for the entire linked binary; relevant for dual-use deployment if the companion image is sold or transferred to a customer.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 lead candidate
|
||||
|
||||
|
||||
### Source #44
|
||||
- **Title**: VINS-Fusion — Optimization-based multi-sensor state estimator (HKUST-Aerial-Robotics)
|
||||
- **Link**: https://github.com/HKUST-Aerial-Robotics/VINS-Fusion ; LICENCE: https://github.com/HKUST-Aerial-Robotics/VINS-Fusion/blob/master/LICENCE
|
||||
- **Tier**: L1 (canonical reference; superset of VINS-Mono)
|
||||
- **Publication Date**: original 2019 (Qin, Cao, Pan, Shen — ICRA workshop / IROS); repository last update 2024-05-23
|
||||
- **Timeliness Status**: ⚠️ **Borderline.** ~24 months since the last update at access time. Same Step-0.5 reasoning as VINS-Mono — established class.
|
||||
- **Version Info**: master-branch-only. Stars 4,476. Top-ranked open-source stereo-VIO on KITTI Odometry as of January 2019.
|
||||
- **Target Audience**: Multi-sensor VIO implementers (mono+IMU, stereo, stereo+IMU, +GPS fusion)
|
||||
- **Research Boundary Match**: **Full match** for monocular+IMU mode. VINS-Fusion README explicitly enumerates four sensor configurations (mono+IMU, stereo, stereo+IMU, +GPS toy example).
|
||||
- **Summary**: Superset of VINS-Mono adding stereo and GPS-fusion modes. Same algorithmic core (sliding-window optimization with IMU pre-integration). Online spatial + temporal camera-IMU calibration; visual loop closure; ROS Kinetic/Melodic build dependency. **License: GPL-3.0** — same dual-use distribution constraint as VINS-Mono. Independent KAIST benchmark (Source #46) found VINS-Fusion CPU mode + VINS-Fusion-imu **fail to run** on Jetson TX2 (insufficient memory and CPU); GPU-accelerated VINS-Fusion-gpu does run on TX2. Implication for project: VINS-Fusion-imu on Jetson Orin Nano Super is feasible but not certain; needs MVE.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 lead candidate
|
||||
|
||||
|
||||
### Source #45
|
||||
- **Title**: OpenVINS — An open source platform for visual-inertial navigation research (Robot Perception and Navigation Group, U. of Delaware — rpng)
|
||||
- **Link**: https://github.com/rpng/open_vins ; docs: https://docs.openvins.com/ ; LICENSE: https://github.com/rpng/open_vins/blob/master/LICENSE
|
||||
- **Tier**: L1 (canonical research implementation; ICRA 2020 paper Geneva, Eckenhoff, Lee, Yang, Huang)
|
||||
- **Publication Date**: original 2020; latest tagged release v2.7 = 2023-06; ongoing master-branch commits through 2024–2025 (latest issue threads through Feb 2025)
|
||||
- **Timeliness Status**: ✅ Currently valid (master branch active; latest tagged release ~35 months but library is in stable/maintenance mode with continued issue triage).
|
||||
- **Version Info**: Stars 2,828; 30 contributors; 12 releases. v2.7 is the current tagged stable.
|
||||
- **Target Audience**: MSCKF/EKF VIO implementers; researchers needing a reference MSCKF
|
||||
- **Research Boundary Match**: **Full match** for monocular+IMU mode. OpenVINS supports mono, stereo, multi-camera (1–N cameras) + IMU; mono is a documented first-class mode.
|
||||
- **Summary**: Modular MSCKF (Multi-State Constraint Kalman Filter) implementation built around an Extended Kalman filter that fuses inertial state with sparse visual feature tracks via the sliding-window MSCKF formulation (Mourikis & Roumeliotis 2007). Supports SLAM features (in-state landmarks) plus pure MSCKF features (out-of-state). ROS1 + ROS2 (Humble) builds documented; Jetson Orin Nano Dev Kit + JetPack 6 + ROS 2 Humble compilation **confirmed working** by community contributors (rpng/open_vins issue #421, fdcl-gwu/openvins_jetson_realsense Nov 2025 setup guide). **License: GPL-3.0** — same dual-use distribution constraint. Reported latency ~270 ms on Xavier NX (4-core, ARM, 40% CPU usage) per issue #164; needs Jetson-Orin-Nano-Super MVE for production budget verification.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 lead candidate
|
||||
|
||||
|
||||
### Source #46
|
||||
- **Title**: Run Your Visual-Inertial Odometry on NVIDIA Jetson — Benchmark Tests on a Micro Aerial Vehicle (Jeon, Jung, Lee, Choi, Myung — KAIST)
|
||||
- **Link**: https://arxiv.org/abs/2103.01655 ; KAIST VIO dataset: https://github.com/zinuok/kaistviodataset
|
||||
- **Tier**: L1 (peer-reviewed conference, IROS-track preprint with public dataset)
|
||||
- **Publication Date**: arXiv 2021-03-02
|
||||
- **Timeliness Status**: ⚠️ Older than the 18-month Critical-novelty window, but **uniquely authoritative** for the specific question "do these VIO algorithms run on a Jetson?"; the included algorithms (VINS-Mono, VINS-Fusion, ROVIO, ALVIO, Stereo-MSCKF, Kimera, ORB-SLAM2-stereo) are all classical baselines whose runtime characteristics on ARM CPUs have not changed materially. Jetson hardware comparison (TX2 / Xavier NX / AGX Xavier) does NOT include Orin Nano — must extrapolate.
|
||||
- **Version Info**: Conference paper.
|
||||
- **Target Audience**: UAV state-estimation engineers picking a VIO for a Jetson companion
|
||||
- **Research Boundary Match**: **Strong match for the question**, partial for the hardware (no Orin Nano). KAIST VIO dataset is indoor mocap, not UAV-aerial-nadir — the *latency / CPU / memory* numbers transfer; the *accuracy* numbers do not transfer to our domain.
|
||||
- **Summary**: Comprehensive benchmark of 9 algorithms on TX2, Xavier NX, AGX Xavier: VINS-Mono, VINS-Fusion (CPU), VINS-Fusion-gpu, VINS-Fusion-imu, ROVIO, Stereo-MSCKF, ALVIO, Kimera, ORB-SLAM2-stereo. **Hard findings**: (a) on TX2, **VINS-Fusion (CPU) and VINS-Fusion-imu fail to run** due to insufficient memory and CPU performance — VINS-Fusion-gpu does run; (b) all algorithms except ROVIO show >100% CPU usage (multi-core utilisation, OK for our 6-core Orin Nano A78AE); (c) Kimera has the highest memory usage among VIO methods (numerous computations per keyframe), failure-prone on Xavier NX-class memory; (d) Stereo-MSCKF has the lowest memory among stereo VIOs; (e) ROVIO has the lowest CPU usage owing to its patch-tracking formulation. **Implication for project**: Jetson Orin Nano Super (8 GB shared, 6-core A78AE, Ampere GPU, 67 TOPS sparse INT8) is between Xavier NX and AGX Xavier in CPU performance and memory; algorithms passing on Xavier NX should pass on Orin Nano Super, but VINS-Fusion-imu's TX2 failure is a yellow-flag for memory pressure under co-resident C2/C3/C5 modules.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 (VINS-Mono / VINS-Fusion / OpenVINS / Kimera / Stereo-MSCKF / ROVIO Jetson runtime evidence), SQ5 (resource-budget failure modes)
|
||||
|
||||
|
||||
### Source #47
|
||||
- **Title**: OKVIS2 — Realtime Scalable Visual-Inertial SLAM with Loop Closure (Leutenegger, ETH/Imperial/TUM Smart Robotics Lab)
|
||||
- **Link**: https://github.com/ethz-mrl/okvis2 ; arXiv: https://arxiv.org/abs/2202.09199 ; LICENSE: https://github.com/ethz-mrl/okvis2/blob/main/LICENSE
|
||||
- **Tier**: L1 (canonical implementation; arXiv 2022 by paper author)
|
||||
- **Publication Date**: original arXiv 2022; OKVIS2-X T-RO 2025 successor (Boche, Jung, Laina, Leutenegger — IEEE T-RO 2025, vol 41 pp 6064–6083, DOI 10.1109/TRO.2025.3619051; arXiv 2510.04612, Oct 2025). Repository last push 2026-03-17 (ethz-mrl/OKVIS2-X).
|
||||
- **Timeliness Status**: ✅ **Current.** Active development through 2026; OKVIS2-X is the most recent published VI-SLAM system in this class.
|
||||
- **Version Info**: ethz-mrl/okvis2 (core) and ethz-mrl/OKVIS2-X (multi-sensor extension with optional GNSS / LiDAR / dense depth).
|
||||
- **Target Audience**: Factor-graph VI-SLAM implementers; mid-large-scale loop-closure use cases
|
||||
- **Research Boundary Match**: **Full match** for monocular+IMU mode. OKVIS2 README + paper explicitly support mono and multi-camera VI configurations. OKVIS2-X adds GNSS fusion (relevant: VINS-Fusion-style GPS-when-available drop-in IS the project's eventual posture in non-spoofed regions).
|
||||
- **Summary**: Factor-graph VI-SLAM with bounded-size optimization. Innovation: pose-graph edges from marginalised observations can be "seamlessly turned back into observations" upon loop closure, reviving old landmarks and reprojection errors. Includes lightweight CNN segmentation for dynamic-region removal. OKVIS2-X (2025) generalises the core to fuse multi-camera + IMU + optional GNSS + LiDAR/depth — directly aligned with project's "VIO that may opportunistically fuse a non-spoofed GPS update" pattern and AC-NEW-2's spoof-promotion path. **License: 3-clause BSD (permissive)** — no copyleft / dual-use distribution friction. Note: GitHub UI shows "Other (NOASSERTION)" because of the standard BSD clause language pattern; the LICENSE file is canonical 3-clause BSD.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 lead candidate (factor-graph + permissive license + active maintenance)
|
||||
|
||||
|
||||
### Source #48
|
||||
- **Title**: OKVIS2-X: Open Keyframe-based Visual-Inertial SLAM Configurable with Dense Depth or LiDAR, and GNSS (Boche, Jung, Laina, Leutenegger — TUM / ETH Zurich Smart Robotics Lab)
|
||||
- **Link**: https://github.com/ethz-mrl/OKVIS2-X ; arXiv: https://arxiv.org/abs/2510.04612 ; IEEE T-RO 2025 vol 41 pp 6064–6083 DOI 10.1109/TRO.2025.3619051
|
||||
- **Tier**: L1 (peer-reviewed IEEE Transactions on Robotics, Special Issue Visual SLAM 2025)
|
||||
- **Publication Date**: arXiv 2025-10-04; T-RO 2025 vol 41
|
||||
- **Timeliness Status**: ✅ Current (within 6-month Critical-novelty window)
|
||||
- **Version Info**: 295 stars; 38 forks; 2 contributors; created 2025-09-23, last push 2026-03-17. License: NOASSERTION on GitHub UI; per-paper license follows ethz-mrl convention (BSD-3 derived).
|
||||
- **Target Audience**: Multi-sensor SLAM researchers; large-scale VI-SLAM with optional GNSS/LiDAR
|
||||
- **Research Boundary Match**: **Strong match** — extends OKVIS2 monocular+IMU mode with optional GNSS fusion (Visual-Inertial SLAM with Tightly-Coupled Dropout-Tolerant GPS Fusion lineage from IROS 2022). Project's `MAV_CMD_SET_EKF_SOURCE_SET` switch + companion-side spoof-detection conceptually mirrors OKVIS2-X's "GPS as drop-out-tolerant signal".
|
||||
- **Summary**: Non-trivial extension of OKVIS2; submap-based volumetric occupancy mapping. Demonstrates that the OKVIS2 factor-graph backbone can absorb spoofing-aware GPS without re-architecting. Useful as architectural template for project's C5 estimator + C8 adapter integration. License: same as OKVIS2 (BSD-3-derived). Two named contributors (bochsim, SebsBarbas) actively pushing through Mar 2026.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 (OKVIS2 lineage; VI-SLAM with optional GPS/LiDAR), SQ8 (GPS-fusion dropout-tolerant lineage)
|
||||
|
||||
|
||||
### Source #49
|
||||
- **Title**: Kimera-VIO — Visual Inertial Odometry with SLAM capabilities and 3D Mesh generation (MIT-SPARK)
|
||||
- **Link**: https://github.com/MIT-SPARK/Kimera-VIO ; LICENSE.BSD: https://github.com/MIT-SPARK/Kimera-VIO/blob/master/LICENSE.BSD
|
||||
- **Tier**: L1 (canonical implementation by MIT SPARK Lab)
|
||||
- **Publication Date**: original 2020 (Rosinol, Abate, Chang, Carlone — ICRA 2020); ongoing development through 2024–2025 issue threads (Dec 2024 / Feb 2025 ROS2 / mono-inertial discussion).
|
||||
- **Timeliness Status**: ✅ Active maintenance (recent issues / PRs through 2025).
|
||||
- **Version Info**: master-branch-only; LICENSE.BSD = BSD 2-Clause "Simplified".
|
||||
- **Target Audience**: VI-SLAM + mesh-mapping researchers
|
||||
- **Research Boundary Match**: **Partial.** Stereo+IMU is the primary supported configuration; mono+IMU is **optional but documented**. Kimera also produces 3D mesh and high-level semantic labels (relevant to neither C1 nor the project's bandwidth budget — overhead).
|
||||
- **Summary**: Frontend (image processing + IMU pre-integration) + Backend (factor-graph optimization in iSAM2 or GTSAM) + Mesher + Pose-Graph-Optimizer. **License: BSD 2-Clause (permissive)** — no dual-use distribution friction. **Penalty for project**: Source #46 KAIST benchmark found Kimera has highest memory usage among the VIOs tested (numerous computations per keyframe), and Kimera failed to fit on Xavier-NX-class memory under multi-process load. Mesh + semantic features are unused by the project — Kimera's overhead is unjustified vs OKVIS2 / OpenVINS for the project's narrow C1 mandate. **Status**: viable secondary fallback if OKVIS2 / VINS-Mono runtime issues arise; not a lead candidate due to overhead misfit.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 secondary candidate (BSD-permissive but resource-heavy)
|
||||
|
||||
|
||||
### Source #50
|
||||
- **Title**: DROID-SLAM — Deep Visual SLAM for Monocular, Stereo, and RGB-D Cameras (princeton-vl, Teed & Deng)
|
||||
- **Link**: https://github.com/princeton-vl/droid-slam ; arXiv: https://arxiv.org/abs/2108.10869 ; NeurIPS 2021
|
||||
- **Tier**: L1 (canonical reference)
|
||||
- **Publication Date**: NeurIPS 2021; repository latest tagged baseline.
|
||||
- **Timeliness Status**: ✅ Foundational reference; DPV-SLAM (Source #51) is the lighter successor.
|
||||
- **Version Info**: master-branch-only.
|
||||
- **Target Audience**: Deep-learning-based VO/VSLAM researchers
|
||||
- **Research Boundary Match**: **Disqualified by hardware budget.** Inference requires ≥11 GB GPU VRAM per official README; project budget is 8 GB **shared CPU+GPU** on Jetson Orin Nano Super, leaving <8 GB for VO + VPR + matcher + estimator + cache co-resident. DROID-SLAM is also **monocular VO/SLAM, not VIO** — no native IMU fusion; metric scale recovery requires external scale alignment.
|
||||
- **Summary**: Recurrent dense bundle adjustment over a complete history of camera poses. State-of-the-art accuracy on TartanAir / EuRoC / TUM-RGBD at the cost of GPU memory. **Disqualified outright for C1 lead** by AC-4.2 (≤8 GB shared RAM) and the lack of IMU fusion that would require an additional ESKF/UKF wrapping. Kept as **reference baseline** to be cited as "what we cannot afford" in `solution_draft01`.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 disqualified candidate
|
||||
|
||||
|
||||
### Source #51
|
||||
- **Title**: DPVO — Deep Patch Visual Odometry (princeton-vl, Teed, Lipson, Deng) + DPV-SLAM (Lipson, Teed, Deng — ECCV 2024)
|
||||
- **Link**: https://github.com/princeton-vl/DPVO ; LICENSE: https://github.com/princeton-vl/DPVO/blob/main/LICENSE ; ECCV 2024 paper: https://www.ecva.net/papers/eccv_2024/papers_ECCV/papers/00272.pdf
|
||||
- **Tier**: L1 (canonical implementation; NeurIPS 2023 + ECCV 2024)
|
||||
- **Publication Date**: NeurIPS 2023 (DPVO); ECCV 2024 (DPV-SLAM); repository last update 2024-10-12.
|
||||
- **Timeliness Status**: ⚠️ Borderline. ~19 months since last code update; ECCV-2024 publication of DPV-SLAM keeps the algorithm class within the 6-month claim window for the SLAM successor.
|
||||
- **Version Info**: 989 stars; primary languages C++ / Python / CUDA. **License: MIT (permissive)** — no dual-use distribution friction.
|
||||
- **Target Audience**: Deep-learning VO/SLAM with reduced memory footprint
|
||||
- **Research Boundary Match**: **Partial.** DPVO is **monocular VO only — no IMU fusion**. Output pose is in arbitrary scale (no metric scale recovery). To be a viable C1 candidate the project must wrap DPVO with an external IMU+scale-fusion stage (loosely-coupled ESKF / VIO-fusion module). This makes DPVO **not a drop-in C1** like VINS-Mono / OpenVINS / OKVIS2; it is a **VO module that needs a separate VIO wrapper**.
|
||||
- **Summary**: Sparse patch tracking + differentiable bundle adjustment back end. Outperforms DROID-SLAM on TartanAir / EuRoC ATE while using ~1/3 of DROID-SLAM's GPU memory (DROID-SLAM: 8.7 GB VO mode vs DPVO: ~3 GB). DPV-SLAM (Lipson, Teed, Deng — ECCV 2024) adds full SLAM capability with 4–5 GB GPU usage. **Jetson runtime evidence**: indirect via DPVO-QAT++ (Source #52) — peak reserved memory 1.02 GB on RTX 4060 (8 GB) after INT8 fake-quant + custom CUDA kernel fusion; not directly tested on Jetson Orin Nano. **Status for C1**: pure-VO candidate (must be paired with separate IMU integration to deliver metric scale + attitude); would not satisfy "monocular VIO" gate alone, but viable as the *VO half* of a hybrid C1+C5 design.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 conditional candidate (VO not VIO; needs external IMU wrapper)
|
||||
|
||||
|
||||
### Source #52
|
||||
- **Title**: DPVO-QAT++: Heterogeneous QAT and CUDA Kernel Fusion for High-Performance Deep Patch Visual Odometry (Cheng Liao)
|
||||
- **Link**: https://arxiv.org/abs/2511.12653 ; project HTML: https://arxiv.org/html/2511.12653
|
||||
- **Tier**: L2 (single-author preprint, code partially released; no peer-review yet)
|
||||
- **Publication Date**: arXiv 2025-11-16 (within 6-month Critical-novelty window)
|
||||
- **Timeliness Status**: ✅ Current
|
||||
- **Version Info**: arXiv preprint; code & weights released for QAT-only and fused-CUDA variants.
|
||||
- **Target Audience**: Embedded-platform DPVO deployers
|
||||
- **Research Boundary Match**: **Partial.** Hardware tested = RTX 4060 (8 GB) + Intel Core Ultra 5-125H + 32 GB RAM — desktop GPU, NOT Jetson Orin Nano. Direct extrapolation requires Jetson MVE; Orin Nano Super's Ampere GPU is architecturally similar but smaller than RTX 4060.
|
||||
- **Summary**: Quantization-Aware Training framework for DPVO with fused CUDA kernels. Reduces peak GPU memory from 1.94 GB → 1.02 GB (-47%) on a representative TartanAir sequence; +34.6% median FPS on TartanAir, +26.7% on EuRoC; -22.8 ms / -19.7 ms median P99 tail latency on TartanAir / EuRoC respectively. Heterogeneous precision: front-end pseudo-quantization (FP16/FP32 with INT8 simulation) + FP32 back-end geometric solver. **Implication for project**: shows DPVO has a documented Jetson-suitable footprint **path** but not a Jetson-Orin-Nano measurement. ATE accuracy comparable to baseline DPVO across 32 TartanAir + 11 EuRoC validation sequences. Notable: requires a teacher-student distillation training pipeline before deployment — adds operational complexity vs classical VINS-* / OpenVINS / OKVIS2.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 supporting evidence for DPVO embedded feasibility
|
||||
|
||||
|
||||
### Source #53
|
||||
- **Title**: Pure VO baseline — KLT optical flow + 5-point essential matrix or homography RANSAC (OpenCV reference)
|
||||
- **Link**: https://docs.opencv.org/4.x/d4/dee/tutorial_optical_flow.html ; representative public implementation: https://github.com/alishobeiri/Monocular-Video-Odometery (MIT, 2018) ; tutorial reference: https://zxh.me/posts/2022-12-19-monocular-visual-odometry/
|
||||
- **Tier**: L1 (OpenCV official documentation) + L2 (representative public implementations)
|
||||
- **Publication Date**: OpenCV docs continuously updated; tutorial 2022-12; reference implementation 2018 (algorithmic class is foundational, no time window per Step 0.5)
|
||||
- **Timeliness Status**: ✅ Foundational baseline (no time window).
|
||||
- **Version Info**: OpenCV `cv::calcOpticalFlowPyrLK` (KLT) + `cv::findEssentialMat` (5-point Nister) or `cv::findHomography` with RANSAC.
|
||||
- **Target Audience**: Implementers needing a transparent low-complexity fallback
|
||||
- **Research Boundary Match**: **Full match for the simple-baseline candidate.** Suits planar nadir-down UAV at altitude (Ukrainian steppe is ~planar at 1 km AGL — homography is geometrically appropriate; for non-planar relief the essential matrix path is more appropriate but adds scale-recovery work).
|
||||
- **Summary**: Established classical pipeline: Shi-Tomasi or FAST corner detection → KLT pyramidal optical flow tracking → 5-point essential matrix or homography RANSAC → relative pose with arbitrary scale (must be metric-scale-aligned via IMU integration externally). Reference implementations widely available in OpenCV samples and pedagogical repos. **Status**: candidate as the project's `Simple baseline / known-runnable / known-failure-mode` C1 option per Component Option Breadth rule. Not a lead, but mandatory fallback presence per the research engine's "include at least one simple baseline" rule.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 simple-baseline candidate
|
||||
|
||||
|
||||
### Source #54
|
||||
- **Title**: OpenVINS — `context7` per-mode capability lookup (`/rpng/open_vins`, master)
|
||||
- **Link**: context7 query against `/rpng/open_vins`, accessed 2026-05-08; canonical doc references returned: `https://github.com/rpng/open_vins/blob/master/docs/gs-tutorial.dox`, `https://github.com/rpng/open_vins/blob/master/docs/gs-datasets.dox`, `https://github.com/rpng/open_vins/blob/master/docs/gs-calibration.dox`, `https://github.com/rpng/open_vins/blob/master/docs/propagation-analytical.dox`
|
||||
- **Tier**: L1 (project-official documentation reachable via the project's documentation generator)
|
||||
- **Publication Date**: live docs (master, accessed 2026-05-08)
|
||||
- **Timeliness Status**: ✅ Within Critical-novelty window (active master + community evidence through 2025–2026)
|
||||
- **Version Info**: master HEAD at access time (no tagged release for ROS 2 path; ROS 1 / ROS 2 build paths both documented)
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Research Boundary Match**: **Full match** for monocular + IMU mode. The `subscribe.launch.py` ROS 2 launch script (and its ROS 1 sibling) declare `use_stereo` and `max_cameras` as DeclareLaunchArguments — setting `use_stereo:=false max_cameras:=1` selects monocular operation; `config:=` selects an estimator-config directory (`euroc_mav`, `tum_vi`, `rpng_aruco`, …). KALIBR + RPNG IMU intrinsic calibration models are both documented in `propagation-analytical.dox` with the corresponding state-vector composition.
|
||||
- **Summary**: Confirms documentary evidence for OpenVINS' three sensor configurations exposed at the launch layer (mono / stereo / multi-camera), all with IMU mandatory; confirms the project's pinned mode (`use_stereo:=false max_cameras:=1`) is a first-class launch configuration that requires no source patch. Confirms that estimator config files in `ov_msckf/config/<dataset>/estimator_config.yaml` are the parameter-tuning surface and that supported IMU intrinsic models include both KALIBR and RPNG. **Open**: `context7` Disqualifier-Probe query did not surface explicit per-mode latency/memory limits or sub-20-Hz validation evidence; those constraints carry into the Jetson-Orin-Nano-Super hardware MVE (D-C1-2 deferred phase).
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 — OpenVINS per-mode API capability verification (Mandatory `context7` lookup per Per-Mode API Capability Verification rule)
|
||||
|
||||
|
||||
### Source #55
|
||||
- **Title**: VINS-Mono — official README + VINS-Fusion `context7` per-mode capability lookup (`/hkust-aerial-robotics/vins-fusion`, master) [cross-source documentary evidence for the mono+IMU mode shared with VINS-Mono]
|
||||
- **Link**: VINS-Mono README — https://raw.githubusercontent.com/HKUST-Aerial-Robotics/VINS-Mono/master/README.md (accessed 2026-05-08); VINS-Fusion docs — context7 query against `/hkust-aerial-robotics/vins-fusion`, accessed 2026-05-08, canonical reference returned: https://github.com/hkust-aerial-robotics/vins-fusion/blob/master/README.md
|
||||
- **Tier**: L1 (project-official READMEs of both repos)
|
||||
- **Publication Date**: VINS-Mono README — 2019-01-11 last major revision (master-branch only, no tagged releases); VINS-Fusion docs — live (master, accessed 2026-05-08)
|
||||
- **Timeliness Status**: ⚠️ borderline (per Step 0.5 timeliness — VINS-Mono master last meaningful commit 2024-02-25 / 2024-05-23; older than the 18-month preferred window for live API behaviour, but the algorithm class remains the canonical mono+IMU sliding-window VIO referenced by 2025 community work — see Fact #36)
|
||||
- **Version Info**: VINS-Mono master HEAD; depends on Ceres v1.14.0 (versions ≥2.0.0 have build issues per README). VINS-Fusion master HEAD has `euroc_mono_imu_config.yaml` as a first-class config.
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Research Boundary Match**: **Full match** for the project's pinned mode (mono + IMU). VINS-Mono is single-mode by construction — "real-time SLAM framework for **Monocular Visual-Inertial Systems**" — the project's pinned mode is the only mode the project will use the binary in. VINS-Fusion `euroc_mono_imu_config.yaml` is the documentary cross-source evidence that the algorithmic mono+IMU path remains a first-class configuration in the same authors' active fork.
|
||||
- **Summary**: Confirms VINS-Mono = monocular + IMU only (single mode); ROS Kinetic / Ubuntu 16.04 reference build; pinhole + MEI camera models supported; rolling-shutter support with calibrated reprojection error <0.5 px; online camera-IMU extrinsic + temporal calibration; loop closure via DBoW2; pose-graph reuse and map merge supported. **Critical recommended-input bound**: README §5.1 — *"The image should exceed 20Hz and IMU should exceed 100Hz."* — the project's nav cam target is 3 fps; this is a documentary signal that VIO performance below the recommended frame rate is not validated by the upstream authors. License: GPLv3 (confirmed in README §8). **Cross-source note**: VINS-Fusion `euroc_mono_imu_config.yaml` is named explicitly in `context7` results and uses the same algorithmic core; treat as evidence for VINS-Mono's mono+IMU mode while honouring the per-mode rule that VINS-Fusion's mono+IMU mode is a separately-cataloged candidate (Fact #29).
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 — VINS-Mono per-mode API capability verification (Mandatory `context7` lookup per Per-Mode API Capability Verification rule, with cross-source documentary evidence from VINS-Fusion since VINS-Mono itself is not indexed in `context7`)
|
||||
|
||||
|
||||
### Source #56
|
||||
- **Title**: OKVIS2 — official README (`smartroboticslab/okvis2`, main)
|
||||
- **Link**: https://raw.githubusercontent.com/smartroboticslab/okvis2/main/README.md (accessed 2026-05-08); papers cited in README: arXiv:2202.09199 (Leutenegger 2022), IJRR 2015, RSS 2013
|
||||
- **Tier**: L1 (project-official README; arXiv canonical paper)
|
||||
- **Publication Date**: README live; canonical paper 2022-02; OKVIS2 master last push within the Critical-novelty window (per Fact #36 timeliness audit, OKVIS2-X 2026-03-17 push confirms active)
|
||||
- **Timeliness Status**: ✅ Fully within Critical-novelty window
|
||||
- **Version Info**: OKVIS2 main HEAD; cmake build with optional ROS 2 wrapping (`BUILD_ROS2=ON`); optional sky-segmentation CNN via LibTorch (`USE_NN=OFF` to disable)
|
||||
- **Target Audience**: System architects + C1 implementer + Step-7.5 reviewer
|
||||
- **Research Boundary Match**: **Full match** for the project's pinned mode (mono + IMU). README confirms multi-camera support (camera frames `C_i` for the i-th camera) plus IMU mandatory; mono operation is a documented configuration via the example apps (`okvis_app_synchronous`, `okvis_app_realsense`). OKVIS2-X is the GNSS-fusion extension (T-RO 2025) that aligns architecturally with the project's spoof-promotion path.
|
||||
- **Summary**: Confirms OKVIS2 = keyframe-based VI-SLAM (factor-graph backbone with loop closure); BSD-3 license (no copyleft); coordinate-frame contract (`W` world, `C_i` cameras, `S` IMU, `B` body); state representation (`T_WS` pose + velocity + gyro/accel biases); two-callback API (`setOptimisedGraphCallback` for batch updates incl. loop closure + `setImuCallback` for high-rate prediction). Calibration prerequisites: camera intrinsics + camera-IMU extrinsics + IMU noise parameters + tight time sync (Kalibr toolchain explicitly recommended). Optional LibTorch sky-segmentation CNN can be disabled (`USE_NN=OFF`) to remove a major Jetson dependency. ROS 2 build path (`BUILD_ROS2=ON`) with `okvis_node_realsense.launch.xml`, `okvis_node_realsense_publisher.launch.xml`, `okvis_node_subscriber.launch.xml`, `okvis_node_synchronous.launch.xml`. **Health warning** in README: poor calibration → poor results; this is shared with all VI candidates but is more strongly emphasised in OKVIS2 docs. **Open**: README does not state explicit minimum frame rate (cf. VINS-Mono's documented 20 Hz minimum) — keyframe-based selection generally tolerates lower input frame rates than sliding-window optimisation; this needs explicit Jetson MVE validation at 3 fps.
|
||||
- **Related Sub-question**: SQ3+SQ4 / C1 — OKVIS2 per-mode API capability verification (Mandatory `context7` lookup per Per-Mode API Capability Verification rule, with WebFetch fallback to official README since `context7` returned no match)
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,88 @@
|
||||
# Source Registry — C4 — Pose estimation (PnP + RANSAC + LM) candidates
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> This file replaces a section of the previous monolithic `01_source_registry.md`. See `00_summary.md` for the full category index. Investigation order is tracked in `../00_question_decomposition.md` and the cross-category Investigation Status table in `00_summary.md`.
|
||||
|
||||
---
|
||||
|
||||
### Source #82
|
||||
- **Title**: OpenCV canonical implementation — `opencv/opencv` (Open Source Computer Vision Library) GitHub repository metadata via GitHub API + LICENSE — **Apache-2.0** (`license.spdx_id: "Apache-2.0"`); 87385 stars + 56554 forks + 2606 subscribers + 2732 open issues; created 2012-07-19; **last pushed 2026-05-08T07:00:03Z = TODAY at access time** (daily-active maintenance); default branch `4.x`; size 555 GB; topics include `c-plus-plus, computer-vision, deep-learning, image-processing, opencv`
|
||||
- **Link**: GitHub API metadata https://api.github.com/repos/opencv/opencv (accessed 2026-05-08; `license.spdx_id: "Apache-2.0"` confirmed); canonical repo https://github.com/opencv/opencv ; canonical website https://opencv.org ; LICENSE file https://raw.githubusercontent.com/opencv/opencv/4.x/LICENSE (Apache License 2.0 standard text)
|
||||
- **Tier**: L1 (project-official codebase by the OpenCV organization; canonical reference computer-vision library used by every modern computer-vision deployment as the de-facto industry-standard classical-CV foundation; cited by every C-row component's deployment guide; canonical solvePnPRansac is the industry-standard reference RANSAC-PnP implementation that every modern alternative [OpenGV, GTSAM-PnP, Theia, Ceres-only] compares against in its own documentation)
|
||||
- **Publication Date**: original 2000 (Intel) → open-source release 2006 (Willow Garage) → OpenCV.org foundation 2020 → canonical 4.x branch active continuous development; access date 2026-05-08; daily commits to `4.x` branch
|
||||
- **Timeliness Status**: ✅ Within Established-baseline-reference window (2000+ — established competitive ground for classical computer-vision + RANSAC-PnP reference; Established-competitive-mandatory-baseline exemption applies — `cv::solvePnPRansac` is the **canonical RANSAC-PnP reference baseline** that defines the mandatory-simple-baseline role for the C4 row per the engine Component Option Breadth rule, structurally analogous to NetVLAD's role in C2 row + SuperGlue+SuperPoint's role in C3 row)
|
||||
- **Version Info**: 4.14.0-pre at access time (default branch `4.x` = next-major-release rolling-development branch; current stable release 4.10.0 from late 2025 at access date — 4.x is the project's pinned major version per Source #83 documentation footer "Generated on Fri May 8 2026 04:21:44 for OpenCV by 1.12.0"); JetPack 6 ships canonical `libopencv_calib3d.so` for ARM Cortex-A78AE = the project's pinned Jetson Orin Nano Super deployment runtime
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + license-posture decision-maker (D-C1-1 — clean Apache-2.0) + C7 (Jetson runtime) implementer (canonical OpenCV is shipped with JetPack 6 distribution)
|
||||
- **Research Boundary Match**: **Full match** for the project's pinned C4 mandatory-simple-baseline mode (per-frame pose-from-correspondences via classical RANSAC-PnP with paired Levenberg-Marquardt refinement). The canonical `opencv/opencv` library ships everything needed for C4 deployment: `cv::solvePnPRansac` two function signatures (classical + USAC variant), nine `SolvePnPMethod` enum values, paired `cv::solvePnPRefineLM` LM refinement + alternate `cv::solvePnPRefineVVS` Gauss-Newton SO(3) refinement, paired `cv::solvePnPGeneric` for multi-solution + per-solution reprojection-error reporting, `cv::projectPoints` Jacobian for D-C4-2 post-hoc covariance recovery. **N/A for the project's domain caveat** — OpenCV solvePnPRansac is a classical algorithm with no training data; D-C2-1 retrain decision is irrelevant for OpenCV solvePnPRansac
|
||||
- **Summary**: OpenCV is the canonical industry-standard open-source computer vision library; the calib3d module ships `cv::solvePnPRansac` as the canonical RANSAC-PnP reference implementation. **CRITICAL LICENSE FINDING**: Apache-2.0 (`license.spdx_id: "Apache-2.0"`) — permissive, BSD/permissive license track on the C4 mandatory-simple-baseline; **deployment-ready under every D-C1-1 license-posture choice** with the cleanest license-compliance story tied with cvg/LightGlue + DISK + XFeat. **Daily-active maintenance**: last pushed 2026-05-08 (TODAY at access time) — among the most actively-maintained C-row references across all components evaluated. **Industry-standard reference status**: 87385 stars + 56554 forks + 2606 subscribers — the dominant industry-standard reference implementation that every modern C4 alternative (OpenGV, GTSAM-PnP, Theia, Ceres-only) compares against in its own documentation. **JetPack 6 canonical distribution**: canonical OpenCV is shipped with JetPack 6 distribution, providing zero-effort deployment for the project's pinned Jetson Orin Nano Super runtime
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — OpenCV solvePnPRansac per-mode API capability verification (Mandatory `context7` lookup MCP-validation-error + WebFetch fallback PASS per Per-Mode rule item 2; cross-validated against canonical GitHub API license metadata WebFetch + canonical OpenCV calib3d module documentation [Source #83]); **D-C1-1 license-posture compliance**: clean Apache-2.0 throughout; **Mandatory-simple-baseline role per engine Component Option Breadth rule** confirmed; **JetPack 6 canonical distribution** documented
|
||||
|
||||
|
||||
### Source #83
|
||||
- **Title**: OpenCV 4.x calib3d module canonical documentation — group `cv::calib3d` (Camera Calibration and 3D Reconstruction) at `https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html` + Perspective-n-Point (PnP) pose computation tutorial at `https://docs.opencv.org/4.x/d5/d1f/calib3d_solvePnP.html`; `cv::solvePnPRansac` two function signatures (classical with `iterationsCount=100, reprojectionError=8.0, confidence=0.99, flags=SOLVEPNP_ITERATIVE` defaults + USAC variant with `UsacParams` and `cameraMatrix` as `InputOutputArray` for focal-length refinement); Python bindings; `cv::SolvePnPMethod` enum 9 values; `cv::solvePnPRefineLM` + alternate `cv::solvePnPRefineVVS`; `cv::solvePnPGeneric` for multi-solution + per-solution reprojection-error reporting; USAC RANSAC-method enum 7 modern variants
|
||||
- **Link**: calib3d module documentation https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html (accessed 2026-05-08); PnP tutorial page https://docs.opencv.org/4.x/d5/d1f/calib3d_solvePnP.html (accessed 2026-05-08); both pages footer-stamped "Generated on Fri May 8 2026 04:21:44 for OpenCV by 1.12.0" — fresh canonical documentation at the project's evaluation time
|
||||
- **Tier**: L1 (canonical project-official documentation by the OpenCV organization; the canonical reference for the `cv::solvePnPRansac` function signature, parameter defaults, paired refinement variants, minimal-solver enum values, and structural caveats; auto-generated by Doxygen 1.12.0 from canonical opencv/opencv source code at `4.x` branch)
|
||||
- **Publication Date**: rolling Doxygen documentation auto-regenerated on every push to `4.x` branch; access date 2026-05-08 04:21:44 page-generation timestamp
|
||||
- **Timeliness Status**: ✅ Within Established-baseline-reference window (rolling Doxygen documentation; the canonical reference for `cv::solvePnPRansac` API surface at the project's evaluation time)
|
||||
- **Version Info**: 4.14.0-pre at access time (default branch `4.x` = next-major-release rolling-development branch). **Mode-enumeration query (1/3) — context7 MCP-validation-error + WebFetch fallback PASS** — `context7 resolve-library-id` returned MCP validation errors (parameter schema mismatch on both `query` and `libraryName` argument names — context7 server expects different argument shape than provided); per Per-Mode API Capability Verification rule item 2, fall-back to official-docs WebFetch on the canonical OpenCV calib3d module documentation + PnP tutorial page was used (this Source #83). **Nine `SolvePnPMethod` enum values documented** at line 243 of the calib3d.html: `SOLVEPNP_ITERATIVE=0` (default; iterative LM-based on top of EPNP minimal-solver result), `SOLVEPNP_EPNP=1` (Efficient Perspective-n-Point [Lepetit et al. IJCV 2009]; canonical default for ≥4 non-planar correspondences), `SOLVEPNP_P3P=2` (Revisiting the P3P Problem [Ding et al. 2023]; minimal-solver for exactly-3 correspondences with up to 4 solutions), `SOLVEPNP_DLS=3` (**BROKEN per explicit docstring "Broken implementation. Using this flag will fallback to EPnP"** — Direct Least-Squares method [Hesch & Roumeliotis 2011] originally), `SOLVEPNP_UPNP=4` (**BROKEN per explicit docstring "Broken implementation. Using this flag will fallback to EPnP"** — Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation [Penate-Sanchez et al. 2013] originally), `SOLVEPNP_AP3P=5` (Algebraic P3P [Ke & Roumeliotis CVPR 2017]), `SOLVEPNP_IPPE=6` (Infinitesimal Plane-Based Pose Estimation [Collins & Bartoli ECCV 2014]; **planar-only — object points must be coplanar — directly relevant to project's D-C4-1 = 4-DoF flat-earth lift recommendation**), `SOLVEPNP_IPPE_SQUARE=7` (special-case IPPE for marker pose with 4 fixed-pattern points), `SOLVEPNP_SQPNP=8` (SQPnP: A Consistently Fast and Globally Optimal Solution [Terzakis & Lourakis ECCV 2020]; **modern globally-optimal alternate without planarity restriction — second-recommended fallback if D-C4-1 chooses 6-DoF DSM lift**). **`cv::solvePnPRansac` classical signature** at line 3211 of calib3d.html: `bool solvePnPRansac(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int iterationsCount=100, float reprojectionError=8.0, double confidence=0.99, OutputArray inliers=noArray(), int flags=SOLVEPNP_ITERATIVE)` — Python `cv.solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs[, rvec[, tvec[, useExtrinsicGuess[, iterationsCount[, reprojectionError[, confidence[, inliers[, flags]]]]]]]]) -> retval, rvec, tvec, inliers`. **`cv::solvePnPRansac` USAC variant signature** at line 3261: `bool solvePnPRansac(InputArray objectPoints, InputArray imagePoints, InputOutputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, OutputArray inliers, const UsacParams& params=UsacParams())` — Python `cv.solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs[, rvec[, tvec[, inliers[, params]]]]) -> retval, cameraMatrix, rvec, tvec, inliers`; note `cameraMatrix` is `InputOutputArray` in the USAC variant, allowing focal-length refinement during the RANSAC loop. **`cv::solvePnPRefineLM`** at line 3268: canonical default `TermCriteria(EPS+COUNT, 20, FLT_EPSILON)`. **CRITICAL CAVEAT** documented at the PnP-tutorial page: "the current implementation computes the rotation update as a perturbation and not on SO(3)" — minor structural caveat; alternate `cv::solvePnPRefineVVS` at line 3289 uses Gauss-Newton with rotation update via exponential map on SO(3) (preferred for high-accuracy aerial pose-from-correspondences). **`cv::solvePnPGeneric`** at line 370: returns multiple candidate solutions sorted by reprojection error + an `OutputArray reprojectionError` per-solution. **Default minimal-sample-set method** at line 3256: "The default method used to estimate the camera pose for the Minimal Sample Sets step is `SOLVEPNP_EPNP`. Exceptions are: if you choose `SOLVEPNP_P3P` or `SOLVEPNP_AP3P`, these methods will be used; if the number of input points is equal to 4, `SOLVEPNP_P3P` is used." **USAC RANSAC-method enumeration** at the calib3d.html anonymous-enum block: canonical RANSAC, LMEDS, RHO, **USAC_DEFAULT, USAC_PARALLEL, USAC_FM_8PTS, USAC_FAST, USAC_ACCURATE, USAC_PROSAC, USAC_MAGSAC** — modern USAC variants (Barath et al. CVPR 2019 + ICCV 2019 MAGSAC++) provide higher inlier-recovery rate than vanilla RANSAC at the same iteration budget; **USAC_MAGSAC is the canonical sigma-consensus modern alternative to vanilla RANSAC** with no fixed inlier threshold
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + Plan-phase architect (mandatory-simple-baseline role documentation for engine Component Option Breadth rule compliance + D-C4-1 2D-3D-lift architectural decision carry-forward + D-C4-2 NEW covariance-recovery-strategy gate)
|
||||
- **Research Boundary Match**: **Full match** for the C4 row's pinned mode (per-frame pose-from-correspondences contract on Jetson Orin Nano Super; inputs = up to 1024 3D-2D correspondences from C3's 2D-2D + D-C4-1's 2D→3D lift + camera intrinsic + distortion; outputs = 6-DoF camera pose + per-correspondence inlier mask + reprojection error + RANSAC iter count + 6×6 covariance via D-C4-2). The canonical OpenCV calib3d module documentation provides the complete API surface for the project's pinned mode: two function signatures, nine minimal-solver enum values, paired LM + Gauss-Newton SO(3) refinement, paired multi-solution reporting with reprojection error, USAC RANSAC-method enumeration with 7 modern variants. **CRITICAL contract finding**: the documented signature requires `objectPoints` Nx3 1-channel + `imagePoints` Nx2 1-channel — **3D-2D, not 2D-2D**; the project must perform a 2D→3D lift on C3's satellite-tile-side 2D pixels via D-C4-1's 4-DoF flat-earth lift recommendation (project default) before calling solvePnPRansac. **CRITICAL covariance finding**: the documented signature returns `retval, rvec, tvec, inliers` only — **NO direct 6×6 covariance output**; AC-NEW-4 covariance-honesty contract requires D-C4-2 NEW Plan-phase decision for covariance-recovery-strategy
|
||||
- **Summary**: The canonical OpenCV 4.x calib3d module documentation is the definitive reference for `cv::solvePnPRansac` API surface, parameter defaults, paired refinement variants, minimal-solver enum values, and structural caveats. Two function signatures (classical + USAC variant), nine `SolvePnPMethod` enum values (4 valid for general project use + 2 special-case + 1 ITERATIVE default + 2 BROKEN-fallback-to-EPNP), paired `cv::solvePnPRefineLM` (LM with rotation update as perturbation, NOT on SO(3)) + alternate `cv::solvePnPRefineVVS` (Gauss-Newton on SO(3) via exponential map) refinement, paired `cv::solvePnPGeneric` for multi-solution + per-solution reprojection-error reporting, USAC RANSAC-method enumeration with 7 modern variants (USAC_DEFAULT, USAC_PARALLEL, USAC_FM_8PTS, USAC_FAST, USAC_ACCURATE, USAC_PROSAC, USAC_MAGSAC). **CRITICAL findings for the C4 row**: (i) **3D-2D INPUT CONTRACT, NOT 2D-2D** — solvePnPRansac requires Nx3 objectPoints + Nx2 imagePoints; project must perform 2D→3D lift via D-C4-1's locked-in 4-DoF flat-earth lift recommendation before invocation; (ii) **NO DIRECT 6×6 COVARIANCE OUTPUT** — AC-NEW-4 covariance-honesty contract requires D-C4-2 NEW Plan-phase decision for covariance-recovery-strategy; (iii) **TWO MINIMAL-SOLVER ENUM VALUES BROKEN** — SOLVEPNP_DLS + SOLVEPNP_UPNP fall back to EPNP per explicit docstring; valid set is `EPNP / AP3P / IPPE / SQPNP` plus 2 special-case (`P3P` for exactly-3; `IPPE_SQUARE` for 4-fixed-pattern markers) plus `ITERATIVE` default; (iv) **`cv::solvePnPRefineLM` ROTATION UPDATE NOT ON SO(3)** — minor caveat; alternate `cv::solvePnPRefineVVS` is the SO(3)-correct refiner. Canonical default minimal-sample-set method is `SOLVEPNP_EPNP`; recommended pairing for D-C4-1 = 4-DoF flat-earth lift is `SOLVEPNP_IPPE` (planar-scene minimal-solver designed for coplanar object points) with `SOLVEPNP_SQPNP` as the modern globally-optimal fallback
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — OpenCV solvePnPRansac per-mode API capability verification (cross-source verification of canonical API documentation + structural caveats + minimal-solver enum + paired refinement variants); **D-C4-2 NEW Plan-phase decision raised** for covariance-recovery-strategy; **D-C4-1 carry-forward REINFORCED** by the 3D-2D-input-contract finding (applies to all C4 candidates, not unique to OpenCV); cross-cite to Fact #20 + #21 closures from C2 row (canonical PnP+RANSAC+LM reference pipeline shape feeds AC-NEW-4 covariance-honesty contract)
|
||||
|
||||
|
||||
### Source #84
|
||||
- **Title**: OpenGV canonical implementation — `laurentkneip/opengv` (A library for solving calibrated central and non-central geometric vision problems) GitHub repository metadata via GitHub API + License.txt — **BSD-3-Clause-equivalent boilerplate** ("Author: Laurent Kneip, ANU. All rights reserved." with three numbered redistribution conditions including non-endorsement clause; **GitHub API license SPDX detector reports `license.spdx_id: "NOASSERTION"`** because the License.txt file does NOT use the canonical Open Source Initiative BSD-3-Clause boilerplate text — verified by direct WebFetch of `https://raw.githubusercontent.com/laurentkneip/opengv/master/License.txt`); 1109 stars + 358 forks + 66 subscribers + 58 open issues; created 2013-08-10; **last pushed 2023-06-07T18:14:14Z = ~2 years 11 months stale at access time 2026-05-08** (CRITICAL maintenance finding); default branch `master`; size 7790 KB; description "OpenGV is a collection of computer vision methods for solving geometric vision problems. It is hosted and maintained by the Mobile Perception Lab of ShanghaiTech."
|
||||
- **Link**: GitHub API metadata https://api.github.com/repos/laurentkneip/opengv (accessed 2026-05-08); canonical repo https://github.com/laurentkneip/opengv ; License.txt https://raw.githubusercontent.com/laurentkneip/opengv/master/License.txt (BSD-3-Clause-equivalent boilerplate verified via WebFetch); canonical Doxygen documentation portal https://laurentkneip.github.io/opengv/
|
||||
- **Tier**: L1 (project-official codebase by Laurent Kneip + ShanghaiTech Mobile Perception Lab; canonical reference for non-OpenCV PnP solvers including p3p_kneip [Kneip et al. CVPR 2011], p3p_gao [Gao et al. PAMI 2003], UPnP [Kneip et al. ECCV 2014], gpnp [Kneip 2014 generalized PnP], gp3p [generalized 3-point]; cited by every modern multi-camera + central-camera + relative-pose paper since 2014; field-standard for non-trivial PnP variants beyond OpenCV's `cv::solvePnPRansac` coverage)
|
||||
- **Publication Date**: original 2013-08-10 → continuous development 2013-2018 → maintenance gap 2018-2023 → last pushed 2023-06-07; access date 2026-05-08; **Doxygen documentation portal generation timestamp "Generated on Mon Jan 8 2018 21:43:04 for OpenGV by 1.8.11" — documentation page is 8.3 years old at access time**
|
||||
- **Timeliness Status**: ⚠️ Within Established-baseline-reference window (2013+ — established competitive ground for non-OpenCV PnP minimal solvers + generalized-camera support) but **with CRITICAL ~3-year maintenance staleness caveat** — Established-competitive-mandatory-baseline exemption applies (OpenGV is the canonical reference for non-trivial PnP variants beyond OpenCV) but Plan-phase decision-maker MUST account for: (i) no security patches since 2023; (ii) no Eigen 3.4+ compatibility patches; (iii) no JetPack 6 + ARM Cortex-A78AE compilation testing in upstream CI; (iv) ShanghaiTech Mobile Perception Lab's claim of active maintenance is contradicted by the GitHub commit history at access time
|
||||
- **Version Info**: master branch at git commit ea7c66f5e (last commit 2023-06-07T18:14:14Z); no version tags, no releases. **Mode-enumeration query (1/3) — context7 NOT INDEXED + WebFetch fallback PASS** — `context7 resolve-library-id` returned only OpenCV variants for the OpenGV query (top-5 results were `/websites/opencv_4_x` + `/websites/opencv_4_6_0` + `/opencv/opencv` + `/opencv/opencv-python` + `/websites/opencv_5_0_0-alpha` — all unrelated to OpenGV); per Per-Mode API Capability Verification rule item 2, fall-back to official-docs WebFetch on canonical Doxygen portal `laurentkneip.github.io/opengv/page_how_to_use.html` was used (this Source #85 below + License.txt verification on this Source #84). **Absolute pose minimal solvers documented** via Source #85 §"Central absolute pose": `absolute_pose::p2p` (with known rotation), `absolute_pose::p3p_kneip` [Kneip CVPR 2011], `absolute_pose::p3p_gao` [Gao PAMI 2003], `absolute_pose::upnp` [Kneip ECCV 2014]. **Absolute pose non-minimal solvers documented**: `absolute_pose::epnp` [Lepetit IJCV 2009 — same algorithm as OpenCV's SOLVEPNP_EPNP], `absolute_pose::upnp` (also valid for non-minimal). **Generalized/multi-camera absolute pose solvers documented** via Source #85 §"Non-central absolute pose": `absolute_pose::gp3p` (Kneip 3-point generalized), `absolute_pose::gpnp` [Kneip 2014]. **Non-linear LM optimizer documented**: `absolute_pose::optimize_nonlinear(adapter)` — handles both central + non-central cases; canonical refinement after RANSAC. **RANSAC documented**: `sac::Ransac` + `sac_problems::absolute_pose::AbsolutePoseSacProblem(adapter, algorithm)` with **algorithm parameter selectable from {KNEIP, GAO, EPNP, GP3P}** — richer minimal-solver selection than OpenCV's effectively-4-valid SolvePnPMethod enum (EPNP/AP3P/IPPE/SQPNP after 2 BROKEN entries removed). **CRITICAL input-contract finding**: OpenGV uses **bearing vectors (3D unit vectors)** as input, NOT 2D pixel coordinates — adapters (`AbsoluteAdapterBase`, `RelativeAdapterBase`, `PointCloudAdapterBase`) convert from user data format to OpenGV bearing-vector representation; project must implement adapter or use `CentralAbsoluteAdapter(bearingVectors, points)` constructor where bearingVectors are pre-computed unit vectors via inverse camera-intrinsic projection from C3's pixel correspondences. **CRITICAL threshold-structure finding**: RANSAC threshold is a **3D angle (radians)** between bearing vectors, NOT a 2D pixel reprojection error — Source #85 documents the conversion `ransac.threshold_ = 1.0 - cos(atan(sqrt(2.0)*0.5/800.0))` for a focal length of 800 px and 0.5*sqrt(2.0) pixel reprojection-error-equivalent
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + license-posture decision-maker (D-C1-1 — BSD-3-Clause-equivalent contingent on Plan-phase license-clearance verification due to NOASSERTION SPDX-detector status) + C7 (Jetson runtime) implementer (canonical OpenGV requires custom build on JetPack 6 ARM Cortex-A78AE — no canonical Jetson distribution; Plan-phase MVE prerequisite)
|
||||
- **Research Boundary Match**: **Partial match** for the project's pinned C4 mode (per-frame pose-from-correspondences via classical RANSAC-PnP with paired LM refinement) — algorithm coverage is RICHER than OpenCV at the minimal-solver axis (UPnP for both minimal+non-minimal, GP3P for generalized cameras, 2 P3P variants [Kneip + Gao] vs OpenCV's 1 P3P variant [Ke & Roumeliotis 2017 AP3P]) BUT the input contract (bearing vectors, not pixels) + threshold contract (3D angle, not pixels) + maintenance status (~3 years stale) require Plan-phase mitigation work. **N/A for the project's domain caveat** — OpenGV is a classical algorithm library with no training data; D-C2-1 retrain decision is irrelevant for OpenGV
|
||||
- **Summary**: OpenGV is the canonical reference for non-OpenCV PnP minimal solvers + generalized-camera support. **CRITICAL LICENSE FINDING**: License.txt content matches BSD-3-Clause boilerplate (three numbered redistribution conditions including non-endorsement clause) — eligible on every D-C1-1 license-posture choice CONTINGENT on Plan-phase license-clearance verification gate (because GitHub API SPDX detector reports `NOASSERTION`, indicating the License.txt file uses non-standard boilerplate that didn't match the OSI BSD-3-Clause template detection — recommend Plan-phase counsel-review of the License.txt text to confirm BSD-3-Clause-equivalent dual-use compatibility). **CRITICAL MAINTENANCE FINDING**: ~3 years stale at access time (last pushed 2023-06-07; Doxygen documentation portal generated 2018-01-08); ShanghaiTech Mobile Perception Lab's claimed maintenance is contradicted by commit history. **POSITIVE structural findings**: (i) richer minimal-solver coverage than OpenCV (UPnP minimal+non-minimal, GP3P generalized, 2 P3P variants); (ii) canonical reference for non-trivial PnP variants every modern paper compares against; (iii) generalized-camera support (multi-camera rig, non-central absolute pose) — not directly applicable to project's pinned 1× ADTi 20MP nav frame but architecturally cleaner if the project later adds a side-looking camera. **NEGATIVE structural findings**: (iv) bearing-vector input contract requires adapter or pre-computed unit-vector conversion from pixel correspondences (additional engineering vs OpenCV's direct pixel input); (v) 3D-angle RANSAC threshold requires conversion from project's pixel-reprojection-error budget; (vi) NO direct 6×6 covariance output from `optimize_nonlinear` (same finding as OpenCV — D-C4-2 covariance-recovery-strategy applies identically to OpenGV)
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — OpenGV per-mode API capability verification (Mandatory `context7` lookup NOT-INDEXED + WebFetch fallback PASS per Per-Mode rule item 2; cross-validated against canonical GitHub API metadata WebFetch + canonical License.txt WebFetch + canonical Doxygen documentation portal [Source #85]); **D-C1-1 license-posture compliance**: BSD-3-Clause-equivalent CONTINGENT on Plan-phase license-clearance verification gate (NOASSERTION SPDX-detector caveat); **D-C4-1 carry-forward REINFORCED** (bearing-vector input contract still requires 2D→3D lift on satellite-tile-side from pixel correspondences); **D-C4-2 NEW gate APPLIES IDENTICALLY** to OpenGV (`optimize_nonlinear` returns no covariance — same Plan-phase mitigation strategies as OpenCV); **D-C4-3 NEW gate raised by OpenGV closure** — license-clearance verification due to NOASSERTION SPDX status; **D-C4-4 NEW gate raised by OpenGV closure** — maintenance-staleness mitigation (Plan-phase decision: accept-as-is + freeze upstream / fork into project-controlled branch + apply Eigen-3.4+ + JetPack-6 patches in-house / migrate to Ceres-only as fallback if patches not feasible)
|
||||
|
||||
|
||||
### Source #85
|
||||
- **Title**: OpenGV canonical Doxygen documentation portal — `laurentkneip.github.io/opengv/page_how_to_use.html` (How to use OpenGV: vocabulary, library organization, adapter pattern interface, conventions, problem types and examples) + `namespaceopengv.html` (top-level namespace) + `namespaceopengv_1_1absolute__pose.html` (absolute-pose methods reference) + `namespaceopengv_1_1relative__pose.html` (relative-pose methods reference) + `namespaceopengv_1_1sac.html` + `namespaceopengv_1_1sac__problems_1_1absolute__pose.html`
|
||||
- **Link**: documentation portal entry https://laurentkneip.github.io/opengv/ (accessed 2026-05-08); how-to-use page https://laurentkneip.github.io/opengv/page_how_to_use.html (accessed 2026-05-08; **Doxygen-generated 2018-01-08 21:43:04 by Doxygen 1.8.11 = 8.3 years old at access time**)
|
||||
- **Tier**: L1 (canonical project-official Doxygen-generated documentation; the canonical reference for OpenGV's adapter pattern, function signatures, RANSAC integration, and threshold-structure conventions)
|
||||
- **Publication Date**: page-generation 2018-01-08; access date 2026-05-08
|
||||
- **Timeliness Status**: ⚠️ Established-baseline-reference window with **8.3-year-old documentation** — Plan-phase architect MUST cross-check actual `master` branch source (`opengv/include/opengv/absolute_pose/methods.hpp` + `opengv/include/opengv/sac/Ransac.hpp` + `opengv/include/opengv/sac_problems/absolute_pose/AbsolutePoseSacProblem.hpp`) for any signature drift between 2018 documentation and 2023-06-07 master branch HEAD. The documentation portal is structurally complete for the canonical 2013-2018 published API surface; subsequent commits (2018-2023) appear to be primarily fix commits + ShanghaiTech-era additions
|
||||
- **Version Info**: master branch at git commit ea7c66f5e (last commit 2023-06-07). **Pinned-mode runnable example query (2/3) — WebFetch PASS**: Source #85 §"Central absolute pose" provides the canonical OpenGV runnable example: `absolute_pose::CentralAbsoluteAdapter adapter(bearingVectors, points); std::shared_ptr<sac_problems::absolute_pose::AbsolutePoseSacProblem> absposeproblem_ptr(new sac_problems::absolute_pose::AbsolutePoseSacProblem(adapter, sac_problems::absolute_pose::AbsolutePoseSacProblem::KNEIP)); sac::Ransac<sac_problems::absolute_pose::AbsolutePoseSacProblem> ransac; ransac.sac_model_ = absposeproblem_ptr; ransac.threshold_ = 1.0 - cos(atan(sqrt(2.0)*0.5/800.0)); ransac.max_iterations_ = maxIterations; ransac.computeModel(); ransac.model_coefficients_;` followed by optional `absolute_pose::optimize_nonlinear(adapter)` LM refinement on the inlier set with `adapter.sett(initial_translation); adapter.setR(initial_rotation);`. **Disqualifier-probe query (3/3) — FOUR FINDINGS (1 negative-but-mitigable structural + 3 caveats)**: (i) **CRITICAL contract finding — OpenGV uses bearing vectors (3D unit vectors) as input, NOT 2D pixel coordinates** (Source #85 explicit "OpenGV assumes to be in the calibrated case, and landmark measurements are always given in form of bearing vectors in a camera frame"); the project must implement a `CentralAbsoluteAdapter` constructor or pre-compute unit-vector conversion from C3's pixel correspondences via inverse camera-intrinsic projection — additional engineering vs OpenCV's direct pixel input contract; this is an API-level structural difference, not a fundamental algorithmic limitation; (ii) **CRITICAL covariance finding — `optimize_nonlinear` does NOT directly emit a 6×6 pose covariance** (Source #85 documentation does not document a covariance output API; D-C4-2 covariance-recovery-strategy applies identically to OpenGV — Plan-phase mitigation strategies (a) post-hoc Jacobian-based via custom Jacobian propagation through `optimize_nonlinear` residuals OR (b) wrap OpenGV result in GTSAM `Marginals` posterior OR (c) heuristic scaling = AC-NEW-4 REJECT family); (iii) **CRITICAL threshold-structure finding — RANSAC threshold is a 3D angle (radians) between bearing vectors, NOT a 2D pixel reprojection error** (Source #85 §"Ransac threshold" canonical conversion `ransac.threshold_ = 1.0 - cos(atan(sqrt(2.0)*0.5/800.0))` for focal length 800 px and reprojection-error-equivalent 0.5*sqrt(2.0) pixels); project must convert from pixel-reprojection-error budget at runtime; (iv) **CRITICAL maintenance staleness — Doxygen portal generated 2018-01-08 + last commit 2023-06-07 = ~8.3 years documentation staleness + ~3 years code staleness** at access time 2026-05-08; D-C4-4 NEW Plan-phase mitigation strategy required; (v) **License-clearance contingency** — License.txt is BSD-3-Clause-equivalent but GitHub SPDX detector reports NOASSERTION; D-C4-3 NEW Plan-phase license-clearance verification gate required for dual-use deployment compliance
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + license-posture decision-maker (D-C1-1 + D-C4-3 NEW) + Plan-phase architect (richer-minimal-solver-coverage role documentation for engine Component Option Breadth rule compliance + bearing-vector adapter engineering work + 3D-angle threshold conversion engineering work + D-C4-4 NEW maintenance-staleness mitigation gate)
|
||||
- **Research Boundary Match**: Documents the OpenGV library's complete absolute-pose API surface (4 minimal solvers + 2 non-minimal solvers + 1 LM optimizer + 1 RANSAC integration + 4 algorithm-selectable RANSAC enum values) at the structural detail required for Plan-phase decision-making; runnable examples for both central + non-central + relative + multi-camera cases. **N/A for the project's domain caveat** — same as Source #84
|
||||
- **Summary**: Canonical Doxygen documentation portal for OpenGV's adapter-pattern interface and method signatures. Documents richer minimal-solver coverage than OpenCV (UPnP for both minimal+non-minimal, GP3P for generalized cameras, 2 P3P variants [Kneip + Gao] vs OpenCV's 1 [AP3P Ke & Roumeliotis 2017]). **CRITICAL contract differences vs OpenCV**: (i) bearing-vector input (3D unit vectors) instead of 2D pixels — adapter required; (ii) 3D-angle RANSAC threshold instead of pixel reprojection — conversion required; (iii) `optimize_nonlinear` LM refinement does not emit covariance — D-C4-2 still applies. **Documentation staleness**: page generated 2018-01-08 by Doxygen 1.8.11 (8.3 years old). **Maintenance staleness**: master branch last pushed 2023-06-07 (~3 years stale). **Recommended pinned mode**: `CentralAbsoluteAdapter` + `AbsolutePoseSacProblem::KNEIP` (Kneip's P3P inside RANSAC) + `optimize_nonlinear` LM refinement — Kneip's P3P is the canonical OpenGV-distinctive minimal solver and is the closest structural analog to OpenCV's `flags=SOLVEPNP_AP3P` (both are P3P variants but Kneip's is the original 2011 method while AP3P is Ke & Roumeliotis 2017 algebraic alternate); for project's planar-scene D-C4-1 = 4-DoF flat-earth lift case, OpenGV does NOT have a dedicated planar-scene minimal solver equivalent to OpenCV's `flags=SOLVEPNP_IPPE` — project would need to use Kneip's P3P or EPNP without the planar-scene specialization advantage. For project's 6-DoF DSM-lift case, OpenGV's UPnP is the modern globally-optimal alternate (analogous structural role to OpenCV's `flags=SOLVEPNP_SQPNP`)
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — OpenGV per-mode API capability verification (cross-source verification with Source #84 GitHub API + License.txt; runnable example documented; structural caveats documented including bearing-vector contract + 3D-angle threshold + LM-no-covariance findings); **D-C4-2 NEW gate APPLIES IDENTICALLY**; **D-C4-3 NEW gate raised** (license-clearance contingency); **D-C4-4 NEW gate raised** (maintenance-staleness mitigation)
|
||||
|
||||
|
||||
### Source #86
|
||||
- **Title**: GTSAM canonical implementation — `borglab/gtsam` (Georgia Tech Smoothing and Mapping library; C++ classes for smoothing and mapping in robotics and vision using factor graphs and Bayes networks) GitHub repository metadata via GitHub API + LICENSE + LICENSE.BSD — **BSD-3-Clause** (LICENSE.BSD file contains 3 numbered redistribution conditions including non-endorsement clause; **GitHub API license SPDX detector reports `license.spdx_id: "NOASSERTION"`** because the wrapper LICENSE file at the repo root references `LICENSE.BSD` indirectly + bundles third-party license declarations rather than directly containing OSI canonical BSD-3-Clause boilerplate text; verified BSD-3-Clause via direct WebFetch of `https://raw.githubusercontent.com/borglab/gtsam/develop/LICENSE.BSD`); 3424 stars + 927 forks + 60 subscribers + 140 open issues; created 2017-03-27; **last pushed 2026-05-08T13:00:22Z = TODAY at access time** (daily-active maintenance — fresher than OpenCV); default branch `develop`; size 109374 KB; topics include `estimation, perception, robotics, sensorfusion`; canonical website https://gtsam.org and Doxygen portal https://borglab.github.io/gtsam/. **Bundled third-party libraries** (per LICENSE wrapper file): CCOLAMD 2.9.6 (BSD-3, gtsam/3rdparty/CCOLAMD), Ceres auto-diff/jet code only (BSD-3, modified, gtsam/3rdparty), Eigen 3.3.7 (MPL2 file-level copyleft, gtsam/3rdparty/Eigen), METIS 5.1.0 (Apache-2.0, gtsam/3rdparty/metis), Spectra v0.9.0 (MPL2, externally referenced) — **all clean for project's dual-use deployment** (MPL2 is file-level copyleft only, doesn't propagate to project product code; Apache-2.0 + BSD-3 are permissive)
|
||||
- **Link**: GitHub API metadata https://api.github.com/repos/borglab/gtsam (accessed 2026-05-08); canonical repo https://github.com/borglab/gtsam ; LICENSE wrapper https://raw.githubusercontent.com/borglab/gtsam/develop/LICENSE (top-level documents bundled-library licensing); LICENSE.BSD https://raw.githubusercontent.com/borglab/gtsam/develop/LICENSE.BSD (BSD-3-Clause canonical boilerplate "Copyright (c) 2010, Georgia Tech Research Corporation, Atlanta, Georgia 30332-0415, All Rights Reserved" with three numbered redistribution conditions); canonical website https://gtsam.org ; Doxygen portal https://borglab.github.io/gtsam/
|
||||
- **Tier**: L1 (project-official codebase by Georgia Tech Research Corporation Borg Lab; canonical reference factor-graph SLAM library used by every modern multi-frame state-estimation deployment as the de-facto industry-standard factor-graph foundation; cited by every C-row component's deployment guide; canonical `LevenbergMarquardtOptimizer` + `Marginals` posterior is the **industry-standard reference for covariance-honest pose estimation**)
|
||||
- **Publication Date**: original GTSAM C++ library 2010 (Frank Dellaert + Borg Lab Georgia Tech) → open-source release 2010-12 → migration to GitHub 2017-03-27 → version 4.3a1 indexed in context7 at access time (next-major-release rolling-development branch `develop`); access date 2026-05-08; daily commits to `develop` branch
|
||||
- **Timeliness Status**: ✅ Within Established-baseline-reference window (2010+ — established competitive ground for factor-graph SLAM + covariance-honest pose estimation; Established-competitive-mandatory-baseline exemption applies — `LevenbergMarquardtOptimizer` + `Marginals` is the **canonical covariance-honest factor-graph reference** for the C4 row's modern-competitive-lead role and **directly addresses AC-NEW-4 covariance-honesty contract** without D-C4-2 mitigation work)
|
||||
- **Version Info**: 4.3a1 at access time (default branch `develop` = next-major-release rolling-development branch; current stable release 4.2 from 2024). **`LevenbergMarquardtOptimizer` + `Marginals` posterior covariance recovery API surface** — see Source #87 below for full documentation and runnable examples
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + license-posture decision-maker (D-C1-1 — BSD-3-Clause; bundled deps clean) + C5 (state estimator) implementer (GTSAM iSAM2 + factor-graph fusion is the canonical incremental-multi-frame-fusion pathway that scales naturally from C4 single-frame PnP to C5 multi-frame state estimation) + Plan-phase architect (D-C4-2 option (b) Plan-phase pathway candidate)
|
||||
- **Research Boundary Match**: **Full match** for the project's pinned C4 mode (per-frame pose-from-correspondences contract on Jetson Orin Nano Super) AT THE COVARIANCE-HONESTY AXIS — GTSAM is the **only C4 candidate evaluated to date that emits 6×6 pose covariance NATIVELY via `Marginals(graph, result).marginalCovariance(pose_key)`** without custom Jacobian engineering. **Architectural extension match**: GTSAM's factor-graph paradigm extends naturally from C4 single-frame PnP to C5 multi-frame state estimation via iSAM2 + `BetweenFactor<Pose3>` + `PriorFactorPose3` — would simplify C5 implementation if both C4 and C5 are GTSAM-based. **N/A for the project's domain caveat** — GTSAM is a classical factor-graph library with no training data; D-C2-1 retrain decision is irrelevant for GTSAM
|
||||
- **Summary**: GTSAM is the canonical industry-standard factor-graph SLAM library by Georgia Tech Borg Lab (Frank Dellaert et al.); the `gtsam::slam` module ships `GenericProjectionFactor<Pose3, Point3, CALIBRATION>` as the canonical per-correspondence projection factor for PnP-class problems. **CRITICAL POSITIVE LICENSE FINDING**: BSD-3-Clause via LICENSE.BSD (`Copyright (c) 2010, Georgia Tech Research Corporation`) — permissive, BSD/permissive license track on the C4 modern-competitive-lead axis; **deployment-ready under every D-C1-1 license-posture choice** with the cleanest license-compliance story tied with cvg/LightGlue + DISK + XFeat + OpenCV; bundled dependencies are clean (BSD-3/Apache-2.0/MPL2 file-level — all dual-use compatible). **Daily-active maintenance**: last pushed 2026-05-08 (TODAY at access time) — among the most actively-maintained C-row references; **fresher than OpenCV's last-pushed 2026-05-08T07:00:03Z by 6 hours at access time**. **CRITICAL POSITIVE COVARIANCE FINDING**: `Marginals(graph, result).marginalCovariance(pose_key)` emits a **direct 6×6 pose covariance** with no custom engineering — **the only C4 candidate evaluated to date that satisfies AC-NEW-4 covariance-honesty contract NATIVELY without D-C4-2 mitigation work**; this is the canonical Plan-phase pathway for D-C4-2 = (b) wrap-OpenCV-result-in-GTSAM-Marginals OR full-GTSAM-as-primary
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — GTSAM per-mode API capability verification (Mandatory `context7` lookup INDEXED at `/borglab/gtsam` with **1121 code snippets at version 4.3a1** — best context7 indexing of any C4 candidate evaluated; full per-mode API documentation accessible via `query-docs` tool); **D-C1-1 license-posture compliance**: BSD-3-Clause with clean bundled deps; **D-C4-2 NATIVELY SATISFIED** via `Marginals` posterior covariance recovery — GTSAM is the canonical Plan-phase pathway for D-C4-2 = (b) wrap-OpenCV-result-in-GTSAM-Marginals OR full-GTSAM-as-primary; **NO new D-C4-N gates raised** by GTSAM closure (D-C4-1 carry-forward applies identically, D-C4-2 natively satisfied)
|
||||
|
||||
|
||||
### Source #87
|
||||
- **Title**: GTSAM canonical Python documentation via context7-indexed library `/borglab/gtsam` at version 4.3a1 (1121 code snippets) — `python/gtsam/examples/CameraResectioning.ipynb` (canonical PnP example with `LevenbergMarquardtOptimizer`) + `gtsam/slam/doc/ProjectionFactor.ipynb` (`GenericProjectionFactorCal3_S2` API documentation) + `python/gtsam/examples/Pose2SLAMExample.ipynb` + `python/gtsam/examples/PlanarSLAMExample.ipynb` (`Marginals.marginalCovariance` posterior covariance recovery) + `gtsam/inference/doc/FactorGraph.ipynb` (`NonlinearFactorGraph` API documentation)
|
||||
- **Link**: context7 library ID `/borglab/gtsam` at version 4.3a1; canonical docs portal https://borglab.github.io/gtsam/ ; canonical Python examples directory https://github.com/borglab/gtsam/tree/develop/python/gtsam/examples (accessed 2026-05-08 via context7 query-docs MCP integration); CameraResectioning canonical example https://github.com/borglab/gtsam/blob/develop/python/gtsam/examples/CameraResectioning.ipynb ; ProjectionFactor canonical documentation https://github.com/borglab/gtsam/blob/develop/gtsam/slam/doc/ProjectionFactor.ipynb
|
||||
- **Tier**: L1 (canonical project-official documentation via context7-indexed library; the canonical reference for GTSAM's `GenericProjectionFactorCal3_S2`, `LevenbergMarquardtOptimizer`, `Marginals.marginalCovariance`, `NonlinearFactorGraph`, `Cal3_S2` calibration, `Pose3` 6-DoF pose, and `noiseModel.Diagonal.Sigmas` API surface)
|
||||
- **Publication Date**: rolling Jupyter notebook documentation auto-updated on every push to `develop` branch; access date 2026-05-08; canonical PnP example `CameraResectioning.ipynb` has been part of the GTSAM Python distribution since version 4.0 (~2019); access via context7 query at version 4.3a1
|
||||
- **Timeliness Status**: ✅ Within Established-baseline-reference window (rolling Jupyter notebook documentation; the canonical reference for GTSAM's PnP + covariance API surface at the project's evaluation time)
|
||||
- **Version Info**: 4.3a1 at access time (default branch `develop`). **Mode-enumeration query (1/3) — context7 INDEXED PASS**: `context7 resolve-library-id` returned `/borglab/gtsam` at version 4.3a1 with 1121 code snippets + High source reputation. **Pinned-mode runnable example query (2/3) — context7 query-docs PASS**: canonical PnP runnable Python example from `CameraResectioning.ipynb`: `calibration = Cal3_S2(1, 1, 0, 50, 50)` → `graph = NonlinearFactorGraph()` → per-correspondence factor add via `graph.add(resectioning_factor(measurement_noise, X(1), calibration, Point2(image_pixel), Point3(world_landmark)))` for each 2D-3D correspondence → `initial = Values(); initial.insert(X(1), Pose3(Rot3(...), Point3(...)))` → `result = LevenbergMarquardtOptimizer(graph, initial).optimize()`. **`GenericProjectionFactorCal3_S2` canonical API**: `GenericProjectionFactorCal3_S2(measured_pt2: Point2, pixel_noise: gtsam.noiseModel, pose_key: Symbol, landmark_key: Symbol, calibration: Cal3_S2, body_P_sensor: Pose3=identity)` — per-correspondence projection factor with optional sensor-body offset for IMU-camera extrinsic. **CRITICAL POSITIVE 6×6 covariance recovery API**: `marginals = gtsam.Marginals(graph, result); pose_covariance = marginals.marginalCovariance(pose_key)` — direct 6×6 posterior covariance with NO custom Jacobian engineering required; this is the **DIRECT AC-NEW-4 covariance-honesty contract satisfaction pathway** that no other C4 candidate evaluated to date provides natively. **Disqualifier-probe query (3/3) — TWO FINDINGS (1 negative-but-mitigable structural + 1 caveat)**: (i) **CRITICAL contract finding — GTSAM has NO native RANSAC algorithm** — canonical pattern is to run RANSAC externally (e.g., via OpenCV `cv::solvePnPRansac` for the inlier mask) THEN build the factor graph from inliers only with `GenericProjectionFactorCal3_S2`; alternative is in-graph robust outlier rejection via `gtsam.noiseModel.Robust.Create(gtsam.noiseModel.mEstimator.Huber.Create(1.0), gaussian_noise)` (Huber/Tukey/Cauchy M-estimator robust kernels) OR `GncOptimizer` (Graduated Non-Convexity, Yang et al. RAL 2020) for globally-convergent RANSAC alternative; this couples C4 = GTSAM-as-primary with C5 = OpenCV-RANSAC-as-inlier-detector OR full-GTSAM-with-robust-noise-model OR full-GTSAM-with-GncOptimizer; (ii) **Memory + binary-size CAVEAT — GTSAM library footprint is ~50-200 MB at runtime depending on factor-graph size and bundled-dependency build configuration** (vs OpenCV's ~10-50 MB calib3d module); on Jetson Orin Nano Super 8 GB shared memory budget, GTSAM is the **heaviest C4 candidate evaluated to date** but still well within AC-4.2 budget when co-resident with C1/C2/C3/C5/C6
|
||||
- **Target Audience**: System architects + C4 implementer + Step-7.5 reviewer + Plan-phase architect (modern-competitive-lead role documentation for engine Component Option Breadth rule compliance + D-C4-2 NATIVELY SATISFIED + D-C5-N forward-looking carry-forward for state estimator factor-graph extension)
|
||||
- **Research Boundary Match**: **Full match** for the C4 row's pinned mode AT THE COVARIANCE-HONESTY AXIS (GTSAM `Marginals.marginalCovariance` is the only C4 candidate evaluated to date that emits 6×6 pose covariance natively; canonical PnP runnable example provided via `CameraResectioning.ipynb`; complete API surface for `LevenbergMarquardtOptimizer` + `GenericProjectionFactorCal3_S2` + `Cal3_S2` + `Pose3` + `noiseModel.Diagonal.Sigmas` documented in canonical Python notebooks); **Architectural-extension match**: GTSAM's factor-graph paradigm extends naturally from C4 single-frame PnP to C5 multi-frame state estimation via iSAM2 + `BetweenFactor<Pose3>` — would simplify C5 implementation if both C4 and C5 are GTSAM-based
|
||||
- **Summary**: The canonical GTSAM Python documentation (via context7 at version 4.3a1 with 1121 code snippets) is the definitive reference for `GenericProjectionFactorCal3_S2`, `LevenbergMarquardtOptimizer`, `Marginals.marginalCovariance`, and `NonlinearFactorGraph` API surface. **CRITICAL POSITIVE FINDING for the C4 row**: `Marginals(graph, result).marginalCovariance(pose_key)` emits a **direct 6×6 pose covariance NATIVELY** with no custom Jacobian engineering — **the only C4 candidate evaluated to date that satisfies AC-NEW-4 covariance-honesty contract without D-C4-2 mitigation work**. **NO native RANSAC** — canonical pattern is external RANSAC (via OpenCV solvePnPRansac for inliers) then GTSAM factor-graph from inliers, OR in-graph robust noise model (`gtsam.noiseModel.Robust.Create` + Huber/Tukey/Cauchy), OR `GncOptimizer` (Yang et al. RAL 2020 Graduated Non-Convexity). **Heavier library footprint** than OpenCV (~50-200 MB at runtime) but still well within AC-4.2 8 GB shared memory budget. **Architectural extension to C5**: factor-graph paradigm scales naturally to multi-frame state estimation via iSAM2 + `BetweenFactor<Pose3>` + `PriorFactorPose3` — would simplify C5 implementation
|
||||
- **Related Sub-question**: SQ3+SQ4 / C4 — GTSAM per-mode API capability verification (cross-source verification of canonical Python examples + ProjectionFactor API + Marginals posterior + LevenbergMarquardtOptimizer + NonlinearFactorGraph); **D-C4-2 NATIVELY SATISFIED** via `Marginals.marginalCovariance` — GTSAM is the canonical Plan-phase pathway for D-C4-2 = (b); cross-cite to Fact #20 + #21 closures from C2 row (canonical PnP+RANSAC+LM reference pipeline shape feeds AC-NEW-4 covariance-honesty contract); forward-cite to C5 row (factor-graph paradigm extension to multi-frame state estimation via iSAM2)
|
||||
@@ -0,0 +1,95 @@
|
||||
# Source Registry — C5: State estimator / sensor fusion
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation). Sources for C5 (state estimator / sensor fusion) candidates.
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling categories: [SQ6](SQ6_external_positioning.md), [SQ1](SQ1_existing_systems.md), [SQ2](SQ2_canonical_pipeline.md), [C1](C1_vio.md), [C2](C2_vpr.md), [C3](C3_matchers.md), [C4](C4_pose_estimation.md). Backing fact cards: [`../02_fact_cards/C5_state_estimator.md`](../02_fact_cards/C5_state_estimator.md). Component fit matrix row: [`../06_component_fit_matrix/C5_state_estimator.md`](../06_component_fit_matrix/C5_state_estimator.md).
|
||||
|
||||
---
|
||||
|
||||
## Source #88 — Solà 2017 "Quaternion kinematics for the error-state Kalman filter" (canonical aerial/quaternion ESKF tutorial)
|
||||
|
||||
**Title**: "Quaternion kinematics for the error-state Kalman filter"
|
||||
**Author**: Joan Solà
|
||||
**Venue**: arXiv preprint cs.RO 1711.02508 (HAL hal-01122406; Semantic Scholar 12412090e46d1b21eecc59d1326edb8e47e9640e)
|
||||
**Submitted**: 2017-11-03 (revision v5 hosted on HAL); originally drafted earlier and continually revised since 2014
|
||||
**URL**: <https://arxiv.org/abs/1711.02508> (canonical) + <https://hal.science/hal-01122406v5> (HAL mirror)
|
||||
**Tier**: L1 (canonical authoritative tutorial; 592 citations per Semantic Scholar; the de-facto industry reference for ESKF + quaternion algebra in robotics + aerospace + UAV applications since 2017; open-access public-domain academic preprint)
|
||||
**Length**: 73 sections including 9 main parts (§1 quaternion definition + §2 rotations + §3 conventions + §4 perturbations/derivatives/integrals + §5 error-state kinematics for IMU-driven systems + §6 fusing IMU with complementary sensory data + §7 ESKF using global angular errors + §8 high-order integration variants + §9 references + §10 appendix)
|
||||
**Date Accessed**: 2026-05-08
|
||||
|
||||
**Why it matters for C5**:
|
||||
- §5.1 lists the THREE structural advantages of ESKF over standard EKF that drive its dominance for UAV applications: (i) minimal orientation error-state (no over-parametrization, no covariance singularity), (ii) error-state always near origin (linearization always valid), (iii) error-state always small (Jacobians fast and often constant).
|
||||
- §5.4 provides discrete-time error-state Jacobians directly usable for project's IMU integration.
|
||||
- §6 (sub-divided into §6.1 measurement update + §6.2 injection + §6.3 covariance reset) is the canonical recipe for fusing IMU with complementary sensors (project's case = C1 VIO + C4 satellite anchors + FC IMU).
|
||||
- §6 explicitly states (line 2013 of the paper text): "At the arrival of other kind of information than IMU, such as GPS or vision, we proceed to correct the ESKF. ... These vision + IMU setups are very interesting for use in **GPS-denied environments**, and can be implemented on mobile devices ... but also on **UAVs and other small, agile platforms**." — a direct project-relevant endorsement from the canonical tutorial.
|
||||
- §1675-1677 of the paper text frames the project's exact problem statement: "Integrating IMU readings leads to dead-reckoning positioning systems, which drift with time. Avoiding drift is a matter of fusing this information with absolute position readings such as GPS or vision."
|
||||
- §6.3 explicitly notes that the canonical reset Jacobian G can be approximated as `G = I_18` in most implementations, "but the expression here provided should produce more precise results, which might be of interest for reducing long-term error drift in odometry systems" — relevant for project's 8-hour fixed-wing flights where long-term drift is a binding concern.
|
||||
- §7 provides an alternate formulation using global angular errors (vs §5's local angular errors); both are valid; project must pick one and stick with it.
|
||||
|
||||
---
|
||||
|
||||
## Source #89 — Reference open-source ESKF implementations (canonical-paper-derived)
|
||||
|
||||
**Repositories examined**:
|
||||
|
||||
| # | Repo | Language | License | Sensors fused | Project relevance |
|
||||
|---|---|---|---|---|---|
|
||||
| 89.a | `ludvigls/ESKF` | Python | (LICENSE not declared in front-page README — Plan-phase verification gate **D-C5-1 NEW** required if adoption) | IMU + GNSS for fixed-wing UAVs | **DIRECTLY MATCHES project hardware family (fixed-wing UAV + IMU + GNSS-replacement)** — closest documentary template; tested on simulated + real datasets per author description |
|
||||
| 89.b | `cggos/imu_x_fusion` | C++/ROS | (Plan-phase verification gate **D-C5-1 NEW** required if adoption) | IMU + GNSS + 6DoF-Odom (loosely-coupled) — also IEKF, UKF (UKF/SPKF, JUKF, SVD-UKF), MAP variants | **MATCHES project pattern** — multi-source loosely-coupled fusion (IMU + GNSS-as-satellite_anchor + Odom-as-VIO) |
|
||||
| 89.c | `EliaTarasov/ESKF` | C++/ROS | (Plan-phase verification gate **D-C5-1 NEW** required if adoption) | GPS + Magnetometer + Vision Pose + Optical Flow + Range Finder fused with IMU (ROS Error-State Kalman Filter based on PX4/ecl) | **CLOSE MATCH but PX4-derived** — license-clear if PX4/ecl BSD-3-Clause, but verify that the derived code is BSD-3-Clause (PX4 is dual BSD/Apache, ecl is BSD-3-Clause) |
|
||||
| 89.d | `koledickarlo/ESKF-ESP32` | C++ | (LICENSE not declared in front-page README — Plan-phase verification gate **D-C5-1 NEW** required if adoption) | Accelerometer + Gyroscope + Optical Flow + Time-of-Flight (microcontroller-class, ESP32) | NOT MATCH — microcontroller-class targets (ESP32) not Jetson; useful only as small-state ESKF reference (Solà 2017 paper explicit citation) |
|
||||
| 89.e | `joansola/slamtb` | MATLAB | (LICENSE not declared in front-page README) | EKF-SLAM (full visual-inertial SLAM toolbox) | Author Joan Solà's own SLAM Toolbox in MATLAB — the most authoritative reference for the canonical paper but MATLAB-only, NOT deployable on JetPack 6 |
|
||||
|
||||
**Interpretation**: For Fact #88, project does NOT directly reuse any of the above repositories at the source-code level (license verification gates D-C5-1 NEW + cross-domain adaptation costs). Instead, the project implements ESKF following Solà 2017 §5+§6 equations directly in Python (NumPy/SciPy) or C++17 (Eigen3), using ludvigls/ESKF (89.a) as the closest documentary reference template for fixed-wing UAV ESKF structure. The reference implementations serve as evidence that Solà 2017 ESKF is implementable + deployable on UAV-class platforms with multi-sensor fusion patterns identical to the project's pinned configuration.
|
||||
|
||||
**URLs accessed (full canonical README pages)**:
|
||||
- <https://github.com/ludvigls/ESKF>
|
||||
- <https://github.com/cggos/imu_x_fusion>
|
||||
- <https://github.com/EliaTarasov/ESKF>
|
||||
- <https://github.com/koledickarlo/ESKF-ESP32>
|
||||
- <https://github.com/joansola/slamtb>
|
||||
|
||||
**Tier**: L1 (canonical project repositories; multiple independent reproductions of Solà 2017 paper across Python, C++/ROS, MATLAB, and microcontroller-class) + L2 (reference template only; project does NOT directly reuse).
|
||||
**Date Accessed**: 2026-05-08
|
||||
|
||||
---
|
||||
|
||||
## Source #90 — GTSAM `ImuFactor` / `CombinedImuFactor` / `PreintegratedImuMeasurements` / `PreintegratedCombinedMeasurements` (context7 query-docs at `/borglab/gtsam` — IMU pre-integration sub-API)
|
||||
|
||||
**Title**: GTSAM canonical `ImuFactor` and `CombinedImuFactor` API reference + canonical Python runnable examples
|
||||
**Source**: context7 query-docs at `/borglab/gtsam` version 4.3a1 with 1121 code snippets (cross-cite to Source #87 from C4 Fact #54 — same library, different sub-API surface; queried 2026-05-08 for IMU + state-estimation extension to C5)
|
||||
**Returned canonical Python notebooks**:
|
||||
- `gtsam/navigation/doc/ImuFactor.ipynb` — basic `ImuFactor(X(0), V(0), X(1), V(1), B(0), pim)` 5-key factor + canonical `PreintegrationParams.MakeSharedU(9.81)` setup + `PreintegratedImuMeasurements(params, bias_hat)` + `pim.integrateMeasurement(acc_meas, gyro_meas, dt)` + `pim.predict(initial_state, current_best_bias)` + `imu_factor.evaluateError(pose_i, vel_i, pose_j, vel_j, bias_i)`
|
||||
- `gtsam/navigation/doc/CombinedImuFactor.ipynb` — modern `CombinedImuFactor(X(0), V(0), X(1), V(1), B(0), B(1), pim)` 6-key factor with bias evolution per random walk via `PreintegrationCombinedParams.MakeSharedU(9.81)` + `params.setBiasAccCovariance(np.eye(3) * bias_acc_rw_sigma**2)` + `params.setBiasOmegaCovariance(np.eye(3) * bias_gyro_rw_sigma**2)` + `params.setBiasAccOmegaInit(initial_bias_cov)` + `PreintegratedCombinedMeasurements(params, bias_hat)`
|
||||
- `gtsam/navigation/doc/PreintegratedImuMeasurements.ipynb` — full PIM workflow: `pim.integrateMeasurement(acc, gyro, dt)` × N → `pim.deltaTij()` / `pim.deltaRij().matrix()` / `pim.deltaPij()` / `pim.deltaVij()` / `pim.biasHat()` / `pim.preintMeasCov()` 9×9 covariance + `pim.predict(initial_state, current_best_bias)` for IMU-only state extrapolation
|
||||
- `gtsam/navigation/doc/GPSFactor.ipynb` — `GPSFactor(pose_key, gps_measurement_enu, gps_noise_model)` for 3-DoF GPS prior + `GPSFactorArmCalib(pose_key, lever_arm_key, gps_measurement_enu, gps_noise_model)` for GPS with unknown lever-arm calibration
|
||||
|
||||
**Tier**: L1 (canonical context7-indexed library documentation at version 4.3a1; cross-validated against canonical Doxygen portal `borglab.github.io/gtsam/`).
|
||||
**URL**: context7 indexing of <https://github.com/borglab/gtsam/tree/develop/gtsam/navigation/doc/> (canonical Borg Lab navigation documentation; access via context7 server at queried-date 2026-05-08)
|
||||
**Cross-cite**: Source #86 (canonical `borglab/gtsam` GitHub repo + LICENSE.BSD direct WebFetch — BSD-3-Clause throughout per C4 Fact #54), Source #87 (canonical GTSAM Python examples via context7 query-docs at version 4.3a1 — `CameraResectioning.ipynb` + `Pose2SLAMExample.ipynb` + `PlanarSLAMExample.ipynb` per C4 Fact #54)
|
||||
|
||||
**Date Accessed**: 2026-05-08 (~13:00 UTC, immediately after C4 Fact #54 closure — same daily-active GTSAM master branch state)
|
||||
|
||||
---
|
||||
|
||||
## Source #91 — GTSAM `ISAM2` / `IncrementalFixedLagSmoother` / `Marginals` with iSAM2 results (context7 query-docs at `/borglab/gtsam` — incremental smoothing sub-API)
|
||||
|
||||
**Title**: GTSAM canonical `ISAM2` and `IncrementalFixedLagSmoother` incremental smoothing API + `Marginals` posterior recovery for iSAM2 results
|
||||
**Source**: context7 query-docs at `/borglab/gtsam` version 4.3a1 with 1121 code snippets (queried 2026-05-08 for incremental smoothing sub-API)
|
||||
**Returned canonical Python notebooks**:
|
||||
- `gtsam/inference/doc/ISAM.ipynb` — `GaussianISAM(initial_bayes_tree)` constructor + `isam.update(new_factors)` incremental graph modification + `isam.print()` introspection (legacy linear `GaussianISAM`; modern nonlinear `ISAM2` follows the same API pattern with additional `ISAM2Params(relinearizeThreshold, relinearizeSkip, factorization, evaluateNonlinearError, cacheLinearizedFactors, ...)` configuration)
|
||||
- `python/gtsam/examples/PlanarSLAMExample.ipynb` — `Marginals(graph, result).marginalCovariance(key)` 6×6 posterior covariance recovery (works with both batch `LevenbergMarquardtOptimizer` results and `ISAM2.calculateEstimate()` results)
|
||||
- `python/gtsam/examples/Pose2SLAMExample.ipynb` — same canonical `PriorFactorPose2(1, Pose2(0, 0, 0), PRIOR_NOISE)` initial-pose anchor pattern; reusable for Pose3 (`PriorFactorPose3(X(0), Pose3(...), prior_noise)`) for project's 3D state estimation
|
||||
- `gtsam/slam/doc/lago.ipynb` — `lago.initialize(graph)` linear-and-iterative-pose-graph initialization (good for cold-start pose initialization from FC GPS-extrapolated pose at boot per AC-NEW-1)
|
||||
- `gtsam/slam/doc/InitializePose3.ipynb` — `InitializePose3.initialize(graph)` chordal-relaxation 3D initialization (modern alternative for Pose3 cold-start)
|
||||
- `gtsam/inference/doc/FactorGraph.ipynb` — `NonlinearFactorGraph()` + `BetweenFactorPose2(X(0), X(1), Pose2(1, 0, 0), odometry_noise)` + `PriorFactorPose2(X(0), Pose2(0, 0, 0), prior_noise)` core factor-graph patterns (project applies Pose3 variants: `BetweenFactorPose3` + `PriorFactorPose3` + `GenericProjectionFactorCal3DS2`)
|
||||
|
||||
**Note on `IncrementalFixedLagSmoother`**: context7 query-docs at /borglab/gtsam returned ISAM (legacy GaussianISAM) examples but did NOT return a top-3 `IncrementalFixedLagSmoother` snippet on the queried search. The IncrementalFixedLagSmoother class is documented in the canonical GTSAM source tree at `gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h` (not in the `develop` branch's stable area; in the `gtsam_unstable` namespace, requiring user to opt-in to unstable APIs). Project must verify at Plan-phase Jetson MVE that IncrementalFixedLagSmoother is the correct sliding-window primitive vs writing custom marginalization on top of `ISAM2.marginalizeLeaves(keys_to_marginalize)`.
|
||||
|
||||
**Tier**: L1 (canonical context7-indexed library documentation at version 4.3a1) + L2 (IncrementalFixedLagSmoother — gtsam_unstable namespace, verification at Plan phase required).
|
||||
**URL**: context7 indexing of <https://github.com/borglab/gtsam/tree/develop/gtsam/inference/doc/> + <https://github.com/borglab/gtsam/tree/develop/python/gtsam/examples/> (canonical Borg Lab inference + examples documentation; access via context7 server at queried-date 2026-05-08)
|
||||
**Cross-cite**: Source #86 + Source #87 + Source #90 (all GTSAM library; same daily-active master branch state)
|
||||
|
||||
**Date Accessed**: 2026-05-08
|
||||
|
||||
---
|
||||
@@ -0,0 +1,142 @@
|
||||
# Source Registry — C6: Tile cache + spatial index
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation). Sources backing the C6 component candidates ([`../06_component_fit_matrix/C6_tile_cache_spatial_index.md`](../06_component_fit_matrix/C6_tile_cache_spatial_index.md)) and C6 fact cards ([`../02_fact_cards/C6_tile_cache_spatial_index.md`](../02_fact_cards/C6_tile_cache_spatial_index.md)).
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling component sources: [C1 VIO](C1_vio.md), [C2 VPR](C2_vpr.md), [C3 Matchers](C3_matchers.md), [C4 Pose](C4_pose_estimation.md), [C5 State estimator](C5_state_estimator.md). Sub-question sources: [SQ6 external positioning](SQ6_external_positioning.md), [SQ1 existing systems](SQ1_existing_systems.md), [SQ2 canonical pipeline](SQ2_canonical_pipeline.md).
|
||||
|
||||
---
|
||||
|
||||
## Scope summary
|
||||
|
||||
C6 candidates evaluated documentary level: **Cand 1 (mandatory simple-baseline)** mirrors the parent-suite `satellite-provider` pattern (PostgreSQL + pure btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` + filesystem tile storage at `./tiles/{zoom}/{x}/{y}.jpg`); **Cand 2 (modern-competitive-lead-spatial-extension)** = PostGIS GiST on `geography(POINT,4326)` for geographic side + pgvector HNSW for descriptor ANN side + same filesystem tile storage. Both candidates share the same Postgres-as-runtime-DB substrate per user-pinned scope (Postgres on Jetson at runtime, c6_postgres_locus = A). The user explicitly stated the satellite-provider pattern is NOT carved in stone — Cand 2 may cascade changes back to the satellite-provider IF research reveals a MATERIAL improvement (small improvements stay with Cand 1).
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
### Source #92 — Parent-suite `satellite-provider` existing pattern (verified directly via filesystem read at /Users/obezdienie001/dev/azaion/suite/satellite-provider/)
|
||||
|
||||
**Title**: `azaion/suite/satellite-provider` .NET 8.0 microservice (PostgreSQL + Dapper + filesystem tile storage)
|
||||
**Tier**: L1 — primary code in the same multi-repo project workspace
|
||||
**URL**: file:///Users/obezdienie001/dev/azaion/suite/satellite-provider/
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**:
|
||||
- README at `satellite-provider/README.md` — confirms PostgreSQL backend, .NET 8.0 microservice, Dapper-based DataAccess layer, filesystem tile storage at `./tiles/{zoomLevel}/{x}/{y}.jpg`, NO PostGIS extension declared.
|
||||
- Migration `001_CreateTilesTable.sql` — `tiles` table with `(id UUID PK, zoom_level INT, latitude DOUBLE PRECISION, longitude DOUBLE PRECISION, tile_size_meters DOUBLE PRECISION, tile_size_pixels INT, image_type VARCHAR(10), maps_version VARCHAR(50), file_path VARCHAR(500), created_at, updated_at)`.
|
||||
- Migration `003_CreateIndexes.sql` — `CREATE INDEX idx_tiles_composite ON tiles(latitude, longitude, tile_size_meters)` + `CREATE INDEX idx_tiles_zoom ON tiles(zoom_level)` + `CREATE INDEX idx_regions_status ON regions(status)`. **Pure btree composite indexes; NO GiST, NO PostGIS, NO spatial extension.**
|
||||
- Migration `011_AddTileCoordinates.sql` — RENAME `zoom_level` → `tile_zoom`; ADD `tile_x INT NOT NULL` + `tile_y INT NOT NULL` derived via slippy-map Web Mercator math (`tile_x = FLOOR((longitude + 180.0) / 360.0 * POWER(2, tile_zoom))::INT` + `tile_y = FLOOR((1.0 - LN(TAN(RADIANS(latitude)) + 1.0 / COS(RADIANS(latitude))) / PI()) / 2.0 * POWER(2, tile_zoom))::INT`); CREATE UNIQUE INDEX `idx_tiles_unique_location ON tiles(latitude, longitude, tile_zoom, tile_size_meters, version)` + `CREATE INDEX idx_tiles_coordinates ON tiles(tile_zoom, tile_x, tile_y, version)`. **Confirms: existing pattern uses btree on slippy-map (zoom, x, y) integer-coordinate columns for spatial-grid range queries.**
|
||||
|
||||
**Key facts extracted**:
|
||||
- DB engine: PostgreSQL (vanilla, no extensions).
|
||||
- Spatial index strategy: pure btree composite on slippy-map integer coordinates `(tile_zoom, tile_x, tile_y, version)` for spatial-grid range queries; secondary btree on lat/lon for inverse-geocode lookups.
|
||||
- Tile bytes: filesystem at canonical slippy-map path `./tiles/{zoom}/{x}/{y}.jpg`.
|
||||
- DB ↔ filesystem coupling: `file_path VARCHAR(500)` pointer in DB.
|
||||
- Migration mechanism: numbered SQL files as `EmbeddedResource`, run automatically on startup via `DatabaseMigrator.cs`.
|
||||
- App layer: .NET 8.0 + Dapper + raw SQL repos.
|
||||
|
||||
**Implication**: For the on-Jetson C6 (which is Python/C++, not .NET), the equivalent stack is `psycopg[binary]` or `asyncpg` Python driver + raw SQL queries against the same schema pattern.
|
||||
|
||||
---
|
||||
|
||||
### Source #93 — PostgreSQL official documentation: btree multi-column index ordering and range query optimization
|
||||
|
||||
**Title**: PostgreSQL 16 documentation — "Multicolumn Indexes" + "Indexes and ORDER BY" + "EXPLAIN" + "btree access method"
|
||||
**Tier**: L1 — official authoritative docs
|
||||
**URL**: <https://www.postgresql.org/docs/current/indexes-multicolumn.html> + <https://www.postgresql.org/docs/current/btree.html>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending WebFetch
|
||||
**Key facts to extract**:
|
||||
- Btree multicolumn index supports range queries on the leading prefix (i.e., `WHERE tile_zoom = ? AND tile_x BETWEEN ? AND ?` uses the index optimally).
|
||||
- Btree composite index access time: O(log N) where N = total rows.
|
||||
- Storage overhead: typically ~50-100 bytes per index entry depending on column types.
|
||||
|
||||
**Use**: backs Fact #92 sub-matrix entries on AC-4.1 (latency) and AC-4.2 (memory) for Cand 1.
|
||||
|
||||
---
|
||||
|
||||
### Source #94 — PostGIS official documentation: GiST spatial index on geography type + KNN distance ordering
|
||||
|
||||
**Title**: PostGIS 3.4 documentation — "GiST Indexes" + "geography Type" + "PostGIS Special Functions Index" + "ST_DWithin" + "<-> KNN operator"
|
||||
**Tier**: L1 — official authoritative docs (OGC SFS-compliant canonical extension)
|
||||
**URL**: <https://postgis.net/docs/using_postgis_dbmanagement.html#idx-spgist> + <https://postgis.net/docs/geography.html> + <https://postgis.net/workshops/postgis-intro/knn.html>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending WebFetch
|
||||
**Key facts to extract**:
|
||||
- GiST index access time on `geography(POINT,4326)`: O(log N) for bounding-box pre-filter; full geographic distance check is exact (not approximate).
|
||||
- KNN ordering via `ORDER BY position <-> ST_MakePoint(?, ?)::geography LIMIT K` is index-optimized in PostGIS 2.0+.
|
||||
- `ST_DWithin(position::geography, ST_MakePoint(?, ?)::geography, radius_m)` supports radius queries with native great-circle distance.
|
||||
- PostGIS extension installed footprint: typically ~30-50 MB shared libraries + ~10-20 MB SRID/projection metadata catalog.
|
||||
|
||||
**Use**: backs Fact #93 sub-matrix entries on AC-4.1 (latency) and AC-4.2 (memory) for Cand 2 + comparative-improvement-vs-Cand-1 analysis.
|
||||
|
||||
---
|
||||
|
||||
### Source #95 — pgvector official documentation: HNSW index for vector similarity search
|
||||
|
||||
**Title**: pgvector — "Open-source vector similarity search for Postgres" (`pgvector/pgvector`)
|
||||
**Tier**: L1 — canonical implementation by Andrew Kane
|
||||
**URL**: <https://github.com/pgvector/pgvector> + context7 indexed via `/pgvector/pgvector`
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending context7 + WebFetch
|
||||
**Key facts to extract**:
|
||||
- HNSW index API: `CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)` + `CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops)` + `CREATE INDEX ON items USING hnsw (embedding vector_ip_ops)`.
|
||||
- Default tunable parameters: `m=16` (max connections per layer) + `ef_construction=64` (build-time candidate list size); query-time `ef_search` (default 40).
|
||||
- Vector dimension limits: pgvector 0.7+ supports up to 16,000 dimensions for HNSW; 2,000 dimensions for IVFFlat.
|
||||
- Memory footprint: extension itself ~5-10 MB shared library; per-vector storage = 4 bytes × dimensions (so 2048-D = 8 KB/vec, 1024-D = 4 KB/vec, 512-D = 2 KB/vec, 256-D = 1 KB/vec).
|
||||
|
||||
**Use**: backs Fact #93 sub-matrix on descriptor ANN side for Cand 2 + comparative cache footprint analysis.
|
||||
|
||||
---
|
||||
|
||||
### Source #96 — FAISS official documentation: in-memory ANN library + Python bindings
|
||||
|
||||
**Title**: FAISS — "A library for efficient similarity search and clustering of dense vectors" (`facebookresearch/faiss`)
|
||||
**Tier**: L1 — canonical implementation by Meta AI Research
|
||||
**URL**: <https://github.com/facebookresearch/faiss> + <https://faiss.ai/>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending WebFetch + context7
|
||||
**Key facts to extract**:
|
||||
- Index types relevant to C6 descriptor ANN: `IndexFlatL2` (brute-force, exact), `IndexHNSWFlat` (HNSW graph, approximate), `IndexIVFFlat` (Inverted File, approximate w/ training).
|
||||
- Memory: in-memory only at query time; loaded from disk via `faiss.read_index(path)` at startup.
|
||||
- License: MIT.
|
||||
- Python API: `faiss.IndexFlatL2(d)` / `faiss.IndexHNSWFlat(d, m)` / `index.add(xb)` / `D, I = index.search(xq, k)`.
|
||||
|
||||
**Use**: backs Fact #92 sub-matrix on descriptor ANN side for Cand 1 (app-side FAISS in-memory loaded at takeoff from Postgres bytea blobs).
|
||||
|
||||
---
|
||||
|
||||
### Source #97 — Postgres on NVIDIA Jetson Orin Nano memory footprint and JetPack 6 deployment
|
||||
|
||||
**Title**: PostgreSQL on ARM64 / Ubuntu 22.04 (JetPack 6 base) — official packaging + Docker images
|
||||
**Tier**: L1 — official Postgres ARM64 packages + Docker `postgres:16-alpine` image documentation
|
||||
**URL**: <https://hub.docker.com/_/postgres> + <https://www.postgresql.org/download/linux/ubuntu/>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending WebFetch
|
||||
**Key facts to extract**:
|
||||
- ARM64 packages available for Postgres 16 on Ubuntu 22.04 (JetPack 6 base).
|
||||
- Default `shared_buffers=128MB` + `work_mem=4MB` resident footprint ~80-150 MB on idle; ~200-400 MB under modest load.
|
||||
- Docker `postgres:16-alpine` image size: ~250 MB compressed.
|
||||
- PostGIS Docker image `postgis/postgis:16-3.4-alpine` adds ~50-80 MB to base postgres image.
|
||||
|
||||
**Use**: backs both Fact #92 + Fact #93 sub-matrix entries on AC-4.2 (8 GB shared memory budget) for the Postgres-on-Jetson deployment.
|
||||
|
||||
---
|
||||
|
||||
### Source #98 — Slippy Map Tilenames specification (OpenStreetMap canonical reference)
|
||||
|
||||
**Title**: Slippy Map Tilenames — XYZ tile coordinate system + Web Mercator projection
|
||||
**Tier**: L1 — canonical convention documented by OpenStreetMap Foundation
|
||||
**URL**: <https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: pending WebFetch
|
||||
**Key facts to extract**:
|
||||
- Tile X/Y math: `xtile = floor((lon + 180) / 360 * 2^zoom)` + `ytile = floor((1 - asinh(tan(lat * π/180)) / π) / 2 * 2^zoom)` — matches satellite-provider migration 011 exactly.
|
||||
- Tile coverage: at zoom Z, world divided into 2^Z × 2^Z tiles; each tile covers `360/2^Z` longitude × variable-latitude.
|
||||
- Project zoom: ZoomLevel 18 (per satellite-provider README default) covers ~38m × 38m at equator (cited as "tileSizeMeters: 38.2" in README sample response).
|
||||
- Cache budget per AC-8.3 (10 GB): at typical JPEG ~30 KB/tile, fits ~330,000 tiles = roughly an area of 50 km × 50 km × 9 zoom levels OR a single mission corridor at zoom 18 of ~1000 km × 12 m.
|
||||
|
||||
**Use**: backs both Fact #92 + Fact #93 sub-matrix entries on AC-8.3 (10 GB cache budget) + AC-3.x (mission corridor coverage).
|
||||
|
||||
---
|
||||
|
||||
(Subsequent sources #99+ added during fact extraction below as candidate-specific evidence is gathered.)
|
||||
@@ -0,0 +1,190 @@
|
||||
# Source Registry — C7: On-Jetson inference runtime
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation). Sources backing the C7 cross-cutting integration row ([`../06_component_fit_matrix/C7_inference_runtime.md`](../06_component_fit_matrix/C7_inference_runtime.md)) and C7 fact cards ([`../02_fact_cards/C7_inference_runtime.md`](../02_fact_cards/C7_inference_runtime.md)).
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling component sources: [C1 VIO](C1_vio.md), [C2 VPR](C2_vpr.md), [C3 Matchers](C3_matchers.md), [C4 Pose](C4_pose_estimation.md), [C5 State estimator](C5_state_estimator.md), [C6 Tile cache](C6_tile_cache_spatial_index.md). Sub-question sources: [SQ6 external positioning](SQ6_external_positioning.md), [SQ1 existing systems](SQ1_existing_systems.md), [SQ2 canonical pipeline](SQ2_canonical_pipeline.md).
|
||||
|
||||
---
|
||||
|
||||
## Scope summary
|
||||
|
||||
C7 is a **cross-cutting integration row** rather than a per-component candidate row: it pins how the C1 VIO learned-frontend (if any), C2 VPR backbone, and C3 matcher actually run on the Jetson Orin Nano Super under JetPack 6 — TensorRT vs ONNX Runtime+TRT EP vs pure PyTorch FP16. Per the user-pinned scope (locked via `/autodev` AskQuestion 2026-05-08 — see `_docs/_autodev_state.md` `c7_breadth=B`, `c7_quantization=A`, `c7_overkill_options=A`), three documentary candidate rows are evaluated: **TensorRT native primary** + **ONNX Runtime + TensorRT EP interop alternate** + **pure PyTorch FP16 mandatory simple-baseline**. INT8 primary + FP16 fallback per candidate; INT8-only candidates Experimental until calibration data exists. Triton / DeepStream / CUDA-Python custom kernels noted-and-rejected in one sentence (server/video-pipeline class or out-of-budget for embedded 8 h mission). Cand-row candidates inherit and propagate Plan-phase gates already opened by C2 (D-C2-5 DINOv2 ViT-export to TensorRT FP16/INT8) and C3 (D-C3-2 LightGlue inference runtime path).
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
### Source #99 — NVIDIA TensorRT 10.x official documentation portal (context7-indexed)
|
||||
|
||||
**Title**: NVIDIA TensorRT — SDK for optimizing and accelerating deep learning inference on NVIDIA GPUs (mixed precision, dynamic shapes, transformer optimizations)
|
||||
**Tier**: L1 — official authoritative SDK documentation (NVIDIA primary)
|
||||
**URL**: <https://docs.nvidia.com/deeplearning/tensorrt/latest/> + context7 indexed at `/websites/nvidia_deeplearning_tensorrt`
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ context7 query "INT8 calibration EntropyCalibrator2 ICudaEngine deserialize Jetson Orin Nano FP16 mixed precision deployment workflow Python builder" returned 9371 code snippets at Source Reputation High + Benchmark Score 75.25.
|
||||
|
||||
**Key APIs verified**:
|
||||
- **INT8 calibrator hierarchy**: `nvinfer1::IInt8Calibrator` (abstract base) + `nvinfer1::IInt8EntropyCalibrator` (deprecated) + `nvinfer1::IInt8EntropyCalibrator2` (current canonical) + `nvinfer1::IInt8MinMaxCalibrator`. Each defines `getBatchSize()` + `getBatch(void* bindings[], const char* names[], int32_t nbBindings)` + `readCalibrationCache(size_t& length)` + `writeCalibrationCache(const void* ptr, size_t length)` + `getAlgorithm()` returning `kENTROPY_CALIBRATION_2` for the canonical path.
|
||||
- **Python builder INT8 enable pattern** (canonical TensorRT 10.x):
|
||||
```python
|
||||
config.set_flag(trt.BuilderFlag.INT8)
|
||||
config.int8_calibrator = Int8_calibrator
|
||||
Int8_calibrator = EntropyCalibrator(["input_node_name"], batchstream)
|
||||
```
|
||||
- **Mixed-precision flag pattern**: `config.set_flag(trt.BuilderFlag.FP16)` + `config.set_flag(trt.BuilderFlag.INT8)` for combined FP16+INT8 mixed precision (TensorRT auto-selects per-layer precision based on calibration data).
|
||||
|
||||
**Use**: backs Fact #94 (TensorRT native primary candidate) per-mode API verification block + Plan-phase D-C7-1 calibration-dataset-strategy + D-C7-2 mixed-precision flag matrix.
|
||||
|
||||
---
|
||||
|
||||
### Source #100 — Microsoft ONNX Runtime official documentation (context7-indexed) + Jetson AI Lab community wheel index
|
||||
|
||||
**Title**: Microsoft ONNX Runtime — cross-platform ML inference and training accelerator with TensorRT execution provider; Jetson-specific install path via Jetson AI Lab community PyPI index
|
||||
**Tier**: L1 — official authoritative SDK documentation (Microsoft primary) + L2 community-maintained Jetson wheel index
|
||||
**URL**: <https://onnxruntime.ai/> + context7 indexed at `/microsoft/onnxruntime` (v1.25.0) + <https://pypi.jetson-ai-lab.io/jp6/cu126/> + <https://github.com/dusty-nv/jetson-containers/issues/1283> + <https://github.com/microsoft/onnxruntime/issues/20503> + <https://github.com/microsoft/onnxruntime/issues/27562>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ context7 query "TensorRT execution provider TrtFp16Enable TrtInt8Enable TrtCachePath onnxruntime-gpu Jetson ARM64 inference session options" returned 1462 code snippets at Source Reputation High + Benchmark Score 82.23 (highest of the 3 C7 candidate context7 lookups).
|
||||
|
||||
**Key APIs verified**:
|
||||
- **Provider enumeration + config pattern** (canonical Python API):
|
||||
```python
|
||||
import onnxruntime as ort
|
||||
print(ort.get_available_providers())
|
||||
tensorrt_options = {'device_id': 0, 'trt_max_workspace_size': 2147483648, 'trt_fp16_enable': True}
|
||||
cuda_options = {'device_id': 0, 'arena_extend_strategy': 'kNextPowerOfTwo', 'gpu_mem_limit': 2 * 1024 * 1024 * 1024}
|
||||
session_trt = ort.InferenceSession(
|
||||
"model.onnx",
|
||||
providers=[('TensorrtExecutionProvider', tensorrt_options), ('CUDAExecutionProvider', cuda_options), 'CPUExecutionProvider']
|
||||
)
|
||||
```
|
||||
- **Provider-cascade behavior**: ORT TRT EP attempts to optimize each subgraph via TensorRT; falls back to CUDA EP for unsupported ops; falls back to CPU EP if neither GPU EP applies. Subgraph fallback is automatic and per-op transparent.
|
||||
|
||||
**Jetson install constraints (CRITICAL)**:
|
||||
- **Standard `pip install onnxruntime-gpu` does NOT work on Jetson Tegra** — Microsoft does not publish prebuilt aarch64 wheels with CUDA/TensorRT EPs (per Issue #20503: "NVIDIA does not have CI infrastructure to publish them").
|
||||
- **Canonical install path (JetPack 6 + CUDA 12.6 + Ubuntu 22.04)**: `pip3 install onnxruntime-gpu --index-url https://pypi.jetson-ai-lab.io/jp6/cu126`.
|
||||
- **Alternate index (CUDA 12.9 + Ubuntu 24.04)**: `pip3 install onnxruntime-gpu --index-url https://pypi.jetson-ai-lab.io/jp6/cu129`.
|
||||
- **Known incompatibility**: onnxruntime-gpu v1.23.0 wheels for JetPack 6 were built against `numpy<2.0.0`; importing under `numpy>=2.0.0` raises a compatibility error per Issue #27562. Pin numpy<2 in project requirements until upstream rebuild is published.
|
||||
- **Standard pip install `onnxruntime` (CPU-only) succeeds but exposes only `CPUExecutionProvider` and `AzureExecutionProvider`** — does NOT include CUDA EP or TensorRT EP.
|
||||
|
||||
**Use**: backs Fact #95 (ONNX Runtime + TensorRT EP interop alternate candidate) per-mode API verification block + Plan-phase D-C7-3 ORT-Jetson-wheel-pin + D-C7-4 numpy-version-pin.
|
||||
|
||||
---
|
||||
|
||||
### Source #101 — PyTorch official documentation (context7-indexed) + Jetson AI Lab PyTorch wheel availability for JetPack 6
|
||||
|
||||
**Title**: PyTorch — open-source machine learning framework (tensor computation with strong GPU acceleration; tape-based autograd); Jetson-specific wheels available via Jetson AI Lab + NVIDIA forums
|
||||
**Tier**: L1 — official authoritative SDK documentation (PyTorch Foundation primary) + L1 NVIDIA Developer Forums (canonical Jetson PyTorch distribution channel)
|
||||
**URL**: <https://pytorch.org/docs/stable/amp.html> + context7 indexed at `/pytorch/pytorch` (v2.5.1, v2.8.0, v2.9.1, v2.11.0) + <https://forums.developer.nvidia.com/t/installing-pytorch-for-jetpack-6-2/349519> + <https://forums.developer.nvidia.com/t/jetpack-6-2-and-pytorch-2-6-0-on-jetson-nano-orin/331972>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ context7 query "torch.cuda.amp.autocast half precision FP16 inference mode no_grad CUDA Jetson Orin ARM64 model.half() torch.compile inference deployment" returned 4866 code snippets at Source Reputation High + Benchmark Score 76.69.
|
||||
|
||||
**Key APIs verified**:
|
||||
- **`torch.amp.autocast(device_type, dtype, enabled, cache_enabled)`** — canonical AMP context manager (since PyTorch 1.10). Replaces deprecated `torch.cuda.amp.autocast`. Inference pattern:
|
||||
```python
|
||||
with torch.no_grad():
|
||||
with torch.autocast(device_type='cuda', dtype=torch.float16, enabled=True):
|
||||
output = model(input)
|
||||
```
|
||||
- **`torch.compile(model, backend='inductor')`** — graph-mode optimization for further speedup; tradeoff is cold-start compile cost (~10-60 sec depending on model complexity).
|
||||
- **`model.half()`** — eager-mode FP16 weight conversion (full-precision FP16 throughout, vs autocast's per-op precision selection).
|
||||
|
||||
**Jetson install constraints**:
|
||||
- **Standard `pip install torch` does NOT include CUDA support on Jetson** — must use NVIDIA-published or Jetson AI Lab community wheels.
|
||||
- **JetPack 6.2 + CUDA 12.6 + Ubuntu 22.04 + Python 3.10 canonical wheel**: `torch-2.9.0-cp310-cp310-linux_aarch64.whl` from Jetson AI Lab (per NVIDIA forum recommendation). Earlier stable combination: PyTorch 2.5 + torchvision 0.20.
|
||||
- **Known dependency issues**: missing `libcudss.so.0` and `libnvdla_runtime.so` on PyTorch 2.9 cu129 wheel under JetPack 6.2 (CUDA 12.6) — version mismatch between wheel build target and installed JetPack CUDA. Mitigation: prefer the cu126 variant for JetPack 6.2.
|
||||
- **CUDA capability**: Jetson Orin Nano Super GPU = compute capability **SM 87** (Ampere class).
|
||||
|
||||
**Use**: backs Fact #96 (pure PyTorch FP16 mandatory simple-baseline candidate) per-mode API verification block + D-C7-5 PyTorch-Jetson-wheel-pin.
|
||||
|
||||
---
|
||||
|
||||
### Source #102 — Ultralytics YOLO26 benchmark suite on Jetson Orin Nano Super (April 2026)
|
||||
|
||||
**Title**: Update NVIDIA Jetson Orin Nano Super benchmarks with YOLO26 (Ultralytics 8.4.33; commit 8d4e6e8 April 2026)
|
||||
**Tier**: L1 — official authoritative benchmark suite (Ultralytics is the canonical YOLO maintainer)
|
||||
**URL**: <https://github.com/ultralytics/ultralytics/pull/24097> + <https://github.com/ultralytics/ultralytics/commit/8d4e6e841c89f6598b322695cb2bc816eeba8b93>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ Web search results explicitly cite the per-export-format inference times measured on Jetson Orin Nano Super.
|
||||
|
||||
**Key data extracted (YOLO26n on Jetson Orin Nano Super, April 2026 measurement)**:
|
||||
|
||||
| Export format | Inference time (ms) | mAP50-95 | Speedup vs FP32 | Accuracy delta vs FP16 |
|
||||
|---|---|---|---|---|
|
||||
| TensorRT FP32 | 7.53 | 0.4770 | 1.00× | — |
|
||||
| TensorRT FP16 | 4.57 | 0.4800 | 1.65× | baseline (slightly higher than FP32 due to noise) |
|
||||
| TensorRT INT8 | 3.80 | 0.4490 | 1.98× | **-6.5% mAP50-95** |
|
||||
|
||||
**Key data extracted (YOLOv8s on Jetson Orin Nano, NVIDIA forum)**:
|
||||
- **INT8**: ~157 QPS (~6.4 ms/inference)
|
||||
- **FP16**: ~103 QPS (~9.7 ms/inference)
|
||||
- **INT8 vs FP16 speedup**: ~1.5× (vs ~1.20× on YOLO26n — model architecture and memory bandwidth dependent)
|
||||
|
||||
**Use**: backs Fact #94 (TensorRT) latency claims for object-detection-class CNN backbones on Jetson Orin Nano Super; provides empirical anchor for the engine's "INT8 primary + FP16 fallback" precision strategy. Caveat: YOLO is a detection network; feature-matching networks (LightGlue / DISK / XFeat) are known to be more quantization-sensitive (see Source #103).
|
||||
|
||||
---
|
||||
|
||||
### Source #103 — LightGlue ONNX Runtime + TensorRT acceleration (canonical reference) + FP8 ModelOpt quantization findings (Fabio Sim's Journal)
|
||||
|
||||
**Title**: Accelerating LightGlue Inference with ONNX Runtime and TensorRT (Fabio Sim's Journal, canonical author of `fabio-sim/LightGlue-ONNX`) + FP8 Quantized LightGlue in TensorRT with NVIDIA Model Optimizer (subsequent post)
|
||||
**Tier**: L1 — canonical author of the canonical LightGlue ONNX/TensorRT export pathway (already cited as Source #73 in C3 row)
|
||||
**URL**: <https://fabio-sim.github.io/blog/accelerating-lightglue-inference-onnx-runtime-tensorrt/> + <https://fabio-sim.github.io/blog/fp8-quantized-lightglue-tensorrt-nvidia-model-optimizer/> + <https://github.com/qdLMF/LightGlue-with-FlashAttentionV2-TensorRT> (community Jetson Orin NX TensorRT 8.5.2 + FlashAttentionV2 plugin reference implementation)
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ Web search results explicitly cite the 2-4× ONNX Runtime + TensorRT speedup over compiled PyTorch and the FP8 5.97× / 0.32× engine-size results.
|
||||
|
||||
**Key data extracted**:
|
||||
- **LightGlue (transformer-based feature matcher) — ONNX Runtime + TensorRT inference**: 2-4× speedup over compiled PyTorch across various batch sizes and sequence lengths.
|
||||
- **FP8 quantized LightGlue (NVIDIA ModelOpt) on Hopper/Ada/Blackwell**:
|
||||
- Engine size ~0.32× of FP32 (~68% smaller).
|
||||
- Up to 5.97× speedup vs FP32.
|
||||
- **Material accuracy degradation**: "match counts dropped. Sometimes they dropped hard." This is qualitatively different from YOLO-class detection networks where INT8 is well-tolerated.
|
||||
- **FP8 hardware support**: requires Hopper / Ada / Blackwell architecture. **Jetson Orin Nano Super is Ampere (SM 87) — NOT FP8-native**. FP8 ModelOpt path applies only via INT8 emulation fallback on Ampere.
|
||||
- **Two FP8 formats**: E4M3 (4 exponent bits + 3 mantissa bits, better precision for activations) + E5M2 (5 exponent bits + 2 mantissa bits, better dynamic range for gradients).
|
||||
- **Community Jetson reference implementation**: `qdLMF/LightGlue-with-FlashAttentionV2-TensorRT` deploys on Jetson Orin NX 8 GB with TensorRT 8.5.2 + custom FlashAttentionV2 plugin.
|
||||
|
||||
**Use**: backs Fact #94 (TensorRT) feature-matching-network INT8 caveat; backs the "INT8-only candidates Experimental until calibration data exists" engine ruling per user-pinned `c7_quantization=A` scope; raises Plan-phase gate D-C7-6 INT8-vs-FP16-per-model-family-precision-policy.
|
||||
|
||||
---
|
||||
|
||||
### Source #104 — JetPack SDK release notes (NVIDIA official) — JetPack 6.0 / 6.1 / 6.2 version matrix
|
||||
|
||||
**Title**: NVIDIA JetPack 6.x SDK Release Notes — TensorRT/CUDA/cuDNN versions per release; Super Mode introduction in JetPack 6.2 (January 2025)
|
||||
**Tier**: L1 — official authoritative release notes (NVIDIA Developer)
|
||||
**URL**: <https://developer.nvidia.com/embedded/jetpack-sdk-60> + <https://developer.nvidia.com/embedded/jetpack-sdk-61> + <https://developer.nvidia.com/embedded/jetpack-sdk-62> + <https://developer.nvidia.com/blog/nvidia-jetpack-6-2-brings-super-mode-to-nvidia-jetson-orin-nano-and-jetson-orin-nx-modules/>
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ Web search results explicitly enumerate TensorRT / CUDA / cuDNN per JetPack release.
|
||||
|
||||
**Key data extracted**:
|
||||
|
||||
| JetPack | CUDA | TensorRT | cuDNN | Super Mode | Released |
|
||||
|---|---|---|---|---|---|
|
||||
| 6.0 | 12.2 | 8.6 | 8.9 | No | early 2024 |
|
||||
| 6.1 | 12.6 | 10.3 | 9.3 | MAXN mode (dev kit only) | mid-2024 |
|
||||
| **6.2** | **12.6** | **10.3** | **9.3** | **YES — Orin Nano Super + Orin NX production modules** | **2025-01-16** |
|
||||
|
||||
- **Super Mode performance gains** (vs base Orin Nano): up to 2× higher generative AI inference performance, 70% AI TOPS increase, 50% memory bandwidth boost.
|
||||
- **TensorRT 10.3** is the canonical inference runtime version for JetPack 6.1 / 6.2 deployments. Major API upgrade from TensorRT 8.x → 10.x — `IInt8EntropyCalibrator2` API surface is preserved; `INetworkDefinition` and `IBuilderConfig` semantics unchanged.
|
||||
|
||||
**Use**: pins the project's target software stack to **JetPack 6.2 + CUDA 12.6 + TensorRT 10.3 + cuDNN 9.3 + Super Mode enabled** for the Jetson Orin Nano Super target hardware. Backs Facts #94, #95, #96 deployability claims.
|
||||
|
||||
---
|
||||
|
||||
### Source #105 — TensorRT-on-Jetson canonical install constraints (Ultralytics issue reports + NVIDIA forum)
|
||||
|
||||
**Title**: TensorRT 10.x on Jetson Orin Nano — install path, hardware-specificity, memory-pressure-during-build constraints
|
||||
**Tier**: L2 — community-reported issues with NVIDIA-acknowledged root causes (high signal-to-noise on canonical constraints)
|
||||
**URL**: <https://github.com/ultralytics/ultralytics/issues/18882> ("TensorRT does not currently build wheels for Tegra systems") + <https://forums.developer.nvidia.com/t/tensorrt-10-7-0-on-orin-nano/364236> (SM 87 compute-capability mismatch) + <https://github.com/ultralytics/ultralytics/issues/18730> (laptop-GPU-built engine cannot load on Jetson) + <https://github.com/ultralytics/ultralytics/issues/21281> (TensorRT export memory pressure on Orin AGX)
|
||||
**Access date**: 2026-05-08
|
||||
**Direct verification**: ✅ Web search returned direct issue links with NVIDIA-confirmed root causes.
|
||||
|
||||
**Key constraints extracted** (CRITICAL for C7 deployment design):
|
||||
|
||||
1. **TensorRT Python wheels are NOT installed via pip on Jetson Tegra**. Standard `pip install tensorrt` raises: `RuntimeError: TensorRT does not currently build wheels for Tegra systems`. The canonical install path is the JetPack-bundled TensorRT (already present after `apt install nvidia-jetpack`), accessed via the system Python at `/usr/lib/python3.10/dist-packages/tensorrt`.
|
||||
2. **TensorRT engines are hardware-specific** — engines built against a laptop / dev-machine GPU CANNOT be loaded on the Jetson at runtime. **Engines must be built directly on the Jetson target**.
|
||||
3. **GPU compute capability mismatch is silent at build-time, fatal at load-time**: laptop GPUs (e.g., RTX 4090 = SM 89) and Jetson Orin Nano Super (SM 87) produce incompatible engines; the build emits no error, the load logs `Target GPU SM 87 is not supported by this TensorRT release` — version-and-SM-compatibility matrix must be respected.
|
||||
4. **TensorRT engine builds on Jetson under memory pressure can segfault during tactic profiling** (8 GB shared CPU+GPU is tight; a rich layer-fusion search consumes peak RAM during `tactic.profile` phase). Mitigation: limit `config.max_workspace_size` to a fraction of the budget (e.g., 1-2 GB) and avoid concurrent inference / Postgres / FAISS during builds.
|
||||
5. **JetPack 6.x ships the canonical TensorRT version** (TensorRT 10.3 for JP 6.1/6.2 per Source #104); upgrading TensorRT independently of JetPack is not officially supported.
|
||||
|
||||
**Use**: drives D-C7-7 build-on-Jetson-vs-prebuilt-engine-shipping-strategy + D-C7-8 max-workspace-size-cap-for-build-stability + D-C7-9 SM-compatibility-version-pin.
|
||||
|
||||
---
|
||||
|
||||
(Subsequent sources #106+ added during fact extraction below as candidate-specific evidence is gathered. Closure target: 3 candidate rows + 1 cross-cutting integration matrix.)
|
||||
@@ -0,0 +1,97 @@
|
||||
# Source Registry — C8: MAVLink / MSP2 FC adapter
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation). C8 batch 1 sources for the FC adapter (per-FC adapter pattern verified at SQ6 closure: ArduPilot Plane via MAVLink `GPS_INPUT`, iNav via `MSP2_SENSOR_GPS` primary OR UBX-impersonation alternate). Confidence labels per `references/source-tiering.md`. Cross-references back to SQ6 fact card sources (#4, #9, #10, #12, #13, #15) where the iNav inbound-handler reality and MSP2/UBX transport options were originally established.
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling component categories: [C1 VIO](C1_vio.md), [C2 VPR](C2_vpr.md), [C3 Matchers](C3_matchers.md), [C4 Pose](C4_pose_estimation.md), [C5 State estimator](C5_state_estimator.md), [C6 Tile cache](C6_tile_cache_spatial_index.md), [C7 Inference runtime](C7_inference_runtime.md). Cross-cuts: [SQ6 external positioning](SQ6_external_positioning.md).
|
||||
|
||||
## Sources
|
||||
|
||||
### Source #106 — ArduPilot Pymavlink (context7-indexed `/ardupilot/pymavlink`)
|
||||
- **Tier**: L1 (canonical Python MAVLink implementation maintained by ArduPilot)
|
||||
- **Found via**: context7 `resolve-library-id` → `/ardupilot/pymavlink` → `query-docs` for GPS_INPUT send patterns
|
||||
- **Library posture**: 32 code snippets indexed in context7 (Source Reputation: High); coverage emphasizes the JavaScript MAVLink generator output, with thinner Python-side examples in context7 — supplementary primary sources (canonical pymavlink GitHub README + ArduPilot GPS_INPUT dev docs Source #107) carry the canonical Python `master.mav.gps_input_send(...)` send pattern.
|
||||
- **License**: LGPL v3 (pymavlink itself); MAVLink generated dialects are MIT — the project's runtime dependency is on the LGPL pymavlink Python package. **Compatible with project's Apache-2.0 dual-use track**: LGPL allows linking from a non-LGPL application without "infecting" application license; the only obligation is to publish/redistribute any modifications to pymavlink itself (project does not modify pymavlink), and to allow users to relink against an updated pymavlink (trivially satisfied for an open-source / company-internal deployment with published `requirements.txt`).
|
||||
- **Critical-novelty-sensitivity**: Established baseline; no time window — pymavlink has been the canonical Python MAVLink stack since 2010+, and `GPS_INPUT` (msg 232) has been in `common.xml` since 2017 ArduPilot dev iteration.
|
||||
- **Per-mode capability verification (context7 + SQ6 Source #4 AP_GPS_MAV.cpp cross-cite)**: ✅ `GPS_INPUT` decoder confirmed in AP_GPS_MAV.cpp master per SQ6 Fact #1; Python sender uses `master = mavutil.mavlink_connection(...)` + `master.mav.gps_input_send(time_usec, gps_id, ignore_flags, time_week_ms, time_week, fix_type, lat, lon, alt, hdop, vdop, vn, ve, vd, speed_accuracy, horiz_accuracy, vert_accuracy, satellites_visible, yaw)` per pymavlink generated dialect.
|
||||
- **Used to support**: Fact #97 (ArduPilot Plane FC adapter primary candidate).
|
||||
|
||||
### Source #107 — ArduPilot Plane Non-GPS Position Estimation + MAVProxy GPS Input module documentation
|
||||
- **Tier**: L1 (official ArduPilot dev docs portal; documented configuration + canonical injection example)
|
||||
- **Found via**: web search for `pymavlink GPS_INPUT msg 232 example ArduPilot Plane non-GPS external positioning companion computer 2025`
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **URLs**:
|
||||
- https://ardupilot.org/dev/docs/mavlink-nongps-position-estimation.html
|
||||
- https://ardupilot.org/plane/docs/common-non-gps-navigation-landing-page.html
|
||||
- https://ardupilot.org/mavproxy/docs/modules/GPSInput.html
|
||||
- https://ardupilot.org/plane/docs/common-companion-computers.html
|
||||
- **Critical configuration captured**: `GPS1_TYPE = 14` (MAVLink) is required on the FC for `GPS_INPUT` ingestion. Without this parameter set, AP_GPS will not accept the message. `EK3_SRC1_POSXY = 3` (GPS) selects the GPS_INPUT-fed virtual GPS as the primary horizontal-position source. Per ArduPilot dev docs, the **preferred method** for non-GPS navigation is `ODOMETRY` or `VISION_POSITION_ESTIMATE` at ≥4 Hz — but `GPS_INPUT` remains supported and is the right choice when the project's outcome contract is "WGS84 coordinates as a real-GPS replacement" (AC-4.3 wording aligns with GPS_INPUT semantics, not ODOMETRY semantics).
|
||||
- **Cross-cite**: SQ6 Fact #1 (AP_GPS_MAV.cpp ingestion path) + SQ6 Fact #4 (`ODOMETRY`-velocity-only NOT supported) — together these pin `GPS_INPUT` as the right transport for the project's `{satellite_anchored, visual_propagated, dead_reckoned}` source-label scheme.
|
||||
- **Per-mode capability verification**: ✅ All required ACs (AC-4.3 / AC-NEW-2 / AC-NEW-4 / AC-NEW-8) map directly into GPS_INPUT field semantics per SQ6 working summary table.
|
||||
|
||||
### Source #108 — pyubx2 (context7-indexed `/semuconsulting/pyubx2` + canonical GitHub README)
|
||||
- **Tier**: L1 (canonical Python UBX/NMEA/RTCM3 parser; benchmark score 86.8 in context7; 139 code snippets)
|
||||
- **Found via**: context7 `resolve-library-id` → `/semuconsulting/pyubx2` → `query-docs` for UBX-NAV-PVT message construction with full attribute control + serialize-to-bytes pattern for UART transmission
|
||||
- **Library posture**: BSD-3-Clause license (clean, dual-use compatible); semuconsulting publishes both the canonical GitHub repo + comprehensive readthedocs.io documentation also indexed in context7 as `/websites/semuconsulting_pyubx2` (239 additional code snippets, benchmark 85.2). The library supports `UBXMessage(ubxClass, ubxID, mode, **kwargs)` constructor with three modes: `GET (0x00)` for output from the receiver, `SET (0x01)` for command input, `POLL (0x02)` for query input. NAV-PVT belongs to the GET output set.
|
||||
- **Critical-novelty-sensitivity**: Library/SDK API behaviour — must reflect currently shipped version; semuconsulting/pyubx2 is daily-active (last released 2025).
|
||||
- **Per-mode capability verification (context7-confirmed)**: ✅ NAV-PVT message construction with all UBX-NAV-PVT fields supported as keyword arguments per `UBXMessage('NAV', 'NAV-PVT', GET, iTOW=..., year=..., lon=..., lat=..., height=..., hMSL=..., hAcc=..., vAcc=..., velN=..., velE=..., velD=..., gSpeed=..., headMot=..., sAcc=..., headAcc=..., pDOP=..., fixType=..., flags=..., numSV=..., valid=...)`. ✅ `serialize()` method returns the full UBX wire-format bytestring (sync-bytes 0xB5 0x62 + class + ID + length + payload + 8-bit Fletcher checksum). ✅ `parsebitfield=1` mode allows individual bit attributes for `flags` (e.g., `gnssFixOK`, `diffSoln`, `psmState`) and `valid` (e.g., `validDate`, `validTime`, `fullyResolved`, `validMag`) — required for the impersonation path to set the `gnssFixOK` bit that iNav's `gpsMapFixType()` validates.
|
||||
- **Used to support**: Fact #98 (iNav UBX impersonation alternate candidate).
|
||||
|
||||
### Source #109 — u-blox NEO-M9N Integration Manual (UBX-19014286) + u-blox 8/M8 Receiver Description (UBX-13003221) — UBX-NAV-PVT canonical specification
|
||||
- **Tier**: L1 (vendor-authoritative protocol specification PDFs)
|
||||
- **Found via**: web search for `UBX-NAV-PVT frame structure spec u-blox protocol M8 M9 fix type fabricate inject iNav 2025`
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **URLs**:
|
||||
- https://content.u-blox.com/sites/default/files/NEO-M9N_Integrationmanual_UBX-19014286.pdf
|
||||
- https://content.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_UBX-13003221.pdf
|
||||
- **Frame structure captured**: NAV-PVT (class=0x01, ID=0x07) carries 92-byte payload — `iTOW (u32 ms)` + `year (u16)` + `month/day/hour/min/sec (u8 each)` + `valid (u8 bitmask)` + `tAcc (u32 ns)` + `nano (i32 ns)` + `fixType (u8 enum: 0=NoFix, 1=DeadReck, 2=2D, 3=3D, 4=GNSS+DR, 5=TimeOnly)` + `flags (u8 bitmask incl. gnssFixOK bit 0)` + `flags2 (u8)` + `numSV (u8)` + `lon (i32 deg×1e-7)` + `lat (i32 deg×1e-7)` + `height (i32 mm above ellipsoid)` + `hMSL (i32 mm above mean sea level)` + `hAcc (u32 mm)` + `vAcc (u32 mm)` + `velN/velE/velD (i32 each mm/s)` + `gSpeed (i32 mm/s)` + `headMot (i32 deg×1e-5)` + `sAcc (u32 mm/s)` + `headAcc (u32 deg×1e-5)` + `pDOP (u16 ×0.01)` + reserved bytes + `headVeh (i32)` + `magDec (i16)` + `magAcc (u16)`. M9N supersedes M8 with refined NAV-PVT semantics; both are accepted by iNav 9.0 (per Source #11 in SQ6 — UBX ≥ 15.00 protocol version).
|
||||
- **Critical-novelty-sensitivity**: Established baseline + library/SDK API behaviour — u-blox NAV-PVT is a stable protocol surface since u-blox 8 (2014); minor field semantics evolve across vendor protocol versions, so exact wire format must be checked against the iNav-target version (iNav 9.0 expects ≥ 15.00).
|
||||
- **Per-mode capability verification**: ✅ NAV-PVT contains all fields needed for iNav's `gpsMapFixType()` validation (Source #110 cross-cite): `flags` byte bit 0 `gnssFixOK` + `fixType` enum + `numSV` + `hAcc/vAcc` for AC-NEW-4 covariance honesty.
|
||||
- **Used to support**: Fact #98 (iNav UBX impersonation alternate candidate) NAV-PVT frame fabrication spec.
|
||||
|
||||
### Source #110 — iNav `gps_ublox.c` source (master, GitHub) — UBX validation gates that the impersonation must pass
|
||||
- **Tier**: L1 (canonical iNav firmware source, master branch, accessed via cached web fetch)
|
||||
- **Found via**: web search for `iNav GPS UBX validation fixType numSat hDOP threshold reject GNSS spoofing companion computer 2025`
|
||||
- **URL**: https://github.com/iNavFlight/inav/blob/master/src/main/io/gps_ublox.c
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **Critical-novelty-sensitivity**: Library/SDK API behaviour — must reflect current shipped iNav version. iNav 9.0 master (post-2025-12-11 wiki update per SQ6 Source #10) confirmed via direct file read.
|
||||
- **Validation logic captured (line-numbered evidence)**:
|
||||
- **Line 215-220**: `gpsMapFixType(fixValid, ubloxFixType)` returns `GPS_FIX_2D` if `fixValid && ubloxFixType == FIX_2D`, returns `GPS_FIX_3D` if `fixValid && ubloxFixType == FIX_3D`, otherwise `GPS_NO_FIX`. **THIS IS THE GATE** the impersonation must pass.
|
||||
- **Line 654**: NAV-PVT path computes `next_fix_type = gpsMapFixType(_buffer.pvt.fix_status & NAV_STATUS_FIX_VALID, _buffer.pvt.fix_type)`. The `fix_status & NAV_STATUS_FIX_VALID` masks the lowest bit of NAV-PVT's `flags` byte (bit 0 = `gnssFixOK`).
|
||||
- **Lines 656-683**: NAV-PVT-driven full state population including `lon (1e-7 deg)`, `lat (1e-7 deg)`, `altitude_msl (mm)`, NED velocity (mm/s converted to cm/s), `speed_2d (mm/s)`, `heading_2d (deg×1e-5 → deg×10)`, `satellites`, `horizontal_accuracy (mm)`, `vertical_accuracy (mm)`, `position_DOP`, valid date/time bits.
|
||||
- **Lines 1024-1060**: Configuration logic — for u-blox version ≥ 15.0 (iNav 9.0+), iNav configures NAV-PVT-only via `configureMSG(MSG_CLASS_UBX, MSG_PVT, 1)`. For older receivers, configures the legacy NAV-POSLLH + NAV-SOL + NAV-VELNED + NAV-TIMEUTC quad. **Implication**: companion impersonator should advertise version ≥ 15.0 via NAV-VER (CLASS=0x0A, ID=0x04) to drive iNav into the simpler NAV-PVT-only protocol.
|
||||
- **Per-mode capability verification**: ✅ Validation gate fully decoded; impersonation viability confirmed at the firmware-source level (no opaque downstream filter discovered).
|
||||
- **Used to support**: Fact #98 — provides the iNav-firmware-side validation contract that the UBX impersonation must satisfy.
|
||||
|
||||
### Source #111 — iNav `docs/development/msp/README.md` (master, GitHub) — MSP2_SENSOR_GPS canonical payload specification
|
||||
- **Tier**: L1 (canonical iNav protocol-reference documentation, master branch, accessed via cached web fetch)
|
||||
- **Found via**: web search for `MSP2_SENSOR_GPS Python library iNav msp2 protocol companion computer external GPS injection 2025 2026`
|
||||
- **URL**: https://github.com/iNavFlight/inav/blob/master/docs/development/msp/README.md
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **Payload structure captured (line 2999-3031 of the master README)**: `MSP2_SENSOR_GPS (7939 / 0x1F03)` — request payload 36 bytes containing `instance (u8)` + `gpsWeek (u16)` + `msTOW (u32 ms)` + `fixType (u8 = gpsFixType_e)` + `satellitesInView (u8)` + `hPosAccuracy (u16 mm)` + `vPosAccuracy (u16 mm)` + `hVelAccuracy (u16 cm/s)` + `hdop (u16 ×0.01)` + `longitude (i32 deg×1e7)` + `latitude (i32 deg×1e7)` + `mslAltitude (i32 cm)` + `nedVelNorth (i32 cm/s)` + `nedVelEast (i32 cm/s)` + `nedVelDown (i32 cm/s)` + `groundCourse (u16 deg×100)` + `trueYaw (u16 deg×100, 65535 = unavailable)` + `year (u16)` + `month/day/hour/min/sec (u8 each)`. **Reply payload: None.** **Notes: Requires `USE_GPS_PROTO_MSP`. Calls `mspGPSReceiveNewData()`.**
|
||||
- **Critical-novelty-sensitivity**: Library/SDK API behaviour — verified against iNav master (post-9.0).
|
||||
- **Per-mode capability verification**: ✅ Full payload spec covers all AC-NEW-4 covariance honesty fields (`hPosAccuracy`, `vPosAccuracy`, `hVelAccuracy`); ✅ AC-NEW-8 graceful-degrade signal carried via `fixType` enum (`gpsFixType_e`) — companion can emit `GPS_NO_FIX` (0) or `GPS_FIX_2D` (1) for the "covariance >100 m" / "covariance >500 m" thresholds; ✅ AC-1.4 95% covariance proxy carried in `hPosAccuracy`.
|
||||
- **Used to support**: Fact #99 (iNav MSP2_SENSOR_GPS primary candidate).
|
||||
|
||||
### Source #112 — Python MSP2 implementations: YAMSPy + INAV-Toolkit `inav_msp.py`
|
||||
- **Tier**: L2 (community implementations; NOT vendor-canonical but actively maintained)
|
||||
- **Found via**: web search for Python MSP2_SENSOR_GPS libraries; iNav Issue #4465 confirms YAMSPy as community-recommended; agoliveira/INAV-Toolkit confirmed via direct GitHub source read
|
||||
- **URLs**:
|
||||
- YAMSPy mention: https://github.com/iNavFlight/inav/issues/4465
|
||||
- INAV-Toolkit `inav_msp.py`: https://github.com/agoliveira/INAV-Toolkit/blob/5c4ef789068399b4dc7461b71c6f71c25aef5e4e/inav_msp.py
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **Library posture**:
|
||||
- **YAMSPy** (`thecognifly/YAMSPy`): MIT-licensed Python library with explicit MSP V2 support; community-blessed for iNav external-device communication per the iNav issue thread.
|
||||
- **INAV-Toolkit `inav_msp.py`**: 951-line MIT-licensed module implementing `msp_v2_encode(cmd, payload)` + `msp_v2_decode(buffer)` with CRC-8 DVB-S2 checksumming + serial transport. Direct primary-source implementation reference for MSP V2 frame construction.
|
||||
- **Critical-novelty-sensitivity**: Library/SDK API behaviour — both libraries are recent (post-2024 commits). **Risk**: community libraries may lag the iNav protocol surface (e.g., MSP V2 sensor message range 0x1F00-0x1FFF was added later than the original MSP V2 baseline). The project may need to either (a) extend the chosen community library with MSP2_SENSOR_GPS-specific encoding helpers, or (b) implement a thin custom encoder using the canonical msp_v2_encode primitive — both paths verified feasible from primary sources.
|
||||
- **License notes**: MIT throughout — clean dual-use compatible.
|
||||
- **Per-mode capability verification**: ⚠️ MSP V2 frame envelope (0x24 + 'X' + 0x3C + flag + cmd_lo + cmd_hi + len_lo + len_hi + payload + CRC8-DVB-S2) confirmed via INAV-Toolkit primary source; ✅ MSP2_SENSOR_GPS payload structure confirmed via Source #111. Combining the two yields a complete companion-side encoder for the iNav primary path.
|
||||
- **Used to support**: Fact #99 (iNav MSP2_SENSOR_GPS primary candidate, Python implementation path).
|
||||
|
||||
### Source #113 — iNav `src/main/msp/msp_protocol_v2_sensor.h` (master, GitHub) — MSP2 sensor command-ID range
|
||||
- **Tier**: L1 (canonical iNav firmware source, master branch)
|
||||
- **Found via**: web search co-result with Source #112; opens via the `msp_protocol_v2_sensor.h` direct link
|
||||
- **URL**: https://github.com/iNavFlight/inav/blob/master/src/main/msp/msp_protocol_v2_sensor.h
|
||||
- **Date accessed**: 2026-05-08
|
||||
- **Critical fact captured**: `MSP2_SENSOR_GPS = 0x1F03` (= 7939 decimal); MSP V2 sensor-message range `0x1F00-0x1FFF` is reserved for sensor injection plugins. iNav 9.0 master expectation: MSP2 frame must use the MSP V2 envelope (sync = 0x24 0x58 0x3C; flag = 0x00; cmd = LE 16-bit; len = LE 16-bit; CRC = CRC-8 DVB-S2 over flag through end of payload).
|
||||
- **Per-mode capability verification**: ✅ MSP2_SENSOR_GPS = 0x1F03 confirmed at source; ✅ MSP V2 envelope spec confirmed.
|
||||
- **Used to support**: Fact #99 — provides the canonical MSP V2 sensor-message-range definition.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Source Registry — Mode B Addendum (2026-05-08)
|
||||
|
||||
> Mode B Solution Assessment of `_docs/01_solution/solution_draft01.md`. New sources gathered for findings F1–F20; Mode A sources #1–#121 remain canonical and are not duplicated.
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Mode B fact cards: [`../02_fact_cards/MODEB_addendum.md`](../02_fact_cards/MODEB_addendum.md). Mode B fit-matrix revisions: [`../06_component_fit_matrix/MODEB_revisions.md`](../06_component_fit_matrix/MODEB_revisions.md). Mode B output: [`../../01_solution/solution_draft02.md`](../../01_solution/solution_draft02.md).
|
||||
|
||||
## New Sources
|
||||
|
||||
| # | Title | Tier | Binding |
|
||||
|---|-------|------|---------|
|
||||
| 122 | HKUST-Aerial-Robotics/VINS-Mono LICENCE file (canonical, master branch) — GNU GPL Version 3 | L1 (verified raw LICENCE on github.com) | C1 candidate-table license-correction (F11/F15). Confirms VINS-Mono is **GPL-3.0**, not BSD-permissive as draft01 claims. Cross-confirms Mode A C1 Fact #28 against Mode A draft01 deliverable. |
|
||||
| 123 | MegaLoc — "One Retrieval to Place Them All" (Berton & Masone, arXiv:2502.17237; CVPR 2025 Image Matching workshop; gmberton/megaloc repo, MIT) | L1 | C2 D-C2-11 candidate (F16). torch.hub install path; MIT license; SOTA on multiple VPR datasets; combines existing methods + training techniques + datasets into a unified retrieval model. |
|
||||
| 124 | UltraVPR — "Unsupervised Lightweight Rotation-Invariant Aerial VPR" (cbbhuxx/UltraVPR repo, MIT; published RAL 2025; ICRA 2026) | L1 | C2 D-C2-11 alternative (F17). MIT license; **44 Hz on Jetson Orin NX (close cousin of Orin Nano Super)** via ONNX export; rotation-invariant; specifically designed for UAV; validated on VPAir + UAV-VisLoc datasets — directly relevant to the project's pinned operating context. |
|
||||
| 125 | AirZoo — "Unified Large-Scale Dataset for Grounding Aerial Geometric 3D Vision" (arXiv:2604.26567v1, 2026) | L1 | C2 evidence base for MegaLoc on aerial domain (F16). Demonstrates that fine-tuning MegaLoc on aerial data yields substantial performance gains for aerial image retrieval and cross-view matching. |
|
||||
| 126 | NVD CVE-2026-1579 — MAVLink protocol Missing Authentication for Critical Function (CVSS 9.8 CRITICAL) | L1 | New cross-cutting security gate (F18). MAVLink lacks cryptographic authentication by default; an unauthenticated party with MAVLink interface access can send arbitrary commands including SERIAL_CONTROL for interactive shell. **Mitigation: enable MAVLink 2.0 message signing.** Affects ArduPilot Plane and PX4; iNav has only partial MAVLink support and does not implement message signing. |
|
||||
| 127 | NVD CVE-2025-53644 — OpenCV uninitialized variable on stack reading crafted JPEG (CVSS 9.8 CRITICAL) | L1 | C4 OpenCV pin update (F19). Affects 4.10.0 / 4.11.0; **fixed in 4.12.0**. Draft01 says "OpenCV 4.x" — must pin **≥4.12.0**. Triggers heap-buffer-write via crafted JPEG file load — relevant if any image format reaching OpenCV originates from uncertain provenance (e.g., tile cache import, FDR thumbnail re-load). |
|
||||
| 128 | ArduPilot MAVLink2 Signing — Plane documentation (`ardupilot.org/plane/docs/common-MAVLink2-signing.html`) + Issue #28736 channel-specific signing PR #29546 (March 2025) | L1 | F18 mitigation evidence. Confirms ArduPilot supports MAVLink2 signing via Mission Planner SETUP > Advanced > "Mavlink Signing" menu; non-USB serial ports can be configured to only respond to MAVLink commands carrying the correct passkey; PR #29546 adds bitmask parameter to enable/disable signing per channel for wired companion-computer connections. |
|
||||
| 129 | iNav MAVLink Wiki (`iNavFlight/inav/wiki/Mavlink`) | L1 | F18 cross-FC asymmetry (verified 2026-05-08 via web search). iNav has partial MAVLink support and **does NOT implement MAVLink message signing**. Companion-FC inbound on iNav is MSP2 (not MAVLink) so signing-gap is on the outbound MAVLink telemetry side, not the inbound external-positioning path — but cross-FC asymmetry is still material for AC-NEW-7 and the GCS link. |
|
||||
| 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 | F8 D-C8-2 evidence (cross-confirms Mode A SQ6 Fact #3). Re-verifies on 2026-05-08 web search that ArduPilot supports the command at firmware level (since August 2021) but **no production-deployed GCS or companion is documented as implementing the companion-driven switch pattern** the project plans to use. Pattern is therefore **novel for a deployed production system** — confirms Mode A characterization but elevates to risk-graded selection. |
|
||||
| 131 | XoFTR — "Cross-modal Feature Matching Transformer" (arXiv:2404.09692) + 2026 SAR-optical satellite registration benchmark (arXiv:2604.10217) | L2 | F20 contrarian-evidence reference. Cross-modal matcher; achieved lowest mean error (3.0 px) on SpaceNet9 SAR-optical training scenes among 24 pretrained matcher families benchmarked. **Important contrarian finding: matchers without explicit cross-modal training sometimes performed comparably**, suggesting foundation-model features (like DINOv2) provide modality invariance — reinforces SelaVPR (DINOv2-L) over MixVPR (CNN-only) on the BSD/permissive C2 axis when cross-domain UAV→satellite registration is the binding stress test. |
|
||||
|
||||
---
|
||||
|
||||
## Verification audit-trail (mandatory per `00_question_decomposition.md` Step 0.5 cross-validation rule)
|
||||
|
||||
| Source | Independent corroboration |
|
||||
|---|---|
|
||||
| #122 (VINS-Mono GPL-3.0) | Cross-confirms Mode A C1 Fact #28 (`02_fact_cards/C1_vio.md`) which already classified VINS-Mono as GPL-3.0; the discrepancy was inside the deliverable layer (`solution_draft01.md` C1 candidate table), not the evidence layer. Both Mode A C1 Fact #28 and Source #122 agree. |
|
||||
| #123 (MegaLoc) | arXiv preprint + CVPR 2025 workshop + GitHub repo + Hugging Face — three-independent-source confirmation per Critical-novelty cross-validation rule. |
|
||||
| #124 (UltraVPR) | RAL 2025 IEEE journal publication + ICRA 2026 + GitHub repo with pre-trained ONNX weights — three independent sources. |
|
||||
| #125 (AirZoo) | arXiv preprint April 2026 — single source; treated as ⚠️ Medium confidence pending second cross-validation. |
|
||||
| #126 (CVE-2026-1579) | NVD official entry + CISA ICS Advisory ICSA-26-090-02 + PX4 GHSA-fh32-qxj9-x32f — three-source confirmation; Critical CVSS. |
|
||||
| #127 (CVE-2025-53644) | NVD official entry; OpenCV release notes confirming 4.12.0 fix — two-source confirmation. |
|
||||
| #128 (ArduPilot MAVLink2 signing) | Official Plane documentation + Issue #28736 + PR #29546 — three-source confirmation. |
|
||||
| #129 (iNav no signing) | iNav wiki (frogmane edited 2025-12-11) — single authoritative source per project convention; iNav wiki is the canonical iNav reference per Mode A SQ6 source #10. |
|
||||
| #130 (companion-driven EKF source switch) | ArduPilot official ekf-sources doc + PR #18345 + cross-confirms SQ6 Mode A Source #3 already-documented "no GCSs known to implement". Three-source confirmation. |
|
||||
| #131 (XoFTR cross-modal) | arXiv preprint + 2026 SAR-optical benchmark study (arXiv:2604.10217) — two-source confirmation. |
|
||||
@@ -0,0 +1,179 @@
|
||||
# Source Registry — SQ1 — Existing / competitor GPS-denied UAV navigation systems
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> This file replaces a section of the previous monolithic `01_source_registry.md`. See `00_summary.md` for the full category index. Investigation order is tracked in `../00_question_decomposition.md` and the cross-category Investigation Status table in `00_summary.md`.
|
||||
|
||||
---
|
||||
|
||||
### Source #25
|
||||
- **Title**: Twist Robotics develops OSCAR — a GPS-independent visual navigation system for drones resistant to electronic warfare equipment
|
||||
- **Link**: https://www.pravda.com.ua/eng/news/2026/01/28/8018266/
|
||||
- **Tier**: L2 (national newspaper of record reporting on a Technology Forces of Ukraine release; primary press is the Technology Forces of Ukraine FB post)
|
||||
- **Publication Date**: 2026-01-28 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid (within 6-month critical-novelty window)
|
||||
- **Target Audience**: Ukraine-deployment practitioners; UAV companion-system designers
|
||||
- **Research Boundary Match**: **Full match** — Ukrainian fixed-wing-class UAV, GPS-denied, vision-based, deployed in active conflict
|
||||
- **Summary**: Twist Robotics (UA) deployed OSCAR ("Optical System of Coordinates with Automatic Relocalisation") — camera + landmark-matching + map → autopilot ingests as a "reliable GPS signal". Vendor claims: 20 m accuracy without cumulative error, day/night/fog operation, 500,000 km logged across 25,000 combat missions over 24 months development, AI-augmented + Obrii proprietary simulator for training. Note: hardware photo shows active cooling on the module — implies non-trivial compute (probably Jetson-class). **No public independent benchmark.** Closest deployed peer system to this project.
|
||||
- **Related Sub-question**: SQ1 (closest peer); also informs SQ8 (anti-spoofing claims), SQ9 (synthesis)
|
||||
|
||||
|
||||
### Source #26
|
||||
- **Title**: Ukraine Gives Drones Vision-Based Navigation to Push Past Heavy Jamming — The Defense Post
|
||||
- **Link**: https://thedefensepost.com/2026/01/29/ukraine-drones-vision-navigation/
|
||||
- **Tier**: L2 (defense-trade publication; corroborates Source #25 with a second-party byline)
|
||||
- **Publication Date**: 2026-01-29 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Defense-policy / procurement readership
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Confirms OSCAR is operational, terrain-imagery-against-mapped-landmarks pattern, autopilot-ingestion. Adds "live imagery" framing. No new technical detail beyond Source #25.
|
||||
- **Related Sub-question**: SQ1
|
||||
|
||||
|
||||
### Source #27
|
||||
- **Title**: Ukraine's Ruta Missile Drone Will Get an EW-Immune Navigation System — Defense Express
|
||||
- **Link**: https://en.defence-ua.com/weapon_and_tech/ukraines_ruta_missile_drone_will_get_an_ew_immune_navigation_system-14541.html
|
||||
- **Tier**: L2 (defense-trade publication, Ukraine-domestic)
|
||||
- **Publication Date**: 2025-05-17 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid (within 18-month authority window)
|
||||
- **Target Audience**: Defense-procurement / industry analysts
|
||||
- **Research Boundary Match**: Partial — operational profile (cruise-missile-class, terminal guidance) differs from our 8-h fixed-wing surveillance/strike profile; technique class is closely related (DSMAC pattern)
|
||||
- **Summary**: Destinus Ruta (Ukrainian-Swiss origin; ~300 km strike range, miniature cruise missile) will integrate a navigation system from UAV Navigation (Spanish, Grupo Oesía). Defense Express infers DSMAC-style operating principle: "takes images of surface mid-flight, identifies location through comparison with reference". Vendor announcement notes validation in Ukrainian combat conditions including GNSS-denied / jamming / spoofing. Establishes that the cruise-missile-tier vision-nav pattern is now being miniaturised for ~300 km strike drones.
|
||||
- **Related Sub-question**: SQ1 (commercial/military landscape)
|
||||
|
||||
|
||||
### Source #28
|
||||
- **Title**: Kilometer-Scale GNSS-Denied UAV Navigation via Heightmap Gradients: A Winning System from the SPRIN-D Challenge
|
||||
- **Link**: https://arxiv.org/abs/2510.01348
|
||||
- **Tier**: L1 (peer-style preprint, full system description, real flight data, competition results)
|
||||
- **Publication Date**: October 2025 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: arXiv v1 (2510.01348v1)
|
||||
- **Target Audience**: GNSS-denied UAV system designers (academic + practitioner)
|
||||
- **Research Boundary Match**: **Partial — different regime.** Multirotor (≤25 kg), <25 m AGL, LiDAR-equipped, no satellite-tile basemap; 9 km waypoint mission. Our project is fixed-wing, ~1 km AGL, no LiDAR, monocular + sat-tile basemap. **Architectural pattern transfers; specific algorithm does NOT** (heightmap gradients require LiDAR).
|
||||
- **Summary**: CTU Prague team won SPRIN-D Funke Fully Autonomous Flight Challenge with: VIO (OpenVINS) + LiDAR-derived local heightmap + gradient template matching against open-data DEM + clustered K-means particle filter, all on Intel NUC i7 16 GB CPU-only (no GPU). Achieved RMSE <11 m over kilometer-scale flights vs ≤53 m for raw odometry. Critical observations explicitly stated:
|
||||
- **RTAB-Map and ORB-SLAM3 both fail** beyond 1 km / above 2 m/s flight (compute/memory) and ORB-SLAM3 loses tracking in textureless areas — directly applicable to our 17 m/s cruise over agricultural steppe.
|
||||
- **"Some teams used RGB satellite image-based matching, but this has proved to be highly unreliable at such low altitudes."** This is a low-altitude (<25 m AGL) finding; our 1 km AGL operates in the high-altitude regime where the same paper notes RGB sat-matching "works reasonably well" (refs [5][6]).
|
||||
- Lesson: "ability to recover from periods of high uncertainty and re-localize is more critical than maintaining consistently low instantaneous RMSE." Direct architectural input for AC-NEW-2 / AC-NEW-8.
|
||||
- Lesson: IMU-from-airframe vibration isolation is mission-critical for VIO usability.
|
||||
- Lesson: magnetometer is unreliable near steel-reinforced structures; sensor-fusion is essential for heading robustness.
|
||||
- **Related Sub-question**: SQ1 + SQ5 (failure modes for VIO/SLAM at speed) + SQ2 (canonical pipeline)
|
||||
|
||||
|
||||
### Source #29
|
||||
- **Title**: Hierarchical Image Matching for UAV Absolute Visual Localization via Semantic and Structural Constraints
|
||||
- **Link**: https://arxiv.org/abs/2506.09748 (PDF: https://arxiv.org/pdf/2506.09748)
|
||||
- **Tier**: L1 (peer-submitted preprint, IEEE-bound, with public CS-UAV dataset)
|
||||
- **Publication Date**: June 2025 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid (within 6-month critical-novelty window for SOTA claims)
|
||||
- **Version Info**: arXiv v1 (2506.09748v1)
|
||||
- **Target Audience**: Academic SOTA researchers + UAV-localization implementers
|
||||
- **Research Boundary Match**: **Full match** — exact same problem (UAV absolute visual localization in GNSS-denied conditions, downward-facing camera, satellite reference)
|
||||
- **Summary**: 2025 SOTA pipeline: (1) image retrieval module (off-the-shelf, optimal-transport feature aggregation), (2) Semantic-Aware and Structure-Constrained Matching Module using **DINOv2** features + 4D correlation tensor + SoftMNN + 4D conv, (3) lightweight fine-grained module for pixel-level. Constructs UAV absolute visual-loc pipeline **without VIO/relative-loc dependence** (retrieval-and-matching only). Evaluation on AerialVL + their own CS-UAV. **Direct relevance**: this is a candidate template for our C2 (VPR) + C3 (cross-domain registration) components, but DINOv2 is a heavyweight foundation model — must be benchmarked under our 25 W / 8 GB Jetson Orin Nano envelope before selection (handed off to SQ3/SQ4 + SQ5 for that component).
|
||||
- **Related Sub-question**: SQ1 (academic SOTA), SQ3+SQ4 (C2/C3 candidates), SQ5 (Jetson-on-Foundation-Model failure mode)
|
||||
|
||||
|
||||
### Source #30
|
||||
- **Title**: Raptor — GPS-Denied UAV Navigation & Coordinate Extraction (Vantor product page; Guide / Sync / Ace suite)
|
||||
- **Link**: https://www.vantor.com/product/mission-solutions/raptor/
|
||||
- **Tier**: L2 (vendor product spec; primary for the product itself, not for independent benchmark numbers)
|
||||
- **Publication Date**: live (accessed 2026-05-07; references Mar 2026 + Dec 2025 + Sep 2025 partner blog posts indicating active product line)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Defense / commercial / industrial UAV integrators
|
||||
- **Research Boundary Match**: **Full match** — vision-based aerial position software using existing camera + 3D terrain data, deployable on commodity hardware
|
||||
- **Summary**: Vantor Raptor product family: **Guide** (on-drone vision-based positioning, demonstrated <7 m absolute accuracy in all dimensions, day/night/low-altitude, runs on commodity HW); **Sync** (georegisters live drone video against 3D terrain in real time, <3 m coordinate extraction); **Ace** (laptop-side coordinate extraction at <3 m). Backbone: Vantor's "100 million-plus sq km of highly accurate 3D terrain data, regularly updated" (Vivid Terrain, 3 m accuracy). Inertial Labs partnership (VINS-integrated Raptor Guide). Use cases include joint multi-domain ops, large-scale autonomous delivery, search-and-rescue. **This is the closest production-grade commercial peer to the project's architecture (sat-basemap-as-service + on-drone vision).**
|
||||
- **Related Sub-question**: SQ1 (commercial), SQ3+SQ4 (commercial alternatives to building C2/C3 ourselves), SQ8 (basemap as a service vs offline cache)
|
||||
|
||||
|
||||
### Source #31
|
||||
- **Title**: Auterion successfully completes Artemis program to deliver long-range deep strike drone (press release)
|
||||
- **Link**: https://auterion.com/auterion-successfully-completes-artemis-program-to-deliver-long-range-deep-strike-drone/
|
||||
- **Tier**: L1 (official vendor press release)
|
||||
- **Publication Date**: 2025-10-15 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Defense-procurement; UAV-integration architects
|
||||
- **Research Boundary Match**: **Full match** — fixed-wing-class one-way attack drone with Ukraine-validated GPS-denied navigation; the system architecture is directly comparable
|
||||
- **Summary**: Auterion Artemis (DIU project, completed Oct 2025) = Shahed-style design developed in Ukraine; up to 1,000-mile range; up to 40 kg warhead; runs on Auterion Skynode N mission computer + Auterion Visual Navigation system + built-in terminal guidance. Government evaluators signed off after operational flight tests in Ukraine including ground launch, GPS and GPS-denied navigation, long-range transit, and terminal engagement. **Establishes that the integration pattern (companion-class autopilot + visual navigation + terminal guidance) is shipping at production scale to a US defense customer.** Open architecture, manufacturing in US/UA/DE.
|
||||
- **Related Sub-question**: SQ1
|
||||
|
||||
|
||||
### Source #32
|
||||
- **Title**: Bring AI and computer vision to small autonomous systems — Auterion Skynode S product page
|
||||
- **Link**: https://auterion.com/product/skynode-s
|
||||
- **Tier**: L2 (vendor product spec)
|
||||
- **Publication Date**: live (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Small-UAS integrators
|
||||
- **Research Boundary Match**: Full match (companion-class autopilot with NPU)
|
||||
- **Summary**: Auterion Skynode S = compact mission computer with **dedicated Neural Processing Unit** for AI / computer-vision applications on small UAS systems. Architecturally the same niche our Jetson Orin Nano Super sits in (companion compute + autopilot integration), but with Auterion's PX4 fork pre-integrated. Hardware/runtime envelope is comparable; the product establishes that this is a product category, not a one-off integration.
|
||||
- **Related Sub-question**: SQ1, SQ7 (alternate companion HW for adjacent context)
|
||||
|
||||
|
||||
### Source #33
|
||||
- **Title**: snktshrma/ngps_flight — Next-Generation Positioning System for ArduPilot (GSoC 2024)
|
||||
- **Link**: https://github.com/snktshrma/ngps_flight (sibling: https://github.com/snktshrma/ap_nongps)
|
||||
- **Tier**: L1 (open-source code repository, published GSoC project under ArduPilot organisation)
|
||||
- **Publication Date**: GSoC 2024 timeframe (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: GSoC 2024 prototype (research-grade, not production firmware)
|
||||
- **Target Audience**: ArduPilot integrators building visual-positioning companion stacks
|
||||
- **Research Boundary Match**: **Full match — closest open-source peer to our exact pipeline.** ArduPilot, downward-facing camera, satellite-image reference, deep-learning matching, fused with VIO, fed back to autopilot.
|
||||
- **Summary**: NGPS = ROS 2 + ArduPilot pipeline composed of three packages: **`ap_ngps_ros2`** (visual geo-localization at 1–2 Hz by matching live camera frames to georeferenced satellite imagery using **LightGlue + SuperPoint**); **`ap_ukf`** (Unscented Kalman Filter fusing NGPS absolute positions with VIO estimates); **`ap_vips`** (VIO providing relative pose). Output is fused odometry to ArduPilot's EKF via `VISION_POSITION_ESTIMATE` (per the related issue #23471 framing). **This is the architectural template** the project should explicitly compare against — same component split as our C1+C2+C3+C5+C8 stack.
|
||||
- Caveats: (a) GSoC prototype, not production-hardened; (b) uses `VISION_POSITION_ESTIMATE` which on AP requires EKF source set 2/3 with EK3_SRC*_POSXY=Vision; our SQ6 conclusion picked `GPS_INPUT` as primary AP path because it carries `horiz_accuracy` directly and supports source-set switching via `MAV_CMD_SET_EKF_SOURCE_SET` — must compare the trade-off in design phase; (c) no documented spoofing-defence integration; (d) no documented covariance-honesty contract.
|
||||
- **Related Sub-question**: SQ1 (closest open-source peer), SQ2 (canonical-pipeline confirmation), SQ3+SQ4 (architectural template for component selection), SQ6 (alternate AP transport: `VISION_POSITION_ESTIMATE` vs `GPS_INPUT`)
|
||||
|
||||
|
||||
### Source #34
|
||||
- **Title**: AerialExtreMatch — A Benchmark for Extreme-View Image Matching and Localization (project page + GitHub + Hugging Face dataset)
|
||||
- **Link**: https://xecades.github.io/AerialExtreMatch/ ; https://github.com/Xecades/AerialExtreMatch ; https://huggingface.co/datasets/Xecades/AerialExtreMatch-Localization
|
||||
- **Tier**: L1 (peer-reviewed benchmark with public dataset, code, model checkpoints; OpenReview submission)
|
||||
- **Publication Date**: 2025 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Academic + practitioner image-matching evaluators
|
||||
- **Research Boundary Match**: **Full match** for cross-source UAV-satellite image matching evaluation
|
||||
- **Summary**: 2025 benchmark with: 1.5 M synthetic train pairs (RGB+depth, diverse UAV/satellite viewpoints); ~30,000 evaluation pairs in 32 difficulty levels stratified by overlap (4 bins: <20/20-40/40-60/>60%), pitch difference (4 bins: 50–55, 55–60, 60–65, 65–70°), and scale (2 bins: 1-2×, >2×); a real-world UAV-localization split captured with DJI M300 RTK + H20T against UAV-derived orthomosaic/DSM AND lower-quality satellite maps. Evaluates 16 representative detector-based + detector-free image matching methods. **This is the academic benchmark our C2+C3 candidate selection must publish numbers against.**
|
||||
- **Related Sub-question**: SQ1 (academic landscape), SQ7 (datasets)
|
||||
|
||||
|
||||
### Source #35
|
||||
- **Title**: DARPA Fast Lightweight Autonomy (FLA) program page + Test-and-Evaluation review (arXiv 2504.08122)
|
||||
- **Link**: https://www.darpa.mil/research/programs/fast-lightweight-autonomy ; https://arxiv.org/abs/2504.08122
|
||||
- **Tier**: L1 (DARPA program page + 2025 academic review of program results)
|
||||
- **Publication Date**: program 2015–2018 (concluded); review 2025-04 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Foundational reference; review is current (within 18-month authority window)
|
||||
- **Target Audience**: Defense-program historians + indoor-low-altitude GPS-denied autonomy researchers
|
||||
- **Research Boundary Match**: **Partial — different regime.** FLA = small quadcopters at ≤20 m/s in cluttered indoor/outdoor with onboard sensing only, no satellite-tile basemap. Our project is fixed-wing, ~17 m/s, 1 km AGL, with sat-tile basemap.
|
||||
- **Summary**: Foundational US-defense lineage for GPS-denied autonomy (2015–2018, complete). Set the template for "small UAV + onboard sensors + onboard compute → autonomous obstacle-avoidance + navigation without datalink/GPS". Phase 1 in Florida 2017; Phase 2 in Georgia 2018. The 2025 retrospective (arXiv 2504.08122) reviews FLA's testing methodology and Phase 1 results. Companion 2025 USAF SBIR Phase II solicitation (Sweetspot ID `7946c818-409f-5b31-8f06-554466071d83`) is requesting visual-position-and-navigation capability for sUAS in GPS-denied environments — the regulatory tailwind is now active.
|
||||
- **Related Sub-question**: SQ1 (defense-program lineage)
|
||||
|
||||
|
||||
### Source #36
|
||||
- **Title**: DSMAC / TERCOM lineage — DTIC ADA315439 (Scene Matching Missile Guidance Technologies) + Wikipedia / SPIE references
|
||||
- **Link**: https://apps.dtic.mil/sti/tr/pdf/ADA315439.pdf ; https://en.wikipedia.org/wiki/DSMAC ; https://www.spiedigitallibrary.org/conference-proceedings-of-spie/0238/1/Terrain-Contour-Matching-TERCOM-A-Cruise-Missile-Guidance-Aid/10.1117/12.959127.short
|
||||
- **Tier**: L1 (DTIC unclassified technical report) + L2 (encyclopedia/SPIE proceedings)
|
||||
- **Publication Date**: DTIC: 1996; SPIE: 1980; Wikipedia: live
|
||||
- **Timeliness Status**: Foundational baseline (no time window per Step 0.5 — established classical algorithms)
|
||||
- **Target Audience**: Cruise-missile-class designers; analogues for downward-vision navigation
|
||||
- **Research Boundary Match**: **Partial — different regime** (cruise missile, terminal guidance). Architectural pattern (pre-cached scene reference + downward camera + correlation matching) is the direct ancestor of our C3 pipeline.
|
||||
- **Summary**: DSMAC = electro-optical camera correlated against pre-stored reference scenes (often from satellite reconnaissance), achieving 3–10 m terminal accuracy. Tomahawk: TERCOM (radar altimeter + DEM) for mid-flight; DSMAC for terminal. CEP without DSMAC: ~30 m; with DSMAC: "only meters". Gulf War 1991: >80% of 280 launched Tomahawks hit target. **Establishes that downward-vision-against-pre-stored-imagery is a 40+ year-old well-characterised technique class with documented accuracy bounds; our project's claim of <500 m / 99.9% reliability is achievable in the same technique class.**
|
||||
- **Related Sub-question**: SQ1 (lineage), SQ8 (baseline accuracy expectations)
|
||||
|
||||
|
||||
### Source #37
|
||||
- **Title**: Electronic Warfare in Ukraine: The Invisible Battle — Ukraine War Analytics
|
||||
- **Link**: https://ukraine-war-analytics.com/analysis/electronic-warfare-ukraine.html
|
||||
- **Tier**: L3 (analytical aggregator; primary-source numbers cite vendor / OSINT reports)
|
||||
- **Publication Date**: live (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid (operational-context reference)
|
||||
- **Target Audience**: Ukraine-deployment practitioners
|
||||
- **Research Boundary Match**: Full match (operational geography, threat environment)
|
||||
- **Summary**: Operational-context anchor: Russian EW systems including Pole-21 GPS jammers (25+ km range) plus spoofing capabilities have driven ~70% of small-tactical-UAV losses to EW across the conflict. Twist Robotics' OSCAR cites the same approximate number (~75% of small tactical UAV losses to EW at the front per Source #25). **Confirms the demand-side number is consistent across two independent reporting chains.**
|
||||
- **Related Sub-question**: SQ1 (Ukraine practitioner perspective)
|
||||
|
||||
---
|
||||
|
||||
## SQ2 — Canonical pipeline decomposition
|
||||
@@ -0,0 +1,74 @@
|
||||
# Source Registry — SQ2 — Canonical pipeline decomposition
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> This file replaces a section of the previous monolithic `01_source_registry.md`. See `00_summary.md` for the full category index. Investigation order is tracked in `../00_question_decomposition.md` and the cross-category Investigation Status table in `00_summary.md`.
|
||||
|
||||
---
|
||||
|
||||
### Source #38
|
||||
- **Title**: Visual Place Recognition for Aerial Imagery: A Survey (Moskalenko, Kornilova, Ferrer — Skoltech)
|
||||
- **Link**: https://arxiv.org/abs/2406.00885 (v2)
|
||||
- **Tier**: L1 (peer-reviewed survey, accepted in Robotics and Autonomous Systems; companion benchmark code: https://github.com/prime-slam/aero-vloc)
|
||||
- **Publication Date**: arXiv 2024-06; v2 update through 2024
|
||||
- **Timeliness Status**: Currently valid (within 18-month authority window for established surveys; specific candidate latency numbers will need cross-validation against newer Jetson-class hardware reports)
|
||||
- **Target Audience**: Aerial-VPR practitioners + UAV navigation system architects
|
||||
- **Research Boundary Match**: **Full match** for the offline-cache visual geo-localization decomposition (aerial-nadir UAV vs. satellite tile basemap)
|
||||
- **Summary**: Authoritative two-stage pipeline definition (verbatim): "Visual geolocalization can be implemented through various methods, typically relying on a pre-built database of images with known locations. This approach generally involves two stages: **global localization (or Visual Place Recognition, VPR) and local alignment**. Global localization involves identifying the nearest frame from the database (Image Retrieval), while local alignment determines the precise position using the selected frame." Re-ranking is treated as an integral sub-stage of VPR for aerial data because of agricultural/urban grid repetition. Local alignment = SuperPoint/keypoint detector → LightGlue/SuperGlue/SelaVPR matcher → cv2.findHomography → cv2.perspectiveTransform → Web-Mercator coordinate conversion. **Practitioner-critical runtime numbers (RTX 3090, NOT Jetson)**: AnyLoc descriptor calculation = 0.37–0.84 s/frame (huge ViT-G DINOv2); MixVPR / SALAD = 0.05–0.20 s; SelaVPR = 0.04 s; SuperGlue re-rank = 15–25 s on top-100 candidates; LightGlue re-rank = ~1 s; SelaVPR re-rank = <0.1 s. Memory: AnyLoc descriptors = 2.3–13.9 GB for 4–7k tiles; SelaVPR = <0.2 GB. Final commentary: "While our methodology alone may not provide comprehensive robustness, it can be effectively augmented with additional sensors, such as inertial measurement units (IMUs). This integration enhances its utility for Visual Inertial Odometry (VIO) and Simultaneous Localization and Mapping (SLAM) systems, particularly for periodic location refinement and loop closure tasks. Additionally, our methodology could serve as a dependable emergency localization fallback in the event of an unexpected GNSS signal loss." → **Validates the project's IMU/VIO + sat-anchor architecture as the canonical extension of the survey's two-stage core.**
|
||||
- **Related Sub-question**: SQ2 (canonical decomposition), SQ3+SQ4 (C2/C3 candidate latency budgets), SQ5 (foundation-model-on-Jetson failure mode)
|
||||
|
||||
|
||||
### Source #39
|
||||
- **Title**: Cross-View Geo-Localization: A Survey (Durgam, Paheding, Dhiman, Devabhaktuni — U. Maine / Fairfield / ISU)
|
||||
- **Link**: https://arxiv.org/abs/2406.09722 (v1)
|
||||
- **Tier**: L1 (peer-style preprint, journal-bound — Expert Systems with Applications)
|
||||
- **Publication Date**: arXiv 2024-06
|
||||
- **Timeliness Status**: Currently valid (≤18 months for survey-of-deep-learning architectures)
|
||||
- **Target Audience**: Cross-view (ground↔aerial) geo-localization researchers; partial overlap with our aerial↔satellite pipeline
|
||||
- **Research Boundary Match**: **Partial — different cross-view setup** (the survey focuses on ground panorama → aerial overhead; ours is aerial nadir → satellite ortho). The pipeline-shape lessons transfer; the polar-transform / Siamese-network / GAN-based view-synthesis lessons do NOT directly apply because our two views are both top-down.
|
||||
- **Summary**: Confirms the canonical pipeline decomposition (feature extraction → cross-view matching → similarity-driven retrieval) is the dominant pattern across 2015–2024 SOTA. Establishes the historical lineage: pixel-wise (Sheikh 2003) → feature-based (Lin 2013) → CNN/triplet-loss (Tian 2017) → Siamese+GAN (Hu 2018) → polar-transform (Shi 2019) → CosPlace/EigenPlaces (2022–2023) → DINOv2-class (AnyLoc 2023) → Transformer-only (TransGeo 2022, MGTL 2022) → multi-method fusion (2023+). Backbone comparison table establishes that ViT/DINOv2 is the current SOTA backbone; ResNet-class is the established production baseline; SIFT/SURF/PHOW remain the handcrafted baseline. **Confirms our component-area split (C2 VPR + C3 cross-domain matching) is canonical and matches the survey's two-axis organization (backbone × matching strategy).**
|
||||
- **Related Sub-question**: SQ2 (decomposition lineage), SQ3+SQ4 (C2 candidate landscape)
|
||||
|
||||
|
||||
### Source #40
|
||||
- **Title**: OrthoLoC: UAV 6-DoF Localization and Calibration Using Orthographic Geodata (Dhaouadi, Marin, Meier, Kaiser, Cremers — DeepScenario / TU Munich / MCML)
|
||||
- **Link**: https://arxiv.org/abs/2509.18350 ; project page https://deepscenario.github.io/OrthoLoC
|
||||
- **Tier**: L1 (peer-style preprint with public dataset, code, model checkpoints; 16,425 UAV images Germany+US, full 6-DoF ground truth)
|
||||
- **Publication Date**: arXiv 2025-09 (within 6-month critical-novelty window)
|
||||
- **Timeliness Status**: Currently valid (within 6-month critical-novelty window for SOTA aerial-localization claims)
|
||||
- **Target Audience**: UAV-localization implementers + system architects building on Digital Orthophotos (DOP) + Digital Surface Models (DSM)
|
||||
- **Research Boundary Match**: **Full match — direct paradigm match** to our project: "lightweight orthographic representations" instead of 3D meshes; "increasingly accessible through free releases by governmental authorities"; "no internet connection or GNSS/GPS support" — exactly the project's constraint envelope.
|
||||
- **Summary**: **Most directly applicable SQ2 source.** Defines the 6-DoF localization pipeline using 2.5D geodata: (1) match query UAV image against DOP (orthophoto raster) using state-of-the-art matchers; (2) lift each 2D match in the DOP to 3D using the corresponding DSM elevation; (3) PnP+RANSAC (RANSAC-EPnP, 5-pixel inlier threshold) → initial pose; (4) Levenberg-Marquardt joint refinement of intrinsics + extrinsics; (5) **AdHoP refinement**: estimate homography from initial 2D-2D correspondences via DLT+RANSAC, warp the DOP to better match the query's perspective, re-match, map back via H⁻¹, lift to 3D, refine pose; accept refinement only if reprojection error decreases. **Quantitative results** on 16.4k images, 47 locations: best matcher = GIM+DKM achieves 75.4% recall at 1m-1° threshold (sparse SP+SG = 64.4%, sparse SP+LG = 64.2%, MASt3R = 63.5%, RoMa+AdHoP = 54.6%, XFeat*+AdHoP = 59.8%; LoFTR / eLoFTR / XoFTR all <23% recall). AdHoP yields ~30% average matching improvement, ~20% translation/rotation error reduction; for previously-underperforming methods (XFeat* → 95% matching improvement; DKM → 63% translation reduction; RoMa → 1m-1° recall +23%). **Performance factors** explicitly characterized: (a) **cross-domain DOPs (visual gap only) cause ~3× translation error increase** even on best method; (b) **cross-domain DOPs+DSMs (visual + structural gap) cause ~7× translation error increase** (0.16 m → 1.12 m for GIM+DKM+AdHoP) — **this is exactly the war-zone scene-change scenario AC-3.x covers**; (c) **20% covisibility floor** between query and reference; below it localization fails; (d) **Calibration is fundamentally ambiguous** between focal length and translation → camera intrinsics MUST be calibrated upstream, not jointly optimized in flight. (e) Resolution: scaling images to 30% of original (~300 px) still works; geodata at 13 m/pixel is the floor, with degradation below.
|
||||
- **Related Sub-question**: SQ2 (canonical pipeline + AdHoP refinement loop), SQ3+SQ4 (C3 matcher candidate ranks), SQ5 (war-zone scene-change failure mode), SQ8 (covisibility safety gate)
|
||||
|
||||
|
||||
### Source #41
|
||||
- **Title**: Exploring the best way for UAV visual localization under Low-altitude Multi-view Observation Condition: a Benchmark — AnyVisLoc (Ye, Teng, Chen, Li, Liu, Yu, Tan — NUDT / Macao Polytechnic)
|
||||
- **Link**: https://arxiv.org/abs/2503.10692 ; benchmark code https://github.com/UAV-AVL/Benchmark
|
||||
- **Tier**: L1 (peer-style preprint with public 18,000-image dataset across 15 Chinese cities, multi-pitch / multi-altitude / multi-scene, with both aerial-photogrammetry AND satellite reference maps)
|
||||
- **Publication Date**: arXiv 2025-03 (within 6-month critical-novelty window)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: Aerial AVL practitioners; UAV-system designers facing pitch/altitude/yaw uncertainty
|
||||
- **Research Boundary Match**: **Partial — different altitude regime** (the benchmark covers 30–300 m AGL, ours is ~1 km AGL); pitch range is 20–90° (ours is mostly nadir, ~80–90°). Lessons on the **pipeline structure, retrieval-vs-matching trade-offs, sensor-prior noise tolerance, and aerial-vs-satellite reference-map gap** transfer directly.
|
||||
- **Summary**: Independently confirms the SAME pipeline as Source #40: image retrieval (rough position) → image matching (2D-2D) → DSM-lift to 3D → PnP+RANSAC. Best baseline = CAMP (retrieval) + RoMa (dense matcher) + Top-N re-rank → 74.1% A@5m on aerial photogrammetry map, 18.5% A@5m on satellite map (ALOS 30m DSM). **Critical AC-quantitative findings**: (a) **Aerial map vs satellite map**: 4× accuracy gap at A@5m (74.1% vs 18.5%) — driven by satellite-DSM coarseness (ALOS 30m vs aerial 0.94m) and modality difference. **Direct relevance**: project's offline cache is satellite tiles ≥0.5 m/px without DSM; this places us between the two data points (better than ALOS 30m, worse than aerial photogrammetry) — exact accuracy must be re-established once tile resolution is pinned. (b) **Yaw prior noise**: σ ≤ 5° → no impact; σ = 10° → 1.9% A@5m drop; σ = 30° → 4.1% drop; σ = 50° → 13.7% drop; σ = 60° → 25.7% drop. **Implication for project's C1+C5+IMU**: companion-side yaw estimate must hold σ < 10°. (c) **Pitch prior noise**: σ < 5° → no impact; σ ≥ 7° causes ~1–5% drops. (d) **Pitch angle**: smaller pitch (more oblique) → lower accuracy; nadir is best. Project's nadir-fixed camera at 1 km AGL is consistent with the benchmark's most-favourable regime. (e) **Sparse vs dense matchers**: SP+LightGlue+GIM+k2s = 75.4% A@10m at 105 ms/frame; RoMa = 81.3% A@10m at 659 ms/frame. **Implication for project's C7 Jetson runtime**: dense matchers ~6× more accurate but ~6× slower → SP+LightGlue-class is the production sweet spot under our 400 ms budget. (f) **Re-ranking strategy**: Top-N re-rank by inlier count = best accuracy/cost trade-off (62.2% A@5m at 0.8 s/frame on RTX 3090). Match-without-retrieval = catastrophic (34.3% A@5m, search-space too large).
|
||||
- **Related Sub-question**: SQ2 (pipeline + sensor-prior tolerance), SQ3+SQ4 (C2 retrieval-vs-matcher trade-offs, C5 IMU prior contract), SQ5 (war-zone reference-map staleness failure mode), SQ7 (aerial-vs-satellite reference benchmarks)
|
||||
|
||||
|
||||
### Source #42
|
||||
- **Title**: Survey on absolute visual localization techniques for low-altitude unmanned aerial vehicles (Ye, Chen, Teng, Li, Yang, Song, Yu — NUDT, College of Aerospace Science)
|
||||
- **Link**: https://www.sciopen.com/article/10.11887/j.issn.1001-2486.25120033 ; DOI 10.11887/j.issn.1001-2486.25120033
|
||||
- **Tier**: L1 (peer-reviewed Chinese journal — Journal of National University of Defense Technology, vol 48 issue 2, 2026; same lab as Source #41 with overlapping authorship — confirmed cross-validation, not duplicative)
|
||||
- **Publication Date**: 2026-04-01 (within 6-month critical-novelty window)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: UAV-system architects + Chinese-defense-research community
|
||||
- **Research Boundary Match**: **Full match** (low-altitude UAV AVL is the survey's exact subject)
|
||||
- **Summary**: Survey-level confirmation of the canonical "**retrieval-matching-pose estimation**" hierarchical framework. Verbatim claim: "the hierarchical framework balances search efficiency, positioning accuracy, and scene generalization, becoming a robust technical path for low-altitude long-endurance absolute localization." Compares the framework against alternatives that are explicitly rejected: (a) relative visual localization (cumulative errors — VIO/SLAM only); (b) end-to-end direct localization (poor generalization); (c) map-free localization (scene-dependent). Sub-component evolution per stage: (a) retrieval = template-matching (SAD/SSD/NCC) → BoW/VLAD → deep-learning (annular/dense feature segmentation, contrastive InfoNCE, self-supervised); (b) matching = SIFT/SURF/ORB → SuperPoint+LightGlue/RoMa (sparse / semi-dense / dense); (c) pose estimation = PnP variants + RANSAC + IMU prior fusion. **Identifies four open challenges** that align with project risks: (i) cross-domain generalization (war-zone scene change); (ii) real-time inference on edge platforms (Jetson); (iii) robustness to complex environments (cropland, snow, low texture); (iv) high-quality datasets (the same gap our project's AC-NEW-7 / cache provisioning works around). **Lightweight-model-design-for-edge-deployment is named as a primary future-research direction** — directly validates project's Jetson Orin Nano constraint as a recognized field-level challenge, not a project-specific oddity.
|
||||
- **Related Sub-question**: SQ2 (framework canonicalness), SQ3+SQ4 (per-component evolution), SQ5 (named open challenges align with project risks)
|
||||
|
||||
---
|
||||
|
||||
## SQ3+SQ4 / C1 (Visual / Visual-Inertial Odometry) — Candidate enumeration
|
||||
@@ -0,0 +1,320 @@
|
||||
# Source Registry — SQ6 — ArduPilot Plane vs iNav external positioning
|
||||
|
||||
> Mode A Phase 2 — engine Step 2 (Source Tiering & Exhaustive Web Investigation).
|
||||
> Critical-novelty sensitivity per Step 0.5 in `../00_question_decomposition.md`. Time windows applied:
|
||||
> - **Lead-candidate / SOTA claims**: prefer sources within last 6 months; up to 18 months if older is the official authority.
|
||||
> - **Library/SDK API behaviour**: must reflect the currently shipped version at search time (`context7` mandatory per lead candidate).
|
||||
> - **Established baselines** (KLT, RANSAC, EKF, ORB, SIFT, GTSAM): no time window.
|
||||
>
|
||||
> This file replaces a section of the previous monolithic `01_source_registry.md`. See `00_summary.md` for the full category index. Investigation order is tracked in `../00_question_decomposition.md` and the cross-category Investigation Status table in `00_summary.md`.
|
||||
|
||||
---
|
||||
|
||||
### Source #1
|
||||
- **Title**: Non-GPS Navigation — Plane documentation
|
||||
- **Link**: https://ardupilot.org/plane/docs/common-non-gps-navigation-landing-page.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: live docs (current ArduPilot stable, accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: ArduPilot 4.7+ (persistent origin storage); applies to current Plane stable
|
||||
- **Target Audience**: ArduPilot Plane operators / developers
|
||||
- **Research Boundary Match**: Full match (fixed-wing, ArduPilot Plane is in scope)
|
||||
- **Summary**: Lists supported non-GPS navigation systems for Plane. Notes that boards <1MB flash still support `GPS_INPUT` even when they cannot run other non-GPS messages. Notes that Plane (non-VTOL) is generally not applicable for low-altitude non-GPS — but `GPS_INPUT` as an external GPS replacement is not constrained by that note.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #2
|
||||
- **Title**: GPS / Non-GPS Transitions — Plane documentation
|
||||
- **Link**: https://ardupilot.org/plane/docs/common-non-gps-to-gps.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: live docs (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: EKF3 (default since AP 4.0+)
|
||||
- **Target Audience**: ArduPilot operators using mixed GPS / non-GPS sources
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Documents the EKF3 source-set mechanism (`EK3_SRC1..3_POSXY/VELXY/POSZ/VELZ/YAW`), three source sets, RC aux switch (option 90 "EKF Pos Source"), `MAV_CMD_SET_EKF_SOURCE_SET`, Lua-script driven switching. Explicitly named messages for non-GPS path: ExternalNav (option 6). GPS_INPUT is treated as a GPS source (set 1).
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #3
|
||||
- **Title**: EKF Source Selection and Switching — Plane documentation
|
||||
- **Link**: https://ardupilot.org/plane/docs/common-ekf-sources.html
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: live docs (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: EKF3 stable
|
||||
- **Target Audience**: ArduPilot operators / developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative parameter reference for `EK3_SRCx_*` (POSXY/VELXY/POSZ/VELZ/YAW). Important caveat: "Ground stations or companion computers may set the source by sending a `MAV_CMD_SET_EKF_SOURCE_SET` mavlink command **but no GCSs are currently known to implement this**." Source-set switching from companion is supported by AP, not by stock GCS UI. Mentions ExternalNAV/OpticalFlow transition options via `EK3_SRC_OPTIONS` bit 1.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #4
|
||||
- **Title**: ArduPilot AP_GPS_MAV.cpp (master)
|
||||
- **Link**: https://raw.githubusercontent.com/ArduPilot/ardupilot/master/libraries/AP_GPS/AP_GPS_MAV.cpp
|
||||
- **Tier**: L1 (source code)
|
||||
- **Publication Date**: master HEAD (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: master branch
|
||||
- **Target Audience**: ArduPilot developers, integrators of external GPS via MAVLink
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative implementation of `MAVLINK_MSG_ID_GPS_INPUT` ingestion into AP_GPS state. Decodes lat/lon/alt, hdop/vdop, velocity (vn/ve/vd), speed/horizontal/vertical accuracy, yaw. Honors `gps_id` (multi-GPS instance), `ignore_flags` bitmask (ALT, HDOP, VDOP, VEL_HORIZ, VEL_VERT, SPEED_ACCURACY, HORIZONTAL_ACCURACY, VERTICAL_ACCURACY). Requires `fix_type ≥ 3` and `time_week > 0` for jitter-corrected timestamping. Yaw uses `0` as "not provided" sentinel. Only `GPS_INPUT` is handled by this driver — `VISION_POSITION_ESTIMATE` / `ODOMETRY` go via the external-nav driver, not AP_GPS_MAV.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #5
|
||||
- **Title**: ArduPilot PR #28750 — AP_NavEKF3: added two more EK3_OPTION bits (GPS-denied testing)
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/pull/28750
|
||||
- **Tier**: L2 (development PR, ArduPilot core team)
|
||||
- **Publication Date**: 2024 (accessed via search 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: master / pending stable branch propagation
|
||||
- **Target Audience**: ArduPilot developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Adds new `EK3_OPTION` bits to allow easier GPS-denied testing of EKF3, including an aux-switch / MAVLink command path to disable GPS use. Confirms ongoing 2024-2025 work on GPS-denied robustness.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #6
|
||||
- **Title**: ArduPilot Issue #15859 — EKF3: improve source switching (GPS<->NonGPS)
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/issues/15859
|
||||
- **Tier**: L4 (issue tracker — open enhancement list)
|
||||
- **Publication Date**: ongoing (long-running issue, accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid (still open per dev docs reference)
|
||||
- **Target Audience**: ArduPilot developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative list of planned improvements for source-switching. Linked from the L1 GPS-Non-GPS Transitions page. Indicates current source switching has known rough edges acknowledged by the core team.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #7
|
||||
- **Title**: ArduPilot Issue #27193 — EK3 Source Switching wrong frame for GUIDED commands SOLVED
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/issues/27193
|
||||
- **Tier**: L4 (issue tracker, resolved)
|
||||
- **Publication Date**: 2024 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Reference only (resolved as user-config)
|
||||
- **Target Audience**: ArduPilot operators using GPS↔Vision source switching
|
||||
- **Research Boundary Match**: Partial overlap (Copter context but the bug was in shared SET_POSITION_TARGET_GLOBAL_INT path)
|
||||
- **Summary**: Documented frame-interpretation issue when companion switches source set 1 (GPS) → set 3 (VISION_POSITION_ESTIMATES) and back. Resolved as configuration not code, but illustrates the kind of edge case to validate in SITL for AC-NEW-2 promotion.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #8
|
||||
- **Title**: ArduPilot Issue #23485 — AP_NavEKF3: support fusing only External Nav Velocities (without position)
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/issues/23485
|
||||
- **Tier**: L4 (open enhancement)
|
||||
- **Publication Date**: ongoing (open as of accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: ArduPilot developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Confirms current limitation: ODOMETRY without position causes position-estimate timeout / failsafe. Implies the project's `visual_propagated` path (VO without satellite anchor) cannot be expressed as ODOMETRY-velocity-only on current AP — must be sent as full GPS_INPUT with widened covariance.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #9
|
||||
- **Title**: iNavFlight/inav — telemetry/mavlink.c (master, processMAVLinkIncomingTelemetry)
|
||||
- **Link**: https://github.com/iNavFlight/inav/blob/master/src/main/telemetry/mavlink.c
|
||||
- **Tier**: L1 (source code, authoritative)
|
||||
- **Publication Date**: master HEAD (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav master (post-9.0)
|
||||
- **Target Audience**: iNav developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative inbound MAVLink switch (lines ~1334–1390). Handles only: HEARTBEAT, PARAM_REQUEST_LIST (stub), MISSION_CLEAR_ALL, MISSION_COUNT, MISSION_ITEM, MISSION_REQUEST_LIST, MISSION_REQUEST, COMMAND_INT (only `MAV_CMD_DO_REPOSITION`), RC_CHANNELS_OVERRIDE, ADSB_VEHICLE, RADIO_STATUS. **No `GPS_INPUT`, no `VISION_POSITION_ESTIMATE`, no `ODOMETRY`, no `GLOBAL_POSITION_INT`, no `GPS_RAW_INT`** are accepted as inputs. Wiki page (Source #10) confirms.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #10
|
||||
- **Title**: iNav Wiki — MAVLink (frogmane edited 2025-12-11)
|
||||
- **Link**: https://github.com/iNavFlight/inav/wiki/Mavlink
|
||||
- **Tier**: L1 (project wiki)
|
||||
- **Publication Date**: 2025-12-11
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav 8.0 / 9.0 era
|
||||
- **Target Audience**: iNav users / integrators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative inbound/outbound MAVLink message lists. "Limited command support: Commands that are not implemented are ignored." Explicitly enumerates the supported incoming list (matches Source #9). Confirms iNav MAVLink is "intended primarily for simple telemetry and operation" and "not 100% compatible".
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #11
|
||||
- **Title**: iNav Wiki — GPS and Compass setup
|
||||
- **Link**: https://github.com/iNavFlight/inav/wiki/GPS-and-Compass-setup
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: live wiki (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav 7.0+ (UBX-only); 9.0 requires UBX protocol ≥15.00
|
||||
- **Target Audience**: iNav operators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: From iNav 7.0 NMEA was removed; only UBX is supported. Recommends u-blox M8/M9/M10 with protocol ≥15.00. Sets up the constraint for any UBX-emulation path the companion would take.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #12
|
||||
- **Title**: iNavFlight/inav docs/development/msp/README.md (MSP message reference)
|
||||
- **Link**: https://github.com/iNavFlight/inav/blob/master/docs/development/msp/README.md
|
||||
- **Tier**: L1 (project docs)
|
||||
- **Publication Date**: live (master, accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav master
|
||||
- **Target Audience**: iNav developers / integrators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative spec for `MSP_SET_RAW_GPS (201)` and `MSP2_SENSOR_GPS (7939)`. `MSP_SET_RAW_GPS` is 14-byte, lossy (no covariance, no per-axis velocity, altitude in meters with cm internal mismatch — bug fixed in 5.0.0 per issue #8336). `MSP2_SENSOR_GPS` is the newer plugin-style message with `hPosAccuracy`/`vPosAccuracy`/`hVelAccuracy` (mm and cm/s), `hdop`, NED velocity components, `trueYaw`, GPS week + time-of-week, fix type, satellite count. Requires `USE_GPS_PROTO_MSP` build flag and routes through `mspGPSReceiveNewData()` (the GPS_PROVIDER_MSP driver path).
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #13
|
||||
- **Title**: iNavFlight/inav src/main/io/gps.c + src/main/target/common.h (master)
|
||||
- **Link**: https://github.com/iNavFlight/inav/blob/master/src/main/target/common.h
|
||||
- **Tier**: L1 (source code)
|
||||
- **Publication Date**: master (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: master
|
||||
- **Target Audience**: iNav developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: `USE_GPS_PROTO_MSP` is enabled by default in the common target configuration; on default builds the MSP GPS provider (`GPS_PROVIDER_MSP`) is registered with `gpsRestartMSP` / `gpsHandleMSP`. Confirms the MSP2_SENSOR_GPS path is reachable on stock iNav firmware without custom builds.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #14
|
||||
- **Title**: iNav Issue #10141 — dual GPS support
|
||||
- **Link**: https://github.com/iNavFlight/inav/issues/10141
|
||||
- **Tier**: L4 (open feature request)
|
||||
- **Publication Date**: ongoing (open as of accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: iNav users
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Confirms iNav does **not** support dual-GPS / primary-secondary failover. Open enhancement; no implementation in 8.0 / 9.0. Architectural implication: companion must be the sole GPS source for iNav (not a backup to a real GPS connected directly to FC).
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #15
|
||||
- **Title**: iNav docs/GPS_fix_estimation.md (master)
|
||||
- **Link**: https://github.com/iNavFlight/inav/blob/master/docs/GPS_fix_estimation.md
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: live (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav 8.0+
|
||||
- **Target Audience**: iNav fixed-wing operators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: iNav's internal dead-reckoning ("GPS fix estimation") for fixed-wing. Uses gyro/accel/baro/(mag/pitot). RTH-only intent. **Explicitly states: "Not a solution for GPS spoofing (GPS output is not validated in INAV)"** — iNav has no internal anti-spoofing, so anti-spoofing is fully the companion's responsibility. Two settings: `inav_allow_gps_fix_estimation` (RTH-with-no-GPS) and `inav_allow_dead_reckoning` (short-outage tolerance) — both default OFF. `failsafe_gps_fix_estimation_delay` controls mission-vs-RTH tradeoff (default 7 s).
|
||||
- **Related Sub-question**: SQ6 (dead-reckoning fallback) + SQ8 (anti-spoofing implication)
|
||||
|
||||
|
||||
### Source #16
|
||||
- **Title**: iNav docs/Settings.md (master)
|
||||
- **Link**: https://github.com/iNavFlight/inav/blob/master/docs/Settings.md
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: master (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav master
|
||||
- **Target Audience**: iNav operators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Authoritative parameter list. Confirms `inav_allow_dead_reckoning` (line 2081, default OFF) ≠ `inav_allow_gps_fix_estimation` (line 2091, default OFF). The two settings address different scenarios. `failsafe_gps_fix_estimation_delay` (line 1041, default 7 s) governs mission-abort timing.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #17
|
||||
- **Title**: iNav Issue #10588 — Weird behaviour in DeadReckoning mode while GPS outage is not constant
|
||||
- **Link**: https://github.com/iNavFlight/inav/issues/10588
|
||||
- **Tier**: L4 (open issue, 2025)
|
||||
- **Publication Date**: 2025
|
||||
- **Timeliness Status**: Currently valid (open)
|
||||
- **Target Audience**: iNav operators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Documented stability bug: intermittent GPS outages cause porpoising and motor bursts in dead-reckoning. Cited recommendation: "GPS should be rejected if providing erroneous coordinates rather than no fix." Risk for AC-NEW-8 (visual blackout + spoofed GPS) on iNav: do NOT rely on iNav's dead-reckoning for the spoof-active failsafe path; companion must actively suppress its own MSP feed and accept that iNav may misbehave during the gap. Better: continue feeding companion-IMU-propagated position with growing covariance via MSP2_SENSOR_GPS so iNav never enters its dead-reckoning state.
|
||||
- **Related Sub-question**: SQ6 + AC-NEW-8 design implication
|
||||
|
||||
|
||||
### Source #18
|
||||
- **Title**: iNav Release 8.0.0 (highlights, Dec 2024)
|
||||
- **Link**: https://github.com/iNavFlight/inav/releases/tag/8.0.0
|
||||
- **Tier**: L1 (project release notes)
|
||||
- **Publication Date**: late 2024 / early 2025
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav 8.0
|
||||
- **Target Audience**: iNav users
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Introduces fixed-wing GPS fix estimation (dead reckoning RTH-only) — the milestone for #8347. No new external-positioning inbound MAVLink in 8.0. Confirms iNav's 2024–2025 trajectory has not added a `GPS_INPUT`-equivalent inbound interface.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #19
|
||||
- **Title**: iNav Release 9.0.0 / 9.0.1 + 9.0.0 Release Notes wiki
|
||||
- **Link**: https://github.com/iNavFlight/inav/wiki/9.0.0-Release-Notes
|
||||
- **Tier**: L1
|
||||
- **Publication Date**: 2025-2026
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: iNav 9.0.x
|
||||
- **Target Audience**: iNav users
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: New in 9.0: pitot APA/TPA, position estimator improvements, MSP_REBOOT DFU, GCS NAV via `COMMAND_INT` `MAV_CMD_DO_REPOSITION`. **No** new external-positioning inbound MAVLink. UBX <15.00 dropped. Confirms iNav 9.x continues the same external-positioning architecture as 8.x.
|
||||
- **Related Sub-question**: SQ6
|
||||
|
||||
|
||||
### Source #20
|
||||
- **Title**: MAVLink common message set — GPS_RAW_INT (24)
|
||||
- **Link**: https://mavlink.io/en/messages/common.html
|
||||
- **Tier**: L1 (MAVLink spec, live)
|
||||
- **Publication Date**: live (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: MAVLink common, current
|
||||
- **Target Audience**: MAVLink integrators
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Current published `GPS_RAW_INT` extension fields: `alt_ellipsoid`, `h_acc` (mm), `v_acc` (mm), `vel_acc` (mm/s), `hdg_acc` (degE5), `yaw` (cdeg). **No spoofing/jamming/integrity bitfield is present in `GPS_RAW_INT` at the time of access**, despite PR #2110 having been merged for spoofing/integrity reporting. Spoofing/integrity may live in a separate message (`GPS_INTEGRITY` or similar — to be verified in SQ8). For now, spoof-detection signals available to companion from FC are limited at the message-shape level; FC-side textual signals (`STATUSTEXT`) and `NAMED_VALUE_INT` are the documented practical path.
|
||||
- **Related Sub-question**: SQ6 + SQ8
|
||||
|
||||
|
||||
### Source #21
|
||||
- **Title**: MAVLink PR #2110 — gps: add status and integrity information
|
||||
- **Link**: https://github.com/mavlink/mavlink/pull/2110
|
||||
- **Tier**: L2 (protocol PR with cross-project sign-off)
|
||||
- **Publication Date**: merged (accessed via search 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: MAVLink common
|
||||
- **Target Audience**: MAVLink integrators across PX4 / ArduPilot / QGC / Mission Planner
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Adds GNSS status / integrity reporting (jamming/spoofing/error) at the protocol level. Cross-project sign-off across PX4, ArduPilot, QGC, Mission Planner. Field-level breakdown to be cross-checked in SQ8 against the dialect XML — current `common.html` does not show those fields inside `GPS_RAW_INT` itself, suggesting they live in a sibling message (likely `GPS_INTEGRITY` or `GPS_STATUS_EXT`).
|
||||
- **Related Sub-question**: SQ6 → defer to SQ8 for the precise message name and field set ArduPilot uses to expose spoofing.
|
||||
|
||||
|
||||
### Source #22
|
||||
- **Title**: AirDroper — GNSS Spoofing Filter (companion device, MAVLink2 NAMED_VALUE_INT pattern)
|
||||
- **Link**: https://gps.airdroper.org/
|
||||
- **Tier**: L3 (vendor product page; design pattern reference, not protocol authority)
|
||||
- **Publication Date**: live (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Target Audience**: ArduPilot integrators considering anti-spoofing
|
||||
- **Research Boundary Match**: Reference only (vendor's specific algorithm not relevant; the integration pattern is)
|
||||
- **Summary**: Establishes a precedent that "companion-runs-spoofing-detection → publishes confidence to GCS as MAVLink2 `NAMED_VALUE_INT`, logged to dataflash" is a real-world integration pattern with ArduPilot, not novel to this project. Useful for SQ8.
|
||||
- **Related Sub-question**: SQ8 (referenced from SQ6)
|
||||
|
||||
|
||||
### Source #23
|
||||
- **Title**: ArduPilot PR #24135 — Add option to make EKF3 more robust to bad IMU and lagged GPS data
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/pull/24135
|
||||
- **Tier**: L2 (development PR)
|
||||
- **Publication Date**: 2023-2024 (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: master / propagated to stable
|
||||
- **Target Audience**: ArduPilot developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: Introduces `EK3_GLITCH_RADIUS` parameter — soft outlier rejection: instead of dropping a GPS measurement that fails innovation gating, the EKF inflates innovation variance to the minimum that just passes, effectively de-weighting the measurement. Implication for AC-NEW-4 (false-position safety): the project's covariance honesty contract on `GPS_INPUT.horiz_accuracy` is the ONLY way for AP's EKF to detect and de-weight a bad estimate; under-reporting collapses this safety net.
|
||||
- **Related Sub-question**: SQ6 + AC-NEW-4 design implication
|
||||
|
||||
|
||||
### Source #24
|
||||
- **Title**: ArduPilot AP_NavEKF3 — VehicleStatus.cpp + AP_NavEKF3.cpp (master)
|
||||
- **Link**: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_NavEKF3/AP_NavEKF3_VehicleStatus.cpp ; https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_NavEKF3/AP_NavEKF3.cpp
|
||||
- **Tier**: L1 (source code)
|
||||
- **Publication Date**: master HEAD (accessed 2026-05-07)
|
||||
- **Timeliness Status**: Currently valid
|
||||
- **Version Info**: master
|
||||
- **Target Audience**: ArduPilot EKF3 developers
|
||||
- **Research Boundary Match**: Full match
|
||||
- **Summary**: EKF3 quality control: (a) ground-stationary GPS drift check ≤ 3 m (gated by `_gpsCheckScaler`); (b) innovation gating per `POS_I_GATE` / `VEL_I_GATE`; (c) soft de-weighting via `EK3_GLITCH_RADIUS` (Source #23). Confirms AP's covariance-driven quality path actually exists; companion-supplied `horiz_accuracy` flows into this chain.
|
||||
- **Related Sub-question**: SQ6 (full file analysis deferred to design phase)
|
||||
|
||||
---
|
||||
|
||||
## SQ1 — Existing / competitor GPS-denied UAV navigation systems
|
||||
@@ -1,348 +0,0 @@
|
||||
# Fact Cards
|
||||
|
||||
## Fact #1
|
||||
- **Statement**: Fixed-wing high-altitude monocular VO suffers from scale ambiguity and accumulated error; comparing against satellite imagery can reduce accumulated drift.
|
||||
- **Source**: Source #1
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: UAV localization implementers
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Architecture
|
||||
- **Fit Impact**: Supports satellite-anchored hybrid estimator.
|
||||
|
||||
## Fact #2
|
||||
- **Statement**: Aerial VPR is sensitive to weather, season, scale variation, repetitive patterns, and map tile construction; overlap and scale level materially affect retrieval quality.
|
||||
- **Source**: Source #2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VPR
|
||||
- **Fit Impact**: Supports AC-8.6 VPR chunks with overlap and seasonal validation.
|
||||
|
||||
## Fact #3
|
||||
- **Statement**: Heavy VPR re-ranking can be too slow for steady-state embedded use; survey evidence reports some re-ranking around 1 s and SuperGlue much slower on evaluated hardware.
|
||||
- **Source**: Source #2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Runtime
|
||||
- **Fit Impact**: Disqualifies per-frame global VPR/re-ranking unless profiled on Jetson.
|
||||
|
||||
## Fact #4
|
||||
- **Statement**: OpenVINS is an EKF/MSCKF visual-inertial estimator with monocular tracking and calibration support, but its code is GPL-3.
|
||||
- **Source**: Source #3
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VO/VIO
|
||||
- **Fit Impact**: Reference/benchmark only unless GPL obligations are accepted.
|
||||
|
||||
## Fact #5
|
||||
- **Statement**: ORB-SLAM3 supports monocular visual-inertial SLAM and multi-map operation, but it is GPLv3 and expects careful calibration and a SLAM-style runtime stack.
|
||||
- **Source**: Source #4
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VO/VIO
|
||||
- **Fit Impact**: Rejected as production dependency; useful benchmark/reference.
|
||||
|
||||
## Fact #6
|
||||
- **Statement**: OpenCV provides camera calibration APIs that output camera matrix and distortion coefficients, and homography estimation APIs including RANSAC.
|
||||
- **Source**: Source #5
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Calibration / geometry
|
||||
- **Fit Impact**: Selected utility layer for calibration, undistortion, homography, and geometric validation.
|
||||
|
||||
## Fact #7
|
||||
- **Statement**: LightGlue accepts local keypoints/descriptors from extractors such as DISK, ALIKED, SIFT, and SuperPoint, and returns matched keypoint indices, coordinates, and confidence scores.
|
||||
- **Source**: Source #6
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Local matching
|
||||
- **Fit Impact**: Selected candidate for conditional cross-domain local matching.
|
||||
|
||||
## Fact #8
|
||||
- **Statement**: LightGlue has adaptive depth/width pruning, FlashAttention, mixed precision, and benchmark scripts; runtime must be profiled on Jetson because defaults are optimized for desktop GPUs.
|
||||
- **Source**: Source #6
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Runtime
|
||||
- **Fit Impact**: Selected with runtime-quality gate.
|
||||
|
||||
## Fact #9
|
||||
- **Statement**: LightGlue code/weights are Apache-2.0, but SuperPoint pretrained weights/inference have restrictive licensing; DISK and ALIKED are safer extractor pairings from a licensing perspective.
|
||||
- **Source**: Source #6
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Licensing
|
||||
- **Fit Impact**: Select DISK/ALIKED+LightGlue for production candidate; treat SuperPoint as license-gated.
|
||||
|
||||
## Fact #10
|
||||
- **Statement**: AnyLoc provides DINOv2 feature extraction and VLAD aggregation APIs, but its full experiment setup notes large storage/compute requirements.
|
||||
- **Source**: Source #7
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VPR descriptors
|
||||
- **Fit Impact**: DINOv2-VLAD selected as offline/conditional retrieval candidate, not unconditional per-frame path.
|
||||
|
||||
## Fact #11
|
||||
- **Statement**: DINOv2 official repository provides Meta's DINOv2 implementation and model assets with Apache-2.0 / CC-BY-4.0 license notices.
|
||||
- **Source**: Source #8
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VPR descriptors
|
||||
- **Fit Impact**: Supports DINOv2 as a permissible descriptor backbone subject to model-license review.
|
||||
|
||||
## Fact #12
|
||||
- **Statement**: FAISS is designed for efficient dense vector similarity search, top-k nearest-neighbor retrieval, speed/accuracy tradeoffs, and indexes too large for simple exhaustive scanning.
|
||||
- **Source**: Source #9
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Descriptor retrieval
|
||||
- **Fit Impact**: Selected vector index for offline VPR descriptors.
|
||||
|
||||
## Fact #13
|
||||
- **Statement**: FAISS supports saving/loading indexes; GPU indexes must be converted to CPU before saving.
|
||||
- **Source**: Source #9
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Cache lifecycle
|
||||
- **Fit Impact**: Supports install-time/index-build flow with runtime load.
|
||||
|
||||
## Fact #14
|
||||
- **Statement**: MAVSDK provides telemetry subscriptions for raw GPS, GPS info, status text, odometry, and position/velocity; it does not remove the need for raw MAVLink control over `GPS_INPUT` emission.
|
||||
- **Source**: Source #10
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: MAVLink integration
|
||||
- **Fit Impact**: Select MAVSDK for telemetry, pymavlink/raw MAVLink for `GPS_INPUT`.
|
||||
|
||||
## Fact #15
|
||||
- **Statement**: ArduPilot GPSInput requires `GPS1_TYPE=14` for MAVLink GPS input.
|
||||
- **Source**: Source #11
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: MAVLink output
|
||||
- **Fit Impact**: Confirms production parameter requirement.
|
||||
|
||||
## Fact #16
|
||||
- **Statement**: `GPS_INPUT` carries WGS84 lat/lon, MSL altitude, velocity, `fix_type`, `horiz_accuracy`, `vert_accuracy`, `speed_accuracy`, and ignore flags.
|
||||
- **Source**: Source #12
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Output contract
|
||||
- **Fit Impact**: Supports mapping estimator covariance to `horiz_accuracy` and failover fix types.
|
||||
|
||||
## Fact #17
|
||||
- **Statement**: ArduPilot GPS glitch protection and EKF failsafe behavior are parameterized and vehicle-specific; Copter docs are not enough to prove Plane behavior.
|
||||
- **Source**: Sources #13, #14
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Failsafe
|
||||
- **Fit Impact**: Requires ArduPilot Plane SITL validation.
|
||||
|
||||
## Fact #18
|
||||
- **Statement**: Jetson Orin Nano Super provides 67 INT8 TOPS, 8 GB memory, 102 GB/s bandwidth, and 7-25 W power range.
|
||||
- **Source**: Source #15
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Runtime
|
||||
- **Fit Impact**: Confirms target platform constraint.
|
||||
|
||||
## Fact #19
|
||||
- **Statement**: NVIDIA warns Super power modes require thermal design that can handle the power modes; otherwise throttling can reduce performance.
|
||||
- **Source**: Source #16
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Thermal
|
||||
- **Fit Impact**: Supports AC-NEW-5 hot-soak and throttle logging.
|
||||
|
||||
## Fact #20
|
||||
- **Statement**: PMTiles is efficient for single-file tile reads but is read-only and cannot be updated in place.
|
||||
- **Source**: Source #17
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Cache storage
|
||||
- **Fit Impact**: Rejected for mutable onboard tile writes; possible export/package format only.
|
||||
|
||||
## Fact #21
|
||||
- **Statement**: COG supports tiled, compressed, overview-enabled GeoTIFFs suitable for efficient raster access and geospatial tooling.
|
||||
- **Source**: Source #18
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Cache storage
|
||||
- **Fit Impact**: Selected imagery storage unit for immutable service tiles and generated candidate tiles.
|
||||
|
||||
## Fact #22
|
||||
- **Statement**: AerialVL provides aerial visual localization sequences, reference maps, and geo-referenced evaluation data.
|
||||
- **Source**: Source #19
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: Validation
|
||||
- **Fit Impact**: Selected validation dataset for VPR/satellite-anchor algorithm development.
|
||||
|
||||
## Fact #23
|
||||
- **Statement**: EuRoC provides synchronized camera/IMU and ground truth for VIO, but it is not representative of high-altitude fixed-wing nadir imagery.
|
||||
- **Source**: Source #20
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Validation
|
||||
- **Fit Impact**: Use for VIO sanity checks only, not final AC proof.
|
||||
|
||||
## MVE Evidence
|
||||
|
||||
### MVE — OpenCV calibration and homography utilities
|
||||
- **Source**: Source #5
|
||||
- **Pinned mode/config**: Use OpenCV 4.x C++/Python APIs for checkerboard calibration, undistortion, homography estimation with RANSAC, and reprojection-error measurement.
|
||||
- **Inputs in example**: Object/image point correspondences, image size, matched keypoints.
|
||||
- **Outputs in example**: Camera matrix, distortion coefficients, rotation/translation vectors, homography matrix.
|
||||
- **Project inputs**: ADTi nav-camera frames, checkerboard calibration images, matched VO/satellite points.
|
||||
- **Project outputs required**: Intrinsics/distortion, homography, inlier mask, MRE.
|
||||
- **Match assessment**: Exact match.
|
||||
|
||||
### MVE — LightGlue in DISK/ALIKED local-matching mode
|
||||
- **Source**: Source #6
|
||||
- **Pinned mode/config**: Use DISK+LightGlue or ALIKED+LightGlue on CUDA/TensorRT-profiled Jetson path, with inputs two normalized images and outputs matched keypoint coordinates plus confidence scores.
|
||||
- **Inputs in example**: Two images loaded to GPU; local features extracted by DISK/ALIKED/SuperPoint.
|
||||
- **Outputs in example**: `matches` shape `(K, 2)`, keypoint coordinates in each image, confidence scores.
|
||||
- **Project inputs**: Orthorectified nav frame crop and candidate satellite/VPR chunk.
|
||||
- **Project outputs required**: 2D-2D correspondences for RANSAC homography and cross-domain MRE.
|
||||
- **Match assessment**: Exact interface match; runtime quality gate remains.
|
||||
|
||||
### MVE — FAISS top-K VPR retrieval
|
||||
- **Source**: Source #9
|
||||
- **Pinned mode/config**: Use FAISS CPU index with optional GPU acceleration for top-K nearest neighbor search over precomputed DINOv2/VLAD descriptors, saved/loaded at install/preflight time.
|
||||
- **Inputs in example**: Float32 descriptor matrix, query descriptor, `k`.
|
||||
- **Outputs in example**: Distance matrix `D` and index matrix `I`.
|
||||
- **Project inputs**: Precomputed VPR chunk descriptors, query frame descriptor.
|
||||
- **Project outputs required**: Top-K candidate chunk IDs for local matching.
|
||||
- **Match assessment**: Exact match.
|
||||
|
||||
### MVE — MAVSDK telemetry + pymavlink GPS_INPUT
|
||||
- **Source**: Sources #10, #11, #12
|
||||
- **Pinned mode/config**: Use MAVSDK for telemetry subscriptions and pymavlink/raw MAVLink for `GPS_INPUT` emission to ArduPilot with `GPS1_TYPE=14`.
|
||||
- **Inputs in example**: Telemetry streams, estimator lat/lon/alt/velocity/covariance.
|
||||
- **Outputs in example**: `GPS_INPUT` fields accepted by ArduPilot GPS backend.
|
||||
- **Project inputs**: ESKF state and covariance, source label, mode/fix quality.
|
||||
- **Project outputs required**: Frame-by-frame WGS84 `GPS_INPUT`, status text, FDR record.
|
||||
- **Match assessment**: Exact match for output contract; Plane SITL validation remains.
|
||||
|
||||
## Mode B Findings
|
||||
|
||||
### Fact #24
|
||||
- **Statement**: DINOv2 TensorRT optimization on Jetson may provide limited speedup and can change embedding distances; descriptor fidelity must be tested against the PyTorch/ONNX baseline before selecting a TensorRT descriptor path.
|
||||
- **Source**: Sources #21, #22
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: VPR runtime / quality
|
||||
- **Fit Impact**: Adds embedding-fidelity gate; keeps DINOv2 selected only after profiling.
|
||||
|
||||
### Fact #25
|
||||
- **Statement**: LightGlue's SuperPoint path has documented license concerns; DISK/ALIKED remain the safer production default unless legal review approves SuperPoint.
|
||||
- **Source**: Source #23
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Licensing
|
||||
- **Fit Impact**: Confirms draft01 decision to avoid SuperPoint as default.
|
||||
|
||||
### Fact #26
|
||||
- **Statement**: ArduPilot `GPS_INPUT_IGNORE_FLAG_VEL_HORIZ` has a reported EKF3 pitfall where velocity may become zero rather than truly ignored; SITL must validate velocity-source parameters and message fields.
|
||||
- **Source**: Source #24
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: MAVLink integration
|
||||
- **Fit Impact**: Adds a specific MAVLink test and parameter gate.
|
||||
|
||||
### Fact #27
|
||||
- **Statement**: FAISS deployment on Jetson ARM64 should assume CPU FAISS by default; GPU FAISS packages are not the safe default on aarch64.
|
||||
- **Source**: Source #25
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: Descriptor retrieval runtime
|
||||
- **Fit Impact**: Changes FAISS pinned mode from CPU with optional GPU to CPU-first, with custom GPU build only as future optimization.
|
||||
|
||||
### Fact #28
|
||||
- **Statement**: Visual matching with orthophotos is a known GNSS-denied UAV approach, but available sources do not prove robustness against adversarial visual attacks on imagery/cache content.
|
||||
- **Source**: Source #26
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: Security
|
||||
- **Fit Impact**: Adds cache integrity, signed manifests, and consistency checks as required controls.
|
||||
|
||||
### Fact #29
|
||||
- **Statement**: COG creation is a write-new-object workflow; the live onboard cache should append/replace tile objects through manifests, not mutate a COG in place.
|
||||
- **Source**: Source #18
|
||||
- **Phase**: Mode B
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Cache lifecycle
|
||||
- **Fit Impact**: Clarifies cache implementation.
|
||||
|
||||
### Fact #30
|
||||
- **Statement**: OpenVINS is technically stronger than a pure hand-rolled OpenCV-only VIO stack for camera+IMU odometry, but its GPLv3 license and generic VIO lifecycle make it unsuitable as the default production dependency for this product.
|
||||
- **Source**: Sources #27, #28
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: VO / VIO selection
|
||||
- **Fit Impact**: Use OpenVINS as a mandatory benchmark/reference, not as the shipped estimator dependency unless GPL obligations are explicitly accepted.
|
||||
|
||||
### Fact #31
|
||||
- **Statement**: The selected production estimator is not "custom OpenCV-only"; OpenCV is the geometry utility layer, while the product-owned ESKF/mode machine owns covariance, source labels, GPS spoofing, blackout, tile-write eligibility, and MAVLink semantics.
|
||||
- **Source**: Sources #5, #29; AC-1.4, AC-3.5, AC-4.3, AC-NEW-4, AC-NEW-7, AC-NEW-8
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Estimator ownership
|
||||
- **Fit Impact**: Keep custom production estimator, but reject any interpretation that means building a naive OpenCV-only VIO stack.
|
||||
|
||||
### Fact #32
|
||||
- **Statement**: Fixed-wing GPS-denied UAV research supports a hybrid of visual odometry plus satellite/orthophoto matching to reduce accumulated drift, matching the project architecture better than a standalone VIO-only solution.
|
||||
- **Source**: Sources #1, #26
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Architecture
|
||||
- **Fit Impact**: Confirms that OpenVINS alone cannot satisfy the absolute-position and re-anchor responsibilities without the satellite anchor path.
|
||||
|
||||
### Fact #33
|
||||
- **Statement**: DINOv2-VLAD/AnyLoc-style retrieval is a strong global candidate generator for aerial VPR, but descriptor size, model size, and environment-specific VLAD/index choices must be budgeted and profiled.
|
||||
- **Source**: Sources #7, #30, #32
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Satellite retrieval
|
||||
- **Fit Impact**: Select DINOv2-VLAD for triggered retrieval, not steady-state per-frame execution.
|
||||
|
||||
### Fact #34
|
||||
- **Statement**: Aerial VPR sources emphasize tile/chunk scale, overlap, weather/season changes, repetitive patterns, and re-ranking cost; local matching should be a verification/rerank stage over bounded top-K candidates.
|
||||
- **Source**: Source #32
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Anchor verification
|
||||
- **Fit Impact**: Supports VPR chunks with 40-50% overlap, dynamic K, and conditional ALIKED/LightGlue verification.
|
||||
|
||||
### Fact #35
|
||||
- **Statement**: ALIKED + LightGlue has an exact local matching interface and a plausible ONNX/TensorRT deployment path, but public evidence does not prove Jetson Orin Nano p95 latency for the project image sizes.
|
||||
- **Source**: Sources #6, #31
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: Local matching runtime
|
||||
- **Fit Impact**: Keep ALIKED/LightGlue selected with runtime gate; benchmark DISK and SIFT/ORB as fallbacks.
|
||||
|
||||
### Fact #36
|
||||
- **Statement**: DINOv2 TensorRT conversion can reduce embedding discrimination and may not provide meaningful speedup on Jetson-class devices; descriptor-fidelity tests must precede any optimized engine acceptance.
|
||||
- **Source**: Source #22
|
||||
- **Phase**: Mode B round 2
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: VPR deployment
|
||||
- **Fit Impact**: TensorRT is an optimization candidate only after PyTorch/ONNX retrieval-rank equivalence is proven.
|
||||
|
||||
### Fact #37
|
||||
- **Statement**: BASALT is the best production VIO candidate among BASALT, OpenVINS, and Kimera-VIO because it combines permissive licensing with strong published EuRoC accuracy and completion evidence.
|
||||
- **Source**: Sources #33, #34, #35
|
||||
- **Phase**: Mode B round 3
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: VO / VIO selection
|
||||
- **Fit Impact**: Select BASALT as the production VIO candidate, pending project replay/profiling.
|
||||
|
||||
### Fact #38
|
||||
- **Statement**: OpenVINS has the clearest EKF covariance story, including full/marginal covariance helpers and NEES-style evaluation support, but remains production-constrained by GPLv3.
|
||||
- **Source**: Sources #27, #28, #38
|
||||
- **Phase**: Mode B round 3
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Confidence / covariance
|
||||
- **Fit Impact**: Keep OpenVINS as covariance/reference baseline and use it to calibrate the BASALT wrapper's reported uncertainty.
|
||||
|
||||
### Fact #39
|
||||
- **Statement**: Kimera-VIO is production-friendly from a license standpoint, but it is heavier/stereo-oriented and has documented mono-inertial parameter/performance caveats.
|
||||
- **Source**: Sources #34, #36
|
||||
- **Phase**: Mode B round 3
|
||||
- **Confidence**: Medium
|
||||
- **Related Dimension**: VO / VIO fallback
|
||||
- **Fit Impact**: Keep Kimera-VIO as a backup candidate, not the first production choice for a single fixed nadir camera.
|
||||
|
||||
### Fact #40
|
||||
- **Statement**: None of BASALT, OpenVINS, or Kimera-VIO provides a special fixed-wing nadir mode; downward-camera support depends on accurate camera-to-IMU extrinsics, altitude/scale constraints, and validation under low-parallax planar terrain.
|
||||
- **Source**: Source #37
|
||||
- **Phase**: Mode B round 3
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Nadir-camera support
|
||||
- **Fit Impact**: The architecture must keep satellite anchors and project-level confidence gates regardless of which VIO library is selected.
|
||||
|
||||
### Fact #41
|
||||
- **Statement**: Published EuRoC-type VIO error rates are useful for ranking libraries but are not acceptance evidence for high-altitude fixed-wing nadir imagery over agricultural terrain.
|
||||
- **Source**: Sources #34, #35, #37
|
||||
- **Phase**: Mode B round 3
|
||||
- **Confidence**: High
|
||||
- **Related Dimension**: Validation
|
||||
- **Fit Impact**: Require representative replay/flight data before claiming AC-1/AC-2 accuracy.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Fact Cards — Index & Summary
|
||||
|
||||
> Mode A Phase 2 — engine Step 3 (Fact Extraction & Evidence Cards). Extracted from sources logged in `../01_source_registry/` (see `../01_source_registry/00_summary.md` for index). Confidence labels: ✅ High (L1 / verified source code), ⚠️ Medium (L1/L2 with caveat), ❓ Low (L3/L4 inferential).
|
||||
>
|
||||
> Bound to sub-questions in `../00_question_decomposition.md`. Many SQ6 facts also bind directly to the Project Constraint Matrix (`../../00_problem/acceptance_criteria.md` / `../../00_problem/restrictions.md`); per the engine's "Per-Mode API Capability Verification" rule, MAVLink/MSP messages are treated as candidate **modes** and are bound `Pass/Fail/Verify/N/A` against numbered ACs and restrictions.
|
||||
|
||||
This folder replaces the previous monolithic `02_fact_cards.md` (1480 lines, too large to navigate). Each category lives in its own file. Open the file matching the area you need — every fact and conclusion is preserved verbatim.
|
||||
|
||||
---
|
||||
|
||||
## Category index
|
||||
|
||||
| File | Sub-question / Component | Facts (count) | Scope summary |
|
||||
| --- | --- | --- | --- |
|
||||
| [`SQ6_fc_external_positioning.md`](SQ6_fc_external_positioning.md) | **SQ6** — ArduPilot Plane vs iNav external positioning | #1–#10 (10 facts) | MAVLink `GPS_INPUT` (232) ingestion in EKF3, iNav MSP `MSP2_SENSOR_GPS` ingestion via INAV BlackBox, covariance honesty, lane-fusion / lane-switch on (NSats, HDOP, fix_type), spoof-promotion via UBX emulation, dead-reckoning behaviour, `EK3_GPS_CHECK` bit-mask gates. Working conclusions: ArduPilot is the cooperative path, iNav requires UBX impersonation. |
|
||||
| [`SQ1_existing_systems.md`](SQ1_existing_systems.md) | **SQ1** — Existing / competitor GPS-denied UAV navigation systems | #11–#20 (10 facts) | Twist Robotics OSCAR (Ukrainian peer), Auterion Artemis OS, Vantor Raptor, NGPS class systems, SPRIN-D winner, RTAB-Map / ORB-SLAM3 pruning rationale, DSMAC/TERCOM lineage, hierarchical retrieval-matching SOTA, AerialExtreMatch benchmark, DARPA FLA + USAF SBIR programs. Working conclusions: VPR-anchored hybrid pipeline is canonical. |
|
||||
| [`SQ2_canonical_pipeline.md`](SQ2_canonical_pipeline.md) | **SQ2** — Canonical GPS-denied pipeline & SOTA components | #21–#27 (7 facts) | Two-stage canonical pipeline (global VPR → local alignment → PnP-RANSAC → EKF), end-to-end visual-localization rejection (poor generalization, no covariance), cross-domain sat ↔ UAV registration, hardware MVE doctrine, Top-N inlier re-rank gate. Working conclusions: VIO + VPR + Matcher + PnP + EKF is the design floor. |
|
||||
| [`C1_vio.md`](C1_vio.md) | **C1** — Visual / Visual-Inertial Odometry | Candidate enumeration + decisions | VINS-Mono (BSD/permissive baseline), VINS-Fusion (GPL-3.0 alternate), OpenVINS (GPL-3.0), OKVIS2 (BSD), Kimera-VIO (BSD), DROID-SLAM (BSD non-VIO), DPVO (Apache-2.0 non-VIO), KLT+RANSAC (homemade fallback). Decisions: D-C1-1 license posture, D-C1-2 IMU rate. |
|
||||
| [`C2_vpr.md`](C2_vpr.md) | **C2** — Visual Place Recognition | Candidate enumeration + decisions | MixVPR, SALAD (GPL-3.0 disqualifier), SelaVPR, NetVLAD, EigenPlaces, AnyLoc, BoQ, DINOv2-VLAD. Decisions: D-C2-1 aerial-domain training, D-C2-2 cache budget, D-C2-3 input resolution shape, D-C2-N TensorRT export gate. |
|
||||
| [`C3_matchers.md`](C3_matchers.md) | **C3** — Cross-domain registration (Matchers) | Candidate enumeration + decisions | SP+LightGlue (Magic Leap noncommercial disqualifier on canonical SP), DISK+LightGlue (RECOMMENDED-PRIMARY-MITIGATION), ALIKED+LightGlue, XFeat (alternate-modern lead), SuperGlue+SuperPoint (deprecated by LightGlue authors), MASt3R (CC-BY-NC), RoMa, DKM, LoFTR. Decisions: D-C3-1 modern-competitive lead, D-C3-2 ONNX/TensorRT export path, D-C3-6 re-rank strategy. |
|
||||
| [`C4_pose_estimation.md`](C4_pose_estimation.md) | **C4** — Pose estimation (PnP + RANSAC + LM) | #52–#54 (3 facts, in progress) | OpenCV `cv::solvePnPRansac` mandatory simple-baseline (Apache-2.0 throughout, 9 SolvePnPMethod enum values with 2 BROKEN, paired `solvePnPRefineLM`/`solvePnPRefineVVS`/`solvePnPGeneric`, 7 USAC RANSAC variants); OpenGV modern-competitive-lead-richer-minimal-solver (BSD-3-Clause-equivalent NOASSERTION-SPDX-detector contingent + ~3-year stale + 4 algorithm-selectable RANSAC enums [KNEIP/GAO/EPNP/GP3P] + 2 P3P variants + UPnP global-optimal + GP3P generalized-camera; NO planar-scene dedicated solver vs OpenCV's IPPE); GTSAM modern-competitive-lead-covariance-honest (BSD-3-Clause clean throughout, daily-active maintenance, **NATIVE 6×6 pose covariance via `Marginals.marginalCovariance` — only C4 candidate to satisfy AC-NEW-4 NATIVELY**, no native RANSAC, ~50-200 MB footprint, tight AC-4.1 latency margin). Decisions: D-C4-1 (carry-forward) 2D-3D-lift; D-C4-2 (NEW + UPDATED) covariance-recovery-strategy; D-C4-3 (NEW) OpenGV license-clearance-verification; D-C4-4 (NEW) OpenGV maintenance-staleness-mitigation. Subsequent candidates pending: Theia / Ceres-only (likely deferrable — D-C4 row may already have sufficient coverage). |
|
||||
| [`C5_state_estimator.md`](C5_state_estimator.md) | **C5** — State estimator / sensor fusion | #88–#89 (2 facts, **batch 1 closed at 2/N 2026-05-08**) | Manual ESKF reference (Solà 2017 canonical aerial/quaternion arXiv preprint — public-domain canonical equations + project-side custom implementation under project's Apache-2.0; mandatory simple-baseline; trivial dependency footprint at ~kilobytes of NumPy/SciPy code; native 6×6 covariance via analytic Jacobian propagation per Solà §6 canonical recipe; quaternion-correct attitude integration on SO(3) via small-angle approximation in error-state; **fastest C5 candidate by an order of magnitude** at ~5-15 ms per update on Jetson CPU); GTSAM `iSAM2` + `CombinedImuFactor` (Forster et al. RSS 2015) + `PreintegratedCombinedMeasurements` + `BetweenFactorPose3` + `GenericProjectionFactorCal3DS2` + `PriorFactorPose3` + smart projection factors + `Marginals.marginalCovariance` + `gtsam_unstable.IncrementalFixedLagSmoother` modern-competitive-lead-factor-graph (clean BSD-3-Clause throughout, daily-active maintenance with last-pushed 2026-05-08T13:00:22Z = TODAY at access time, **architecturally couples with C4 Fact #54 via shared GTSAM substrate**, native 6×6 posterior covariance via `Marginals` — same NATIVE AC-NEW-4 satisfaction pathway as C4 Fact #54, IMU pre-integration via Forster et al. RSS 2015 `CombinedImuFactor` 6-key per-keyframe-pair factor with bias evolution for asynchronous IMU+camera fusion at ~100-200 Hz IMU + 3 Hz camera, ~50-200 MB footprint, incremental smoothing via iSAM2 amortizes per-frame cost, **NATIVE AC-4.5 look-back refinement** unique among C5 candidates). Decisions: D-C5-1 (NEW) reference-implementation-license-verification; D-C5-2 (NEW) long-cruise-observability-strategy; D-C5-3 (NEW) sliding-window-primitive-choice; D-C5-4 (NEW) IMU-gap-handling-strategy; D-C5-5 (NEW) factor-density-choice (recommended D-C5-5 = (c) couples C4 Fact #54 D-C4-2 = (b) with C5 Fact #89 architectural integration via shared GTSAM substrate). |
|
||||
| [`C6_tile_cache_spatial_index.md`](C6_tile_cache_spatial_index.md) | **C6** — Tile cache + spatial index | #92–#93 (2 facts, **batch 1 closed at 2/N 2026-05-08**) | **Cand 1 RECOMMENDED PRIMARY**: Manual mirror of existing parent-suite `satellite-provider` pattern (verified directly via Source #92 filesystem read at /Users/obezdienie001/dev/azaion/suite/satellite-provider/) — PostgreSQL btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` for geographic spatial-grid range queries + `bytea` descriptor blobs + app-side FAISS `IndexHNSWFlat(d, M=32)` loaded at takeoff via `faiss.read_index` for descriptor ANN + filesystem tile storage at `./tiles/{zoom}/{x}/{y}.{image_type}` slippy-map convention; clean PostgreSQL License + MIT + LGPL/MIT-Apache; trivial dependency footprint (no Postgres extensions); empirically-confirmed Postgres-on-Jetson viability per Source #97 March 2026 article (CPU cores limiting, NOT memory); ~6-54 ms per cache hit comfortably within AC-4.1 400 ms p95 budget; ~700 MB-1.5 GB total memory footprint within AC-4.2 8 GB budget. **Cand 2 DEFERRED secondary**: PostgreSQL + PostGIS 3.4 GiST on `geography(POINT,4326)` with KNN distance ordering (`<->`) + pgvector 0.7+ HNSW for descriptor ANN + same filesystem tile storage; native KNN + radius + combined-SQL capabilities are real improvements BUT 5-10× slower geographic lookup than Cand 1 + heavier dependency (~50-100 MB additional memory + ~50-200 MB additional disk install) + PostGIS GPL-2.0-or-later license-complexity (CONTINGENT REJECT under D-C1-1 = (b) BSD/permissive-only-track) + DIVERGENT from suite pattern + improvements marginal-to-negative in project's pinned 3 Hz spatial-grid query operating context. **Comparative-improvement-vs-Cand-1 verdict**: per user's session-start "significant-improvement-only" bar, no material justification to deviate from existing satellite-provider pattern. Decisions: D-C6-1 (NEW) descriptor-storage-format choice (halfvec recommended); D-C6-2 (NEW Cand-1-only) FAISS index variant choice (IndexHNSWFlat M=32 recommended); D-C6-3 (NEW Cand-1-only CROSS-COMPONENT with C10) descriptor-cache-rebuild-trigger strategy (periodic-during-C10-pre-flight recommended); D-C6-4 (NEW Cand-1-only) geographic-spatial-grid radius (dynamic recommended); D-C6-5 (NEW Cand-2-only contingent) Jetson PostGIS+pgvector co-installation Plan-phase verification (verify-on-Jetson-MVE recommended); D-C6-6 (NEW Cand-2-only contingent) pgvector descriptor-storage-type choice (halfvec recommended); D-C6-7 (NEW CROSS-COMPONENT affects parent-suite satellite-provider) cascade-changes-back-to-suite strategy (leave-unchanged recommended given Cand 1 closure verdict). |
|
||||
| [`C7_inference_runtime.md`](C7_inference_runtime.md) | **C7** — On-Jetson inference runtime | #94–#96 (3 facts, **batch 1 closed at 3/N 2026-05-08**) | **Cand 1 RECOMMENDED PRIMARY**: TensorRT native — JetPack 6.2 bundled TensorRT 10.3 + `IInt8EntropyCalibrator2` + `BuilderFlag.FP16+INT8` mixed-precision + engines built directly on Jetson Orin Nano Super SM 87 (Apache-2.0 in TensorRT 10.x; ships with JetPack so zero-effort install; lowest-latency primary path; 2-3× speedup at INT8 vs FP16 per Source #102 YOLO26 benchmark; engines tied to SM 87 hardware-specific per Source #105 — must be built on deployed Jetson via D-C7-7); **Cand 2 modern-competitive-lead-cross-architecture-portability**: ONNX Runtime + TensorRT EP — `onnxruntime-gpu` via Jetson AI Lab JP6/CU126 wheel index + `TensorrtExecutionProvider` config + automatic CUDA EP / CPU EP subgraph fallback (MIT throughout; cross-architecture portability for replay/SITL on x86 dev hosts; `pip install onnxruntime-gpu` does NOT work on Jetson — needs Jetson AI Lab community wheel via D-C7-3 + numpy<2.0.0 pin via D-C7-4); **Cand 3 mandatory simple-baseline**: pure PyTorch FP16 — `torch.amp.autocast` + `model.half()` + Jetson AI Lab PyTorch 2.5 ARM64 wheel (BSD-3-Clause throughout; zero-conversion regression baseline; reference-correctness oracle for accuracy validation of TRT-built engines; standard `pip install torch` lacks CUDA on Jetson — needs Jetson AI Lab wheel via D-C7-5). **Cross-cutting precision policy** (D-C7-6 NEW CROSS-COMPONENT, affects C2+C3+C1+C7): VPR backbones (CNN-class MixVPR/EigenPlaces/NetVLAD) → INT8+FP16 mixed; ViT-class VPR (SelaVPR DINOv2-L; conditional AnyLoc/BoQ/DINOv2-VLAD) → FP16-only initially, INT8 deferred to Jetson MVE per D-C2-5; matchers (LightGlue with SP/DISK/ALIKED, XFeat, XFeat+LighterGlue) → **FP16-only — NO INT8** per Source #103 quantization-sensitivity finding (LightGlue FP8 ModelOpt collapsed match counts); learned VIO frontends → FP16-only initially. **Triton/DeepStream/CUDA-Python custom kernels considered-and-rejected** (server/video-pipeline class + out-of-budget for embedded 8 h mission) per c7_overkill_options scope choice. Decisions: D-C7-1 (NEW Cand-1-only CROSS-COMPONENT with C9) calibration-dataset-strategy (AerialVL S03 + AerialExtreMatch recommended); D-C7-2 (NEW Cand-1-only) TensorRT mixed-precision flag matrix (per-family policy per D-C7-6 recommended); D-C7-3 (NEW Cand-2-only) ORT-Jetson-wheel-index-pin (mirror to project artifact registry + cu126 recommended); D-C7-4 (NEW Cand-2-only) numpy-version-pin (`numpy<2.0.0` recommended); D-C7-5 (NEW Cand-3-only) PyTorch-Jetson-wheel-pin (PyTorch 2.5 + torchvision 0.20 recommended); D-C7-6 (NEW CROSS-COMPONENT C2+C3+C1+C7) INT8-vs-FP16-per-model-family-precision-policy (per-family policy recommended); D-C7-7 (NEW Cand-1-only CROSS-COMPONENT with C10) engine-build-on-Jetson-vs-prebuilt strategy (primary build-on-target + reference-Jetson fallback recommended); D-C7-8 (NEW Cand-1-only) `config.max_workspace_size` cap (1 GB safe default recommended); D-C7-9 (NEW Cand-1-only) TensorRT version pin within JetPack lifecycle (JetPack 6.2 + TensorRT 10.3 recommended). |
|
||||
| [`C10_preflight_provisioning.md`](C10_preflight_provisioning.md) | **C10** — Pre-flight cache provisioning (CROSS-COUPLING MINIMAL scope per 2026-05-08 user choice C; only D-C6-3 + D-C7-7 confirmation pipelines researched here, operator tooling design deferred to Plan-phase) | #100–#101 (2 facts, **batch 1 closed at 2/N 2026-05-08**) | **D-C6-3 confirmation (Fact #100)**: descriptor-cache rebuild trigger + atomic-write strategy via direct `faiss.write_index`/`faiss.read_index` Python API + `python-atomicwrites` (write-temp + `fsync` + atomic rename) + content-hash (SHA-256) verification gate at takeoff load + `IO_FLAG_MMAP_IFC` mmap load with `madvise(MADV_WILLNEED)` pre-fault + manifest-hash-driven rebuild trigger; FAISS MIT + atomicwrites MIT throughout; FAISS warns "no internal integrity check, expects validated input" — MITIGATED by content-hash gate at takeoff (binds AC-NEW-7 cache-poisoning safety); rebuild-while-not-flying constraint per restrictions.md. **D-C7-7 confirmation (Fact #101)**: hybrid TensorRT engine-build orchestration — Polygraphy CLI primary for INT8-calibrating builds (`polygraphy convert --int8 --calib-cache=<path> ...` Apache-2.0 + Calibrator API replaces hand-written `IInt8EntropyCalibrator2`) + `trtexec` for fast cache-reuse rebuilds (`--fp16 --int8 --calib=<existing_cache>`) + direct `IBuilderConfig` Python API as escape hatch for unusual models (LightGlue dynamic-shape profiles); calibration cache binary-blob reuse keyed by `SHA-256(calib_corpus)` per D-C10-6; engines tied to SM 87 hardware-specific per Source #105 → must be built on deployed Jetson per D-C7-7 closure (D-C10-8 reference-Jetson-at-HQ + deployed-Jetson-copy-to-archive prebuilt-fallback venue); self-describing filename schema `<model>_sm<SM>_jp<JP>_trt<TRT>_<precision>.engine` per D-C10-7; binds AC-4.1/4.2 latency+memory budgets via D-C7-2 mixed-precision flag matrix + D-C7-1 calibration corpus closure. |
|
||||
| [`MODEB_addendum.md`](MODEB_addendum.md) | **Mode B addendum** — solution_draft01 assessment (2026-05-08) | #102–#113 (12 facts) | Documentary-audit findings (Facts #102–#108): VINS-Mono BSD/GPL deliverable-formatting error (#102), AC-4.1 latency budget overrun (#103), camera calibration unspecified (#104), Suite Sat Service voting-layer contract gap (#105), `00_ac_assessment.md` BLOCKING-gate skip acknowledged (#106), AC-4.5 FC-consumption pathway scope clarification (#107), SQ2 AdHoP + Top-N re-rank sub-stage absence in solution_draft01 architecture (#108). Web-research findings (Facts #109–#113): MAVLink no-default-auth + MAVLink-2.0 message-signing per FC (#109), MegaLoc + UltraVPR D-C2-11 deferred-evaluation revision (#110), `MAV_CMD_SET_EKF_SOURCE_SET` no-deployed-GCS-implementer re-confirmation (#111), OpenCV ≥4.12.0 CVE pin (#112), XoFTR + DINOv2-features cross-modal contrarian evidence (#113). |
|
||||
| [`C8_fc_adapter.md`](C8_fc_adapter.md) | **C8** — MAVLink / MSP2 FC adapter | #97–#99 (3 facts, **batch 1 closed at 3/N 2026-05-08**) | **Cand 1 RECOMMENDED PRIMARY for ArduPilot**: pymavlink → MAVLink `GPS_INPUT` (msg 232) cooperative-path; `master.mav.gps_input_send(time_usec, gps_id, ignore_flags, time_week_ms, time_week, fix_type, lat, lon, alt, hdop, vdop, vn, ve, vd, speed_accuracy, horiz_accuracy, vert_accuracy, satellites_visible, yaw)` periodic injection at 5 Hz over MAVLink (UART/USB/UDP per D-C8-1); FC-side `GPS1_TYPE=14` MAVLink + `EK3_SRC1_POSXY=3` GPS source-set drives EKF3 ingestion via `AP_GPS_MAV` (verified Source #4 SQ6 + Source #106 + Source #107); pymavlink LGPL-3.0 linkable from Apache-2.0 app per LGPL §6 (D-C8-3 mitigation). **Cand 2 RECOMMENDED PRIMARY for iNav**: `MSP2_SENSOR_GPS` (id 7939 / 0x1F03) via Python MSP V2 (YAMSPy or INAV-Toolkit `msp_v2_encode`); `mspGPSReceiveNewData()` direct passthrough (no validation gate beyond data parse); covariance fields `hPosAccuracy`/`vPosAccuracy`/`hVelAccuracy` align directly with AP `GPS_INPUT.horiz_accuracy`/`vert_accuracy`/`speed_accuracy`; YAMSPy + INAV-Toolkit MIT throughout; `USE_GPS_PROTO_MSP` enabled by default in iNav target/common.h (verified Source #111 + #112 + #113); locked SQ6 + AC-4.3 + restrictions.md transport. **Cand 3 DEFERRED secondary for iNav**: UBX impersonation via pyubx2 NAV-PVT — forging u-blox NAV-PVT frames through standard GPS pipeline; iNav-side `gpsMapFixType()` validation gate requires `flags & 0x01 = 1` (gnssFixOK) AND `fixType ∈ {2,3}` per Source #110 `gps_ublox.c` lines 215-220 + 654; pyubx2 BSD-3-Clause clean dual-use; **does NOT clear user's "significant-improvement-only" bar over Cand 2** — richer protocol surface (NAV-PVT periodic + NAV-VER startup + CFG-MSG/CFG-RATE ACK behaviour) + AC-NEW-7 forgery posture + stricter validation gate + AP-path field-name divergence outweigh pyubx2 library-maturity advantage. **Mid-batch correction**: I caught a contradiction between my own initial AskQuestion phrasing ("UBX impersonation as ONLY iNav path") and locked SQ6 + AC-4.3 + restrictions.md verdicts; user re-locked scope via `c8_inav_recovery=B` to evaluate both as parallel candidates. Decisions: D-C8-1 (NEW Cand-1-only) pymavlink connection-string transport choice (env-driven default-UART recommended); D-C8-2 (NEW Cand-1-only CROSS-COMPONENT with AC-NEW-2) `MAV_CMD_SET_EKF_SOURCE_SET` companion-driven switch ownership pattern (companion publishes to source-set 2 + auto-switches FC recommended); D-C8-3 (NEW Cand-1-only) pymavlink LGPL-3.0 license-posture verification (bundle-unmodified-with-version-pin recommended); D-C8-4 (NEW Cand-2-only) Python MSP V2 implementation choice (YAMSPy primary + thin custom encoder fallback recommended); D-C8-5 (NEW Cand-2-only) MSP2_SENSOR_GPS injection rate (5 Hz periodic recommended); D-C8-6 (NEW Cand-3-only contingent) UBX-version-advertisement strategy (advertise version ≥ 15.0 recommended); D-C8-7 (NEW Cand-3-only contingent CROSS-COMPONENT with AC-NEW-7) AC-NEW-7 audit-trail posture for UBX impersonation (explicit FDR audit entry recommended); D-C8-8 (NEW CROSS-COMPONENT C5+C8) covariance-honesty cross-FC enforcement strategy (per-FC unit conversion recommended via 95% confidence ellipse semi-major axis from C5 GTSAM `Marginals.marginalCovariance`). |
|
||||
|
||||
**Cross-cutting consumers** (do not duplicate facts here, just point in):
|
||||
- The Component Fit Matrix (`../06_component_fit_matrix/`) cites every fact here by `Fact #N` or by candidate row.
|
||||
|
||||
---
|
||||
|
||||
## Confidence-label legend
|
||||
|
||||
| Label | Meaning | Source class |
|
||||
| --- | --- | --- |
|
||||
| ✅ High | Source code / official spec / canonical repo verified | L1 (primary code, official docs, published benchmarks) |
|
||||
| ⚠️ Medium | Authoritative but with stated caveat (out-of-date version, partial coverage, single-source confirmation) | L1 / L2 |
|
||||
| ❓ Low | Inferential or extrapolated (vendor blog, secondary commentary, candidate not yet runtime-verified on target hardware) | L3 / L4 |
|
||||
|
||||
Whenever a candidate is marked **Selected** in `../06_component_fit_matrix/`, its row depends on at least one ✅ High fact in the corresponding C-file plus a `context7` per-mode API capability verification.
|
||||
|
||||
---
|
||||
|
||||
## Editing rules
|
||||
|
||||
1. Add new facts only inside their owning category file. Cross-reference siblings; do not duplicate text.
|
||||
2. Each fact keeps the existing schema — `### Fact #N — title`, `**Statement**`, `**Source**`, `**Phase**`, `**Confidence**`, `**Sub-Question Binding**`, `**Implication**`.
|
||||
3. When extending C-rows, also touch the corresponding component file in `../06_component_fit_matrix/` so the matrix stays in sync.
|
||||
4. Working conclusions and decisions (`D-Cx-y`) live at the bottom of their owning file, not here.
|
||||
@@ -0,0 +1,261 @@
|
||||
# Fact Cards — C10: Pre-flight cache provisioning (cross-coupling minimal scope)
|
||||
|
||||
> Mode A Phase 2 — engine Step 3 (Fact Extraction & Evidence Cards). Bound to sub-questions in `../00_question_decomposition.md` line 78 (C10 = "Pre-flight cache provisioning + sector classification + freshness pipeline" with 2026-05-08 user-locked CROSS-COUPLING MINIMAL scope per `c10_scope=C` — see "C10 Scope Restructure" section). Sources for C10 cluster live in [`../01_source_registry/C10_preflight_provisioning.md`](../01_source_registry/C10_preflight_provisioning.md).
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling components: [C1 VIO](C1_vio.md), [C2 VPR](C2_vpr.md), [C3 Matchers](C3_matchers.md), [C4 Pose](C4_pose_estimation.md), [C5 State estimator](C5_state_estimator.md), [C6 Tile cache + spatial index](C6_tile_cache_spatial_index.md), [C7 On-Jetson inference runtime](C7_inference_runtime.md), [C8 MAVLink/MSP2 FC adapter](C8_fc_adapter.md). Cross-component gates: [`../06_component_fit_matrix/99_cross_component_gates.md`](../06_component_fit_matrix/99_cross_component_gates.md).
|
||||
|
||||
---
|
||||
|
||||
## Scope summary
|
||||
|
||||
C10 batch 1 closed at 2/N on 2026-05-08. **Fact #100** = D-C6-3 confirmation pipeline (descriptor-cache rebuild trigger orchestration for the FAISS HNSW index built during C10 pre-flight provisioning + serialized via `faiss.write_index` + atomic-write + content-hash + manifest-driven rebuild trigger + load-at-takeoff via `faiss.read_index` or memory-mapped via `IO_FLAG_MMAP_IFC`). **Fact #101** = D-C7-7 confirmation pipeline (TensorRT engine-build orchestration via Polygraphy CLI primary + `trtexec` simpler fallback + direct `IBuilderConfig` Python API for reference-Jetson-prebuilt-engine generation; calibration corpus shipping mechanism per D-C7-1 closure). User-pinned scope: cross-coupling-minimal — operator CLI/desktop tooling, sector classification heuristics, and freshness pipeline workflow are **deferred to Plan-phase**.
|
||||
|
||||
---
|
||||
|
||||
### Fact #100 — D-C6-3 confirmation: descriptor-cache rebuild trigger pipeline orchestrated via direct `faiss.write_index` / `faiss.read_index` Python API + atomic-write + content-hash + manifest-driven rebuild trigger + optional `IO_FLAG_MMAP_IFC` load
|
||||
|
||||
**Statement**: For C10 (pre-flight cache provisioning, cross-coupling minimal scope), the D-C6-3 descriptor-cache rebuild trigger pipeline (Recommendation = `periodic rebuild during C10 pre-flight provisioning`) is operationalized as the direct FAISS Python API wrapped in a thin project-side orchestration module:
|
||||
|
||||
- **Build pipeline (per pre-flight, manifest-hash-driven)**:
|
||||
1. C10 pre-flight CLI computes `manifest_hash = sha256(descriptor_blobs.sha256, descriptor_dim, faiss_M, ef_construction, vpr_model_sha256)` over the inputs that would change the index content.
|
||||
2. Compare to `manifest_hash_prev` recorded in `/var/lib/onboard/cache/faiss/manifest.json` from the last successful build.
|
||||
3. If `manifest_hash != manifest_hash_prev` (or if `manifest.json` is missing): rebuild the FAISS index. Otherwise: skip.
|
||||
4. Rebuild = `index = faiss.IndexHNSWFlat(d=descriptor_dim, M=faiss_M)` (per D-C6-2 = `IndexHNSWFlat M=32` recommendation) → `index.hnsw.efConstruction = 40` (per Source #96 / Source #114 / C6 Fact #92 canonical pattern) → `index.add(descriptor_blobs)` → write to disk via the atomic-write wrapper (next bullet).
|
||||
5. Write atomic-write wrapper:
|
||||
```python
|
||||
# pseudocode; implementation may use python-atomicwrites package or be hand-rolled per Source #116
|
||||
temp_path = target_path + ".tmp"
|
||||
faiss.write_index(index, temp_path) # FAISS writes serialized binary
|
||||
fd = os.open(temp_path, os.O_RDONLY)
|
||||
os.fsync(fd) # flush content + metadata to disk
|
||||
os.close(fd)
|
||||
os.rename(temp_path, target_path) # POSIX atomic rename (same filesystem)
|
||||
parent_fd = os.open(os.path.dirname(target_path), os.O_RDONLY | os.O_DIRECTORY)
|
||||
os.fsync(parent_fd) # flush directory entry change
|
||||
os.close(parent_fd)
|
||||
content_hash = sha256(open(target_path, 'rb').read())
|
||||
manifest = {"manifest_hash": manifest_hash,
|
||||
"content_hash": content_hash,
|
||||
"descriptor_dim": descriptor_dim,
|
||||
"faiss_M": faiss_M,
|
||||
"ef_construction": ef_construction,
|
||||
"n_tiles": index.ntotal,
|
||||
"build_iso8601": now(),
|
||||
"vpr_model_sha256": vpr_model_sha256,
|
||||
"build_duration_sec": build_duration_sec}
|
||||
write_atomic(manifest_path, json.dumps(manifest))
|
||||
```
|
||||
6. C10 also records the build event into the AC-NEW-3 FDR record: `(model="faiss_hnsw", manifest_hash, content_hash, build_duration_sec, n_tiles, descriptor_dim)`.
|
||||
|
||||
- **Load pipeline (per takeoff)**:
|
||||
1. Read `/var/lib/onboard/cache/faiss/manifest.json` → recover `expected_content_hash`.
|
||||
2. Compute `actual_content_hash = sha256(open(target_path, 'rb').read())` (single-pass file read; ~0.5-2 s on JetPack 6 ARM64 NVMe per ~430 MB halfvec file at 2048-D × 100K tiles per Source #115 size formula).
|
||||
3. Compare: if `actual != expected` → REJECT the cache; emit `STARTUP_FAULT_FAISS_CACHE_HASH_MISMATCH` MAVLink STATUSTEXT to QGC; refuse takeoff (per AC-NEW-7 cache-poisoning safety budget — never silently load a tampered cache file).
|
||||
4. Otherwise: `index = faiss.read_index(target_path, faiss.IO_FLAG_MMAP_IFC)` (memory-mapped load — zero-copy; <1 s wall-time for the syscall to set up mmap regardless of file size; per Source #114 supports HNSW + IndexFlatCodes-derived classes via the `IO_FLAG_MMAP_IFC` flag).
|
||||
5. Optional: warmup query at takeoff (issue ~10 dummy `index.search(rand_query, k=10)` calls) to prime the kernel page cache — smooths post-load p99 latency per Source #115 Issue #622 observation.
|
||||
|
||||
- **Pinned input/output contract**:
|
||||
- inputs: `descriptor_blobs[*]` per tile (numpy.ndarray of shape `(n_tiles, descriptor_dim)` and dtype float32 or halfvec per D-C6-1) computed by C10 pre-flight via running C2 VPR backbone over each cached tile image; `vpr_model_sha256` (the C2 VPR model artifact hash) — feeds into `manifest_hash` so a model-swap forces an index rebuild.
|
||||
- outputs: `<faiss_cache_dir>/v_<descriptor_dim>_M<HNSW_M>.index` (FAISS binary serialization per Source #114) + `<faiss_cache_dir>/manifest.json` (project-defined JSON manifest with content-hash + build provenance).
|
||||
- runtime: pre-flight build runs on the operator workstation OR on the deployed Jetson (per D-C7-7 = primary build-on-target-Jetson recommendation; the same workflow runs on the deployed Jetson to avoid the C7-style SM 87 hardware-tying constraint that doesn't apply to FAISS — FAISS HNSW serialization is hardware-agnostic and can be built once on any x86/ARM machine and shipped). Load runs on the deployed Jetson at takeoff via `faiss.read_index` Python call.
|
||||
|
||||
**Mode pinning** (per-mode API verification rule):
|
||||
- inputs: `descriptor_blobs: numpy.ndarray of shape (n_tiles, descriptor_dim) and dtype float32 or halfvec`; `descriptor_dim: int ∈ {256, 512, 1024, 2048, 4096}` per D-C2-9/10/6 final lock; `faiss_M: int = 32` per D-C6-2 lock; `ef_construction: int = 40` per Source #96 + C6 Fact #92 canonical pattern; `vpr_model_sha256: str` for manifest-hash binding
|
||||
- outputs: serialized FAISS index file at canonical path `<faiss_cache_dir>/v_<descriptor_dim>_M<HNSW_M>.index` + manifest.json with content-hash + build provenance + per-takeoff load latency <5 s (mmap path: <1 s; full-load path at 100K × 2048-D halfvec = ~430 MB / SATA SSD ~500 MB/s = ~0.9 s + page-cache warmup ~1-2 s)
|
||||
- runtime: FAISS-CPU 1.7+ ARM64 wheel via `pip install faiss-cpu` on JetPack 6 + Python 3.10 + NumPy<2.0.0 (per D-C7-4 cross-coupled numpy-version-pin from C7 batch 1 — same pinning applies here since FAISS-CPU shares the numpy ABI dependency)
|
||||
|
||||
**Source**:
|
||||
- Primary FAISS API: Source #114 (`faiss.write_index` / `faiss.read_index` + `IO_FLAG_MMAP_IFC` flag + explicit security warning — canonical FAISS GitHub Wiki + context7 indexed at `/facebookresearch/faiss`)
|
||||
- File-size + load-latency formula: Source #115 (FAISS GitHub Discussions #3953 + canonical `IndexHNSWFlat` C++ API docs cross-cite — per-vector cost formula `(vector_dim × 4) + (M × 4 × 2) + overhead`)
|
||||
- Atomic-write pattern: Source #116 (gocept blog reliable Python file updates + python-atomicwrites docs + Python tracker Issue 8604 — write-temp + fsync + atomic rename + parent-dir fsync canonical pattern; aligns with POSIX `rename(2)` atomicity guarantee)
|
||||
- Cross-cite: C6 Fact #92 (D-C6-3 originating recommendation = periodic rebuild during C10 pre-flight + `faiss.write_index`), C7 Fact #94 (D-C7-1 calibration-dataset-strategy closure that drives the `vpr_model_sha256` provenance binding)
|
||||
|
||||
**Phase**: Mode A Phase 2 — engine Step 3 + Step 7.5 (Component Applicability Gate)
|
||||
|
||||
**Confidence**: ✅ High — all evidence is L1/L2 with direct API verification; security-warning-driven content-hash gate is the project-side mitigation for the documented FAISS warning; atomic-write pattern is canonical POSIX semantics; FAISS load latency at the project's pinned descriptor dimensions comfortably fits the <5 s takeoff budget via either full-load or mmap path.
|
||||
|
||||
**Sub-Question Binding**:
|
||||
- SQ3+SQ4 → C10 row in `../06_component_fit_matrix/C10_preflight_provisioning.md` (this fact populates the D-C6-3 confirmation candidate row)
|
||||
- D-C6-3 cross-coupling: closes the C6 ↔ C10 cross-component gate inherited from C6 Fact #92 (`Plan-phase architect + C10 owner` joint ownership)
|
||||
- AC-NEW-7 (cache-poisoning safety budget): the content-hash verification gate at takeoff is the project-side mitigation for FAISS's documented "no internal integrity check" warning; binds to AC-NEW-7's per-flight forgery-detection contract
|
||||
- AC-3.3 (re-localization stability): atomic-write + content-hash gate guarantees same-cache-content → same-cache-load → same-result determinism across reboots and pre-flight rebuilds
|
||||
|
||||
**Implication / per-numbered-Restriction × per-numbered-AC sub-matrix**:
|
||||
|
||||
| Project Restriction / AC | Verdict | Evidence |
|
||||
|---|---|---|
|
||||
| **R-NEW-2 no cloud at flight** | ✅ PASS | All FAISS read/write operations are local; `faiss.read_index` opens a local file; no network calls. |
|
||||
| **R-NEW-4 Jetson Orin Nano Super JetPack 6 ARM64** | ✅ PASS | FAISS-CPU ARM64 wheels are available via `pip install faiss-cpu` (cross-cite C6 Fact #92 + Source #97); no Jetson-specific issues with `faiss.write_index` / `faiss.read_index` / `IO_FLAG_MMAP_IFC` (canonical FAISS Python API works identically on ARM64). |
|
||||
| **AC-1.x position accuracy** | N/A | Cache file write/read is downstream of accuracy; this fact concerns the descriptor-cache provenance layer. |
|
||||
| **AC-3.3 re-localization stability** | ✅ PASS | Atomic-write + content-hash gate guarantees deterministic cache load across reboots; rebuild only when manifest hash changes; no silent cache mutation at runtime. |
|
||||
| **AC-3.4 operator re-loc hint** | ✅ PASS | Operator re-loc hint uses the same loaded FAISS index (no rebuild required at runtime); content-hash gate at takeoff suffices. |
|
||||
| **AC-4.1 latency budget (<400 ms p95 end-to-end)** | N/A | This is pre-flight + takeoff-load, NOT runtime per-frame. Runtime per-frame latency is governed by C6 Fact #92 (~6-54 ms per cache hit). |
|
||||
| **AC-4.2 memory budget (<8 GB shared on Jetson)** | ✅ PASS | FAISS index in-memory footprint at the project's pinned descriptor dimensions: ~430 MB at 2048-D halfvec × 100K tiles per Source #115 formula (well within C6 Fact #92's 700 MB-1.5 GB Postgres+FAISS+cache subtotal). With `IO_FLAG_MMAP_IFC` the index is mmap'd from disk on demand — peak RSS reduces further at the cost of a page-fault per first-time access. |
|
||||
| **AC-4.5 look-back refinement** | N/A | Pre-flight cache + takeoff load are forward-only events. |
|
||||
| **AC-8.3 10 GB persistent tile cache budget** | ✅ PASS | FAISS index file size at the project's pinned descriptor dimensions: ~430 MB at 2048-D halfvec × 100K tiles + ~80-160 MB at 256-D/512-D halfvec for smaller VPR backbones — fits comfortably within the 10 GB cache budget (well under 5% even at the largest 2048-D variant). |
|
||||
| **AC-NEW-1 cold-start TTFF (<30 s p95)** | ✅ PASS | Takeoff-load via mmap path: <1 s; full-load path at 430 MB file: ~0.9-2 s; well within the AC-NEW-1 30-second cold-start TTFF budget. Content-hash gate adds ~0.5-2 s for the 430 MB SHA-256 pass; together <5 s — comfortably within budget. |
|
||||
| **AC-NEW-3 (FDR)** | ✅ PASS | Per-rebuild manifest entry (manifest_hash, content_hash, build_duration_sec, n_tiles, descriptor_dim, vpr_model_sha256) is recordable as an FDR field; per-takeoff load-latency + hash-verification result are recordable as FDR fields. |
|
||||
| **AC-NEW-4 covariance honesty** | N/A | Pre-flight pipeline is upstream of the C5 estimator; covariance honesty is C5's contract. |
|
||||
| **AC-NEW-7 cache-poisoning safety budget** | ✅ PASS at the FAISS-cache layer | Content-hash gate at takeoff load REJECTS cache files that don't match the manifest (per Source #114 explicit security warning); atomic-write pattern (Source #116) prevents partial-write corruption from masquerading as a valid cache; manifest-hash-driven rebuild triggers ensure that a model swap forces a rebuild with new content hash. **Cross-flight cache poisoning** (per AC-NEW-7's "P(geo-misalign >30 m) <1%" budget) is upstream of C10 — it's the C6 Fact #92 + AC-8.4 mid-flight tile generation responsibility plus the Suite Service voting layer per AC-NEW-7 external-dependency note. |
|
||||
| **AC-NEW-8 blackout failsafe** | ✅ PASS | Pre-flight pipeline doesn't run during flight; if the FAISS cache is corrupt at takeoff, the cache-hash-mismatch gate refuses takeoff (which is safer than launching with a bad cache). C5 demotion to `dead_reckoned` is the runtime failsafe path, not the pre-flight one. |
|
||||
|
||||
**Strengths** (positive structural advantages):
|
||||
1. **Direct FAISS API — minimal abstraction surface**. No additional library dependency beyond FAISS-CPU (already required by C6 Fact #92); no orchestration framework to maintain. The atomic-write wrapper is ~30 lines of Python; trivially auditable; works identically across operator workstation + deployed Jetson environments.
|
||||
2. **Manifest-hash-driven rebuild trigger** — idempotent (skip rebuild if no change); minimum-rebuild semantics (rebuild only when descriptor_blobs OR vpr_model_sha256 OR descriptor_dim changes); aligns naturally with C10 pre-flight workflow (descriptor blobs change when tiles are pulled/refreshed; VPR model changes only on dev-side model swap).
|
||||
3. **Content-hash verification gate at takeoff** — operationalizes the FAISS security warning as project-side AC-NEW-7 coverage; never silently loads a tampered cache file.
|
||||
4. **Atomic-write pattern guarantees crash safety** — power loss or process kill mid-build leaves the previous valid cache file intact (per POSIX `rename(2)` atomicity); next pre-flight rebuild detects the manifest mismatch and rebuilds cleanly.
|
||||
5. **Optional mmap load path (`IO_FLAG_MMAP_IFC`)** — zero-copy load syscall completes in <1 s regardless of file size; reduces takeoff RSS pressure; canonical FAISS HNSW + IndexFlatCodes-derived support per Source #114.
|
||||
6. **Hardware-agnostic FAISS serialization** — index can be built on the operator workstation (x86) and shipped to the Jetson (ARM64) without rebuild (vs C7's SM 87 hardware-tying constraint for TensorRT engines). Useful for the prebuilt-fallback path.
|
||||
7. **License clean throughout** — FAISS (MIT); python-atomicwrites if used (MIT); no GPL contagion path on this orchestration layer.
|
||||
|
||||
**Negative-but-mitigable structural findings**:
|
||||
8. **No FAISS-internal integrity check on `read_index`** (per Source #114 explicit warning) — must be mitigated project-side via the content-hash gate above. Without that gate, AC-NEW-7 fails. **Mitigation**: project-side ~5 lines of Python (open file → SHA-256 → compare to manifest) before the `read_index` call; cost ~0.5-2 s at takeoff for a 430 MB cache file.
|
||||
9. **Atomic-write pattern is project-side, not FAISS-internal** — must be hand-rolled or via `python-atomicwrites`. **Mitigation**: ~30 lines of Python; well-documented canonical POSIX pattern per Source #116; trivially auditable.
|
||||
10. **Manifest-hash binding requires VPR model SHA-256** — implies the C2 VPR model artifact has a stable SHA-256 (i.e., a versioned ONNX-or-engine file is checked into the cache directory or referenced from a versioned URI). **Mitigation**: standard ML artifact versioning; aligns with the C7 Fact #94 + C7 Fact #95 + C7 Fact #96 ONNX export pathway (each ONNX export is a binary file with a deterministic hash).
|
||||
11. **Mmap path RAM behavior depends on OS page cache pressure** — if other workloads consume RAM, mmap'd FAISS index pages may be evicted and re-faulted at runtime, adding ~1-5 ms per evicted page-fault to per-frame query latency. **Mitigation**: `mlock` / `madvise(MADV_WILLNEED)` syscalls available in Python via `mmap.MADV_WILLNEED` to pre-fault the pages; cost: one-time at takeoff (~1-2 s for the 430 MB file). At 8 GB shared budget (with C6 Fact #92's 700 MB-1.5 GB total subtotal) there's ample headroom for keeping the mmap'd index resident.
|
||||
|
||||
**Caveats / open Plan-phase decisions raised** (D-C10-N gates):
|
||||
|
||||
- **D-C10-1 NEW** — descriptor-cache rebuild trigger choice (manifest-hash-driven [recommended] / always-rebuild-every-pre-flight / operator-manual flag): trade-off between idempotency vs simplicity vs operator control. **Recommendation**: D-C10-1 = (a) manifest-hash-driven (idempotent + minimum-rebuild + operator-manual override flag `--force-rebuild` available).
|
||||
- **D-C10-2 NEW** — descriptor-cache atomic-write strategy (write-temp+fsync+rename hand-rolled / `python-atomicwrites` package / accept-non-atomic-write-and-pray): trade-off between dependency surface vs implementation cost vs crash safety. **Recommendation**: D-C10-2 = (b) `python-atomicwrites` (MIT, ~zero-cost dependency, cross-platform, well-tested in production); fallback (a) hand-rolled if dependency-policy gate prefers in-tree.
|
||||
- **D-C10-3 NEW (CROSS-COMPONENT with AC-NEW-7)** — content-hash verification gate at takeoff load (yes — REJECT cache + STATUSTEXT + refuse takeoff [recommended] / yes — WARN + load anyway / no — trust filesystem): trade-off between safety vs availability vs operator-friction. **Recommendation**: D-C10-3 = (a) reject-and-refuse-takeoff; AC-NEW-7 cache-poisoning budget makes silent acceptance unsafe; operator can re-run pre-flight with `--force-rebuild` to cleanly recover.
|
||||
- **D-C10-4 NEW** — descriptor-cache load path (full-`read_index` / mmap via `IO_FLAG_MMAP_IFC` [recommended] / both available via env flag): trade-off between determinism (full-load is fully resident; mmap RSS depends on page cache) vs takeoff latency (mmap is faster) vs runtime page-fault sensitivity. **Recommendation**: D-C10-4 = (b) mmap with optional `madvise(MADV_WILLNEED)` pre-fault at takeoff (~1-2 s additional cost; eliminates runtime page-faults for the lifetime of the flight) OR (c) both available for Plan-phase Jetson MVE comparison.
|
||||
|
||||
---
|
||||
|
||||
### Fact #101 — D-C7-7 confirmation: TensorRT engine-build pipeline orchestrated via Polygraphy CLI (primary) + `trtexec` (simpler fallback) + direct `IBuilderConfig` Python API (reference-Jetson-prebuilt-engine fallback generation)
|
||||
|
||||
**Statement**: For C10 (pre-flight cache provisioning, cross-coupling minimal scope), the D-C7-7 TensorRT engine-build pipeline (Recommendation = `primary build-on-deployed-Jetson during pre-flight + reference-Jetson-built engines as fallback`) is operationalized as a three-tool orchestration matrix:
|
||||
|
||||
- **Primary path: Polygraphy CLI on the deployed Jetson during pre-flight** (per D-C7-7 = primary build-on-target):
|
||||
```bash
|
||||
polygraphy convert <model>.onnx \
|
||||
--int8 --fp16 \
|
||||
--data-loader-script ./calib_data_loader.py \
|
||||
--calibration-cache <calib_cache_dir>/<model>_calib.cache \
|
||||
--workspace=1000000000 \
|
||||
-o <engine_cache_dir>/<model>_sm87_jp62_trt103_<precision>.engine
|
||||
```
|
||||
- First build per-model: `--data-loader-script` reads the project's pinned calibration corpus per D-C7-1 closure (real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles; ~500-1500 representative samples per Source #120) and runs INT8 calibration; the resulting calibration scales are written to `--calibration-cache` for subsequent builds.
|
||||
- Subsequent rebuilds (when calibration corpus is unchanged): `polygraphy convert ... --calibration-cache <existing_cache>` — calibration step is skipped per Source #117 ("If the provided path does exist, it will be read and int8 calibration will be skipped during engine building").
|
||||
- Per-model precision flags follow D-C7-2 / D-C7-6 cross-component policy: VPR backbones (CNN-class) → `--int8 --fp16`; ViT-class VPR + matchers + learned VIO → `--fp16` only (NO `--int8`).
|
||||
- `--workspace=1000000000` (1 GB cap) per D-C7-8 lock to prevent tactic-profile segfault on 8 GB shared budget.
|
||||
- On-disk engine filename incorporates SM 87 + JetPack 6.2 + TRT 10.3 + precision tag (per D-C7-9 lock) so the runtime can reject a cached engine that was built for a different SM/JP/TRT/precision combination.
|
||||
|
||||
- **Simpler fallback: `trtexec` CLI** (when calibration cache already exists or for ad-hoc/emergency rebuilds):
|
||||
```bash
|
||||
trtexec --onnx=<model>.onnx \
|
||||
--saveEngine=<engine_cache_dir>/<model>_sm87_jp62_trt103_<precision>.engine \
|
||||
--fp16 --int8 \
|
||||
--calib=<calib_cache_dir>/<model>_calib.cache \
|
||||
--shapes=input:1x3x224x224 \
|
||||
--workspace=1000
|
||||
```
|
||||
- Faster invocation (no Python imports; single C++ binary).
|
||||
- Calibration cache file format is interoperable with Polygraphy's per Source #119 — caches built by Polygraphy are loadable by `trtexec` and vice versa.
|
||||
- Used as fallback when Polygraphy is unavailable (e.g., minimal install) OR for reference-Jetson-prebuilt-engine generation when no calibration data shipping is needed.
|
||||
- Critical caveat: `trtexec --int8` without `--calib` falls back to RANDOM data calibration → ~5-15% INT8 accuracy collapse → forbidden in the project's C10 path (always supply `--calib` from the existing calibration cache).
|
||||
|
||||
- **Reference-Jetson-prebuilt-engine fallback generation** (per D-C7-7 fallback path, for emergency provisioning): direct TensorRT `IBuilderConfig` + `IInt8EntropyCalibrator2` Python API per Source #121 — used when Polygraphy's `--data-loader-script` abstraction is too rigid for an unusual model (e.g., LightGlue with dynamic-shape inputs requiring a custom calibration profile per D-C3-2 + D-C3-3). Output: a versioned `.engine` file shipped to the deployed Jetson alongside the calibration cache file. The deployed Jetson at takeoff loads this prebuilt engine via `IRuntime.deserializeCudaEngine` (no on-Jetson rebuild required for the fallback path).
|
||||
|
||||
- **Manifest-hash + content-hash + atomic-write** (same pattern as Fact #100):
|
||||
- `manifest_hash = sha256(model_onnx.sha256, calibration_corpus.sha256, precision_mode, sm_version, jp_version, trt_version)` per engine.
|
||||
- `content_hash = sha256(<engine>.engine)` after build.
|
||||
- Atomic-write wrapper around the engine file output (Polygraphy + trtexec both write to a temp path inside their respective CLIs, but the project-side wrapper enforces the rename-into-position step on top to maintain crash safety across the broader pre-flight workflow).
|
||||
- Per-engine manifest entry recorded in `<engine_cache_dir>/manifest.json`: `(model, precision_mode, calib_corpus_sha256, build_iso8601, build_duration_sec, content_hash, sm_version, jp_version, trt_version)`.
|
||||
|
||||
- **Pinned input/output contract**:
|
||||
- inputs: `<model>.onnx` per inference target (C2 VPR backbone + C3 matcher + optional C1 learned VIO frontend, exported on the dev machine via `torch.onnx.export`); `calibration_corpus` per D-C7-1 closure (real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles in NumPy `.npy` or Torch `.pt` tensor format); `<calib_cache>` per Polygraphy/trtexec INT8 calibration cache file (project-side ships the calibration corpus + the calibration cache; cache is reusable across rebuilds when the corpus hash is unchanged).
|
||||
- outputs: per-model `.engine` file at canonical path `<engine_cache_dir>/<model>_sm87_jp62_trt103_<precision>.engine` + per-engine manifest entry in `<engine_cache_dir>/manifest.json` + AC-NEW-3 FDR record.
|
||||
- runtime context: pre-flight build runs ON the deployed Jetson Orin Nano Super (per D-C7-7 = primary build-on-target — per Source #105 SM 87 hardware-tying constraint). Reference-Jetson-prebuilt-engine fallback runs on a known-good HQ Jetson (same SM 87 / JetPack 6.2 / TensorRT 10.3 — per D-C7-9 lock).
|
||||
|
||||
**Mode pinning** (per-mode API verification rule):
|
||||
- inputs: `<model>.onnx: bytes` (ONNX graph from `torch.onnx.export`); `calibration_corpus: numpy.ndarray of shape [N=500-1500, C=3, H=224-320, W=224-320] and dtype float32 normalized to [0, 1]` per project's pinned VPR + matcher input shapes per D-C2-3 / D-C2-5 / D-C3-3; `precision_mode: str ∈ {'int8+fp16', 'fp16'}` per D-C7-6 per-family policy
|
||||
- outputs: serialized TensorRT engine file `.engine` + calibration cache file `.cache` (interoperable between Polygraphy and trtexec per Source #119) + manifest entry
|
||||
- runtime: TensorRT 10.3 + CUDA 12.6 + cuDNN 9.3 on JetPack 6.2 + Polygraphy bundled with TensorRT distribution OR `pip install nvidia-pyindex && pip install polygraphy` (Polygraphy is pure Python; ARM64 Python + TensorRT Python bindings sufficient)
|
||||
|
||||
**Source**:
|
||||
- Primary Polygraphy CLI: Source #117 NVIDIA/TensorRT GitHub `tools/Polygraphy/examples/cli/convert/01_int8_calibration_in_tensorrt/README.md` + canonical Polygraphy docs context7 indexed at `/websites/nvidia_deeplearning_tensorrt_static_polygraphy` (1041 code snippets, Source Reputation High)
|
||||
- Polygraphy `Calibrator` class API: Source #118 canonical NVIDIA TensorRT/Polygraphy SDK documentation (entropy/min-max algo defaults, dynamic-shapes calibration profile, data-loader-script + calibration-cache CLI flags)
|
||||
- `trtexec` CLI: Source #119 canonical NVIDIA TensorRT SDK documentation (`--onnx --saveEngine --int8 --fp16 --calib --shapes --workspace` flag set; calibration cache format interoperability with Polygraphy)
|
||||
- Calibration corpus size guidance: Source #120 vendor-aligned engineering guide (500-1000 image recommendation; cross-cite to project's D-C7-1 closure 500-1500 sample range)
|
||||
- Direct `IBuilderConfig` Python API: Source #121 (cross-cite from C7 batch 1 Source #102 + Source #105) — used for reference-Jetson-prebuilt-engine fallback generation
|
||||
- Cross-cite: C7 Fact #94 (D-C7-7 originating recommendation = primary build-on-deployed-Jetson + fallback prebuilt; D-C7-8 = 1 GB workspace; D-C7-9 = JetPack 6.2 + TRT 10.3 lock); C7 Fact #94 (D-C7-1 closure = real UAV nadir flight footage as calibration corpus distribution; specific fixture pin delegated to Test Spec)
|
||||
|
||||
**Phase**: Mode A Phase 2 — engine Step 3 + Step 7.5 (Component Applicability Gate)
|
||||
|
||||
**Confidence**: ✅ High for Polygraphy + trtexec API capability verification (L1 canonical NVIDIA docs); ✅ High for the orchestration pattern (canonical NVIDIA-blessed workflow per Source #117 README); ⚠️ Medium for the specific build-duration-on-Jetson-Orin-Nano-Super claim (extrapolated from C7 Fact #94 reference of "30-300 sec per model" + Source #105 constraints — exact build-duration depends on model complexity + INT8 calibration scope; needs Plan-phase Jetson MVE confirmation per D-C1-2)
|
||||
|
||||
**Sub-Question Binding**:
|
||||
- SQ3+SQ4 → C10 row in `../06_component_fit_matrix/C10_preflight_provisioning.md` (this fact populates the D-C7-7 confirmation candidate row)
|
||||
- D-C7-7 cross-coupling: closes the C7 ↔ C10 cross-component gate inherited from C7 Fact #94 (`Plan-phase architect + C10 owner` joint ownership)
|
||||
- D-C7-1 closure (real UAV nadir flight footage corpus): C10 owns the calibration-corpus assembly at pre-flight; specific fixture-file pin remains delegated to Test Spec per the 2026-05-08 C9 / SQ7 restructure
|
||||
- AC-NEW-1 (cold-start TTFF <30 s p95): pre-flight engine build is amortized across all takeoffs that use the same artifacts; takeoff-load via `IRuntime.deserializeCudaEngine` is ~100-500 ms per engine × 3-5 engines = ~0.5-2.5 s — well within 30 s budget
|
||||
- AC-NEW-3 (FDR): per-engine manifest entry recorded as FDR field
|
||||
- AC-NEW-7 (cache-poisoning safety): same content-hash + atomic-write pattern as Fact #100 protects the engine cache file against partial-write corruption
|
||||
|
||||
**Implication / per-numbered-Restriction × per-numbered-AC sub-matrix**:
|
||||
|
||||
| Project Restriction / AC | Verdict | Evidence |
|
||||
|---|---|---|
|
||||
| **R-NEW-2 no cloud at flight** | ✅ PASS | All Polygraphy/trtexec invocations are local CLI subprocess calls; engine build runs entirely on the deployed Jetson. |
|
||||
| **R-NEW-4 Jetson Orin Nano Super JetPack 6 ARM64** | ✅ PASS | Polygraphy is pure Python (works on ARM64 + Python 3.10); trtexec is bundled with TensorRT 10.3 in JetPack 6.2 (installed by default at `/usr/src/tensorrt/bin/trtexec`); both interoperate with the JetPack-bundled TensorRT 10.3 per Source #117 + Source #119. |
|
||||
| **AC-1.x position accuracy** | N/A | Engine build is upstream of accuracy; this fact concerns the engine provenance layer. |
|
||||
| **AC-3.x resilience** | N/A | Engine cache is a takeoff-load artifact; runtime resilience is C5/C8 responsibility. |
|
||||
| **AC-4.1 latency budget (<400 ms p95 end-to-end)** | N/A | Engine build is pre-flight + takeoff-load, NOT runtime per-frame. Per-engine inference latency is governed by C7 Fact #94 / Fact #95 / Fact #96. |
|
||||
| **AC-4.2 memory budget (<8 GB shared on Jetson)** | ✅ PASS | Per Source #105 + D-C7-8: Polygraphy/trtexec engine build with `--workspace=1000` (1 GB cap) holds peak build-time memory at ~3-5 GB out of 8 GB shared (build-time peak; runtime is much lower per C7 Fact #94 ~50-150 MB shared library + ~50-300 MB per engine). Pre-flight build is performed when no other workloads are active, so the 5 GB peak is acceptable. |
|
||||
| **AC-4.5 look-back refinement** | N/A | Engine build pipeline is forward-only. |
|
||||
| **AC-8.3 10 GB persistent tile cache budget** | ✅ PASS | Engine `.engine` files at 10-200 MB each per C7 Fact #94 × 3-5 engines = ~100-500 MB on disk (separate from the 10 GB tile cache; lives at `/var/lib/onboard/cache/trt/` or equivalent). Calibration cache files at 1-10 MB each are negligible. |
|
||||
| **AC-NEW-1 cold-start TTFF (<30 s p95)** | ✅ PASS | Takeoff-load via `IRuntime.deserializeCudaEngine` is ~100-500 ms per engine × 3-5 engines = ~0.5-2.5 s; combined with FAISS load <5 s (Fact #100) and content-hash gates total ~5-10 s, well within 30 s budget. **Build is pre-flight, NOT during cold-start** — engines are pre-built during pre-flight provisioning and persisted across reboots. |
|
||||
| **AC-NEW-3 (FDR)** | ✅ PASS | Per-engine manifest entry (model, precision_mode, calib_corpus_sha256, build_iso8601, build_duration_sec, content_hash, sm_version, jp_version, trt_version) is recordable as an FDR field per AC-NEW-3 forensic trail requirement. |
|
||||
| **AC-NEW-4 covariance honesty** | N/A | Engine build pipeline is upstream of the C5 estimator. |
|
||||
| **AC-NEW-7 cache-poisoning safety budget** | ✅ PASS at the engine-cache layer | Same content-hash + atomic-write pattern as Fact #100 (project-side wrapper around Polygraphy/trtexec output); engine-cache poisoning is detected at takeoff load via SHA-256 verification; manifest-hash binding guarantees that a calibration-corpus swap or ONNX-model swap forces a clean rebuild with new content hash. The reference-Jetson-prebuilt-engine fallback path uses a versioned `.engine` artifact that is signed/checksummed at the HQ source-of-truth (the project's release pipeline owns this signing). |
|
||||
| **AC-NEW-8 blackout failsafe** | ✅ PASS | Engine cache is loaded at takeoff; if a content-hash mismatch is detected, takeoff is refused (same posture as Fact #100). C5 demotion to `dead_reckoned` is the runtime failsafe path, not the pre-flight one. |
|
||||
|
||||
**Strengths** (positive structural advantages):
|
||||
1. **Polygraphy is the canonical NVIDIA-blessed orchestration tool** for TensorRT engine builds with INT8 calibration cache reuse — first-party support, multi-snippet docs coverage, production-mature; eliminates the need to write the calibrator + data-loader + builder-config glue code from scratch.
|
||||
2. **Calibration cache reuse across rebuilds** — first build per-model takes ~30-300 sec including INT8 calibration (per C7 Fact #94 reference); subsequent rebuilds skip the calibration step (per Source #117 explicit "calibration will be skipped" semantics) — typically <30 sec even for the most complex matchers. Critical for fast iteration during the operator's pre-flight workflow.
|
||||
3. **CLI interoperability between Polygraphy and trtexec** — the calibration cache file format is identical between the two tools per Source #119; the project can use Polygraphy for the canonical INT8-calibration-bearing build and trtexec for emergency/ad-hoc rebuilds without re-shipping calibration data.
|
||||
4. **Mixed-precision flag matrix matches D-C7-2 / D-C7-6 cross-component policy** — `--int8 --fp16` is the canonical Polygraphy/trtexec invocation for the project's per-family mixed precision per Source #117 + Source #119.
|
||||
5. **`--load-tactics` / `--save-tactics` for reference-Jetson-prebuilt-engine workflow** — Polygraphy supports replaying tactic-search results across multiple builds (per Source #118); the project can ship the tactic replay file alongside the prebuilt engine for fast on-Jetson rebuild without re-running tactic profiling.
|
||||
6. **Direct `IBuilderConfig` Python API as escape hatch** — for unusual models requiring custom calibration profiles (e.g., LightGlue with dynamic-shape inputs per D-C3-2 + D-C3-3) the project can drop down to the direct TensorRT Python API per Source #121 without abandoning the orchestration framework.
|
||||
7. **Pre-flight build amortized across all takeoffs** — engine cache is persistent; build runs only when calibration corpus or ONNX model changes (manifest-hash-driven); typical operator workflow is: build once at HQ ship → operator pulls fresh tile cache → operator triggers pre-flight (FAISS rebuild + maybe TRT rebuild if calibration-corpus refreshed) → takeoff.
|
||||
8. **License clean throughout** — Polygraphy (Apache-2.0); TensorRT (Apache-2.0 in TensorRT 10.x per C7 Fact #94); python-atomicwrites (MIT); no GPL contagion path on this orchestration layer.
|
||||
|
||||
**Negative-but-mitigable structural findings**:
|
||||
9. **First-build INT8 calibration takes 30-300 sec per model on Jetson** — large matcher models (e.g., LightGlue at K=1024 keypoints) can hit the upper end of this range. **Mitigation**: calibration cache reuse — once the cache is built, subsequent rebuilds are <30 sec; first build at HQ + ship cache to operator workstation pre-deployment.
|
||||
10. **Engine cache is hardware-specific (SM 87)** per C7 Fact #94 + Source #105 — can't ship engines across Jetson hardware variants. **Mitigation**: D-C7-7 = (c) primary-build-on-target with reference-Jetson-prebuilt-engine fallback ONLY for SM 87 / JetPack 6.2 / TRT 10.3 combinations; the project's deployed fleet is uniform per restrictions.md (Jetson Orin Nano Super pinned).
|
||||
11. **Polygraphy CLI requires `pip install polygraphy` separately if not bundled with TensorRT distribution** — minimal Jetson installs may need `pip install nvidia-pyindex && pip install polygraphy`. **Mitigation**: include in the project's pre-flight Docker image / OS image bake; verify at C10 setup.
|
||||
12. **`trtexec --int8` without `--calib` falls back to random-data calibration** with documented ~5-15% INT8 accuracy collapse per Source #119. **Mitigation**: project-side wrapper around `trtexec` invocation enforces `--calib=<existing_cache>` non-empty as a precondition; reject the build otherwise with clear error message.
|
||||
13. **Build-time peak memory ~3-5 GB out of 8 GB shared** per Source #105 constraint #4 + D-C7-8 — not safe to run pre-flight build concurrently with other heavy workloads (e.g., camera pipeline, FAISS build). **Mitigation**: pre-flight orchestration is sequential — build TRT engines one at a time, then FAISS index, then verification; takes ~5-15 min total at first-build (with calibration); ~1-3 min for subsequent rebuilds (cache-reused).
|
||||
14. **Calibration-corpus shipping mechanism** — per D-C7-1 closure the corpus is real UAV nadir flight footage at ~1 km AGL; this corpus is several GB of tensor data. **Mitigation**: ship calibration corpus + calibration cache together as a versioned artifact bundle; ship cache only (not raw corpus) to operators when the cache is sufficient (i.e., fixture-pin from Test Spec is stable and operators don't need to recalibrate).
|
||||
|
||||
**Caveats / open Plan-phase decisions raised** (D-C10-N gates):
|
||||
|
||||
- **D-C10-5 NEW (CROSS-COMPONENT with C7)** — TensorRT engine-build orchestration tool choice (Polygraphy CLI primary [recommended] / `trtexec` CLI primary / direct `IBuilderConfig` Python API primary / hybrid: Polygraphy for INT8-calibrating builds + `trtexec` for cache-reuse rebuilds + direct API for unusual models): trade-off between orchestration sophistication vs install footprint vs flexibility. **Recommendation**: D-C10-5 = (d) hybrid — Polygraphy for INT8-calibrating builds (canonical NVIDIA tool, multi-snippet docs, supports custom data loaders); `trtexec` for cache-reuse fast rebuilds (single binary, no Python imports, faster invocation); direct `IBuilderConfig` Python API as escape hatch for unusual models (e.g., LightGlue dynamic shapes per D-C3-2 + D-C3-3).
|
||||
- **D-C10-6 NEW (CROSS-COMPONENT with D-C7-1)** — TensorRT calibration-cache reuse strategy (always reuse if cache file exists [most-aggressive] / rebuild on calib-corpus SHA-256 change [recommended] / rebuild every pre-flight [most-conservative]): trade-off between rebuild cost vs calibration-data freshness vs operator-workflow simplicity. **Recommendation**: D-C10-6 = (b) rebuild on calib-corpus SHA-256 change — manifest-hash-driven rebuild trigger from Fact #100 pattern naturally extends to TRT engine cache; idempotent + minimum-rebuild + operator-manual override flag `--force-trt-rebuild` available.
|
||||
- **D-C10-7 NEW** — TensorRT engine on-disk filename schema (`<model>_sm<SM>_jp<JP>_trt<TRT>_<precision>.engine` [recommended] / hash-only filename / opaque content-addressable storage with separate manifest mapping): trade-off between operator-debuggability vs filesystem-simplicity vs versioning-rigor. **Recommendation**: D-C10-7 = (a) `<model>_sm<SM>_jp<JP>_trt<TRT>_<precision>.engine` self-describing filename + manifest.json side-cache; runtime can reject a cached engine that doesn't match the deployed Jetson's SM/JP/TRT combination with a clear error message at takeoff load.
|
||||
- **D-C10-8 NEW** — TensorRT prebuilt-fallback engine generation venue (reference Jetson at HQ [recommended] / CI pipeline with Jetson-class runner / deployed Jetson copy-to-HQ-archive after first successful local build): trade-off between reproducibility vs CI cost vs reduced pre-flight risk. **Recommendation**: D-C10-8 = (a) reference Jetson at HQ + (c) deployed-Jetson-copy-to-archive on first successful local build for opportunistic redundancy; both venues use the same Polygraphy/trtexec pipeline so artifacts are interchangeable; HQ-built engines serve as authoritative fallbacks signed by the project's release pipeline.
|
||||
|
||||
---
|
||||
|
||||
## C10 — Working conclusions and decisions (compounded from Fact #100 + Fact #101 closures)
|
||||
|
||||
**Selected primary**:
|
||||
- **D-C6-3 confirmation**: descriptor-cache rebuild trigger pipeline orchestrated via direct `faiss.write_index` / `faiss.read_index` Python API + `python-atomicwrites` (or hand-rolled atomic-write) + content-hash verification gate at takeoff + manifest-hash-driven rebuild trigger + optional `IO_FLAG_MMAP_IFC` mmap load path with `madvise(MADV_WILLNEED)` pre-fault. **Closes the C6 ↔ C10 cross-component gate.**
|
||||
- **D-C7-7 confirmation**: TensorRT engine-build pipeline orchestrated via the **hybrid** tool matrix per D-C10-5 = (d): Polygraphy CLI for INT8-calibrating builds (primary) + `trtexec` for cache-reuse fast rebuilds + direct `IBuilderConfig` Python API for unusual models (LightGlue dynamic shapes). Reference-Jetson-prebuilt-engine fallback per D-C10-8 = (a)+(c). Calibration corpus per D-C7-1 closure (real UAV nadir flight footage at ~1 km AGL over season-matched satellite tiles; specific fixture-file pin delegated to Test Spec). **Closes the C7 ↔ C10 cross-component gate.**
|
||||
|
||||
**Decisions raised (D-C10-N gates)** — see [`../06_component_fit_matrix/99_cross_component_gates.md`](../06_component_fit_matrix/99_cross_component_gates.md):
|
||||
|
||||
- **D-C10-1** (Fact #100) — descriptor-cache rebuild trigger choice: manifest-hash-driven / always-rebuild / operator-manual — RECOMMENDED manifest-hash-driven + `--force-rebuild` override
|
||||
- **D-C10-2** (Fact #100) — descriptor-cache atomic-write strategy: hand-rolled / `python-atomicwrites` / no-atomic — RECOMMENDED `python-atomicwrites` (fallback hand-rolled if dependency-policy gate prefers in-tree)
|
||||
- **D-C10-3** (Fact #100, CROSS-COMPONENT with AC-NEW-7) — content-hash verification gate at takeoff load: reject + STATUSTEXT + refuse takeoff / warn + load anyway / no — RECOMMENDED reject + STATUSTEXT + refuse takeoff
|
||||
- **D-C10-4** (Fact #100) — descriptor-cache load path: full-`read_index` / mmap via `IO_FLAG_MMAP_IFC` / both via env flag — RECOMMENDED mmap with `madvise(MADV_WILLNEED)` pre-fault (or both for Plan-phase Jetson MVE)
|
||||
- **D-C10-5** (Fact #101, CROSS-COMPONENT with C7) — TensorRT engine-build orchestration tool choice: Polygraphy primary / trtexec primary / direct API primary / hybrid — RECOMMENDED hybrid (Polygraphy + trtexec + direct API by use case)
|
||||
- **D-C10-6** (Fact #101, CROSS-COMPONENT with D-C7-1) — TensorRT calibration-cache reuse strategy: always-reuse / rebuild-on-calib-corpus-SHA-256-change / rebuild-every-pre-flight — RECOMMENDED rebuild-on-calib-corpus-SHA-256-change + `--force-trt-rebuild` override
|
||||
- **D-C10-7** (Fact #101) — TensorRT engine on-disk filename schema: self-describing `<model>_sm<SM>_jp<JP>_trt<TRT>_<precision>.engine` / hash-only / content-addressable + manifest — RECOMMENDED self-describing filename + manifest.json side-cache
|
||||
- **D-C10-8** (Fact #101) — TensorRT prebuilt-fallback engine generation venue: reference Jetson at HQ / CI pipeline with Jetson-class runner / deployed-Jetson-copy-to-HQ-archive on first successful local build — RECOMMENDED reference Jetson at HQ + deployed-Jetson-copy-to-archive (opportunistic redundancy)
|
||||
|
||||
C10 batch 1 closed at 2/N on 2026-05-08 (cross-coupling minimal scope per `c10_scope=C` user choice). Operator CLI/desktop tooling, sector classification heuristics, freshness pipeline workflow remain **deferred to Plan-phase as `operator tooling design` out-of-research-scope**. **No further C10 batches required at the research layer** — D-C6-3 and D-C7-7 are now closed; remaining C10 questions are operational/UX, not architectural.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,396 @@
|
||||
# Fact Cards — C1: Visual / Visual-Inertial Odometry
|
||||
|
||||
> Mode A Phase 2 — engine Step 3 (Fact Extraction & Evidence Cards). Extracted from sources logged in `../01_source_registry/C1_vio.md` (see `../01_source_registry/00_summary.md` for index). Confidence labels: ✅ High (L1 / verified source code), ⚠️ Medium (L1/L2 with caveat), ❓ Low (L3/L4 inferential). Bound to sub-questions in `../00_question_decomposition.md`.
|
||||
>
|
||||
> Index: [`../00_summary.md`](../00_summary.md). Sibling categories: SQ6 ([FC external positioning](SQ6_fc_external_positioning.md)), SQ1 ([existing systems](SQ1_existing_systems.md)), SQ2 ([canonical pipeline](SQ2_canonical_pipeline.md)), C2 ([VPR](C2_vpr.md)), C3 ([matchers](C3_matchers.md)).
|
||||
|
||||
**Facts in this file**: VIO candidate enumeration (VINS-Mono, VINS-Fusion, OpenVINS, OKVIS2, Kimera-VIO, DROID-SLAM, DPVO, KLT+RANSAC baseline) + Plan-phase decisions D-C1-1, D-C1-2 + C1 working conclusions.
|
||||
|
||||
---
|
||||
|
||||
## SQ3+SQ4 / C1 — Visual / Visual-Inertial Odometry candidate enumeration
|
||||
|
||||
> **Project's pinned mode for every C1 candidate (binding)**: monocular ADTi 20MP nav camera @ 3 fps + IMU from FC over MAVLink @ ≥100 Hz, on Jetson Orin Nano Super (JetPack/CUDA/TensorRT, 8 GB shared LPDDR5, 25 W TDP), producing relative 6-DoF metric pose between consecutive frames + per-axis covariance, with attitude (yaw + pitch) hard-contract σ ≤ 5° at 1 σ (Fact #24), output cadence ≥3 Hz, no in-flight network, license compatible with onboard-binary distribution to a dual-use customer.
|
||||
>
|
||||
> Per the engine's "Per-Mode API Capability Verification" rule, any candidate marked `Selected` requires a `context7` lookup (mode enum + project's exact mode runnable example + disqualifier probe) AND a per-numbered-Restriction × per-numbered-AC sub-matrix. **This session covers candidate enumeration + preliminary applicability assessment only**; `context7` verification and the structured sub-matrix are deferred to the next session per the autodev context budget heuristic.
|
||||
|
||||
### Fact #28 — VINS-Mono is a canonical monocular-only sliding-window VIO with a working Jetson-Nano deployment record but no GitHub release and ~24-month-old master branch
|
||||
- **Statement**: VINS-Mono is the canonical mono+IMU sliding-window VIO from HKUST-Aerial-Robotics (Qin, Li, Shen — IEEE T-RO 2018). Features: efficient IMU pre-integration, automatic initialization, online camera-IMU spatial + temporal calibration, failure detection + recovery, DBoW2 loop detection, global pose-graph optimization. Output: metric-scale 6-DoF pose at IMU rate. **Repository state**: master-branch only (no tagged releases), 5,829 stars; last meaningful master-branch commit 2024-02-25 with a 2024-05-23 simulation-data commit. **Jetson record**: a 2021 IEICE paper (zinuok / KAIST) demonstrated VINS-Mono real-time on the original Jetson Nano (much weaker than Orin Nano Super) for MAV state estimation; a 2024 arXiv paper (2406.13345) showed an enhanced VINS-Mono variant achieving 50 FPS on a Raspberry Pi CM4 with on-sensor accelerated optical flow. **License**: GPL-3.0 (copyleft viral) — distribution of the onboard binary requires source disclosure for the entire linked binary and triggers GPL-3 anti-tivoization clauses for embedded firmware.
|
||||
- **Source**: Source #43 (canonical), Source #46 (KAIST Jetson benchmark), Source #43-linked LICENCE for license confirmation
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Confidence**: ✅ for algorithm class, mode support, and Jetson Nano feasibility; ⚠️ for Jetson Orin Nano Super specific latency (no direct measurement — but Orin Nano Super >> Jetson Nano, so feasibility is virtually certain); ⚠️ for the maintenance-status risk implied by ~24-month-old master branch.
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Established-production candidate
|
||||
- **Fit Impact**: **carry as lead candidate, conditional on user license decision.** Algorithmic fit is excellent (canonical mono+IMU VIO with metric scale and covariance); maintenance status is borderline; **GPL-3.0 license is a project-level decision required from the user** before this candidate can be marked Selected — see "C1 Open Decisions" section below.
|
||||
|
||||
### Fact #29 — VINS-Fusion is a multi-sensor superset of VINS-Mono but its monocular+IMU mode failed to run on Jetson TX2 in a 2021 KAIST benchmark; Orin Nano Super feasibility unverified
|
||||
- **Statement**: VINS-Fusion (Qin, Cao, Pan, Shen — extension of VINS-Mono) supports four documented sensor configurations: stereo+IMU, mono+IMU, stereo only, +GPS-fusion (toy example). KITTI Odometry top-ranked open-source stereo algorithm as of January 2019. **Repository state**: 4,476 stars; last update 2024-05-23; same master-branch-only convention. **Jetson record**: KAIST 2021 benchmark (Source #46) — on Jetson TX2, both **VINS-Fusion (CPU) and VINS-Fusion-imu fail to run** due to insufficient memory and CPU; VINS-Fusion-gpu (GPU-accelerated front-end) runs on TX2. Orin Nano Super has more memory than TX2 (8 GB LPDDR5 shared vs TX2's 8 GB LPDDR4 shared) and stronger CPU/GPU, but the project's onboard stack is *co-resident* with C2 VPR + C3 matcher + C5 estimator + C6 cache → memory-pressure on the VINS-Fusion-imu path is plausible. **License**: GPL-3.0, same dual-use distribution constraint as VINS-Mono.
|
||||
- **Source**: Source #44 (canonical), Source #46 (KAIST Jetson benchmark)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Confidence**: ✅ for the multi-sensor mode support and KITTI ranking; ✅ for the 2021 TX2 failure-to-run finding; ⚠️ for Orin Nano Super viability (between TX2 and Xavier NX in CPU/memory; not yet measured).
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Open-source candidate
|
||||
- **Fit Impact**: **carry as alternate candidate, with mandatory Jetson Orin Nano Super MVE before promotion.** VINS-Mono's narrower scope (mono+IMU only, no stereo overhead) makes VINS-Mono the preferred lead within the HKUST-Aerial-Robotics family; VINS-Fusion's multi-sensor coverage is a distractor for our pinned mode. **GPL-3.0 license decision is the same as VINS-Mono** — see "C1 Open Decisions".
|
||||
|
||||
### Fact #30 — OpenVINS is the most actively maintained MSCKF-class VIO and runs on Jetson Orin Nano Dev Kit + JetPack 6 + ROS 2 Humble with documented build adjustments; latency 270 ms on Xavier NX needs Orin-Nano-Super MVE
|
||||
- **Statement**: OpenVINS (rpng, U. Delaware — Geneva, Eckenhoff, Lee, Yang, Huang — ICRA 2020) is a modular MSCKF (Multi-State Constraint Kalman Filter) implementation that fuses IMU state with sparse visual feature tracks via the Mourikis-Roumeliotis 2007 sliding-window MSCKF. **Mode support**: monocular, stereo, multi-camera (1–N) + IMU; mono+IMU is a documented first-class configuration. Supports SLAM features (in-state landmarks) plus pure MSCKF features. **Jetson Orin Nano evidence**: rpng/open_vins issue #421 (Genozen, Feb 2024, closed) confirms OpenVINS ROS 2 builds on Jetson Orin Nano Dev Kit + JetPack 6 + Ubuntu 22.04 + ROS 2 Humble after one build patch (`#include <opencv2/aruco.hpp>` with newer OpenCV); fdcl-gwu/openvins_jetson_realsense (Nov 2025) provides a complete setup guide for Jetson Orin Nano + Intel RealSense + librealsense compiled-from-source + `--parallel-workers 1` build to avoid memory issues. **Latency record**: rpng/open_vins issue #164 — ~270 ms latency on Jetson Xavier NX (4 cores, 40% CPU utilisation). Recommended optimisations: subscriber queue size 1, Release builds with ARM-specific optimization flags (e.g., `armv8.2-a`), reduced camera resolution, prefer `odometry` topic over `pose_imu`. **License**: GPL-3.0, same dual-use distribution constraint as VINS-Mono / VINS-Fusion. Stars 2,828; 30 contributors; 12 releases; latest tag v2.7 (June 2023) but master branch active through 2024–2025 issue threads.
|
||||
- **Source**: Source #45 (canonical + LICENSE + docs.openvins.com), Source #46 (KAIST Jetson benchmark for class-level CPU/memory profile), agent-tools record `29ebf728...txt` (Jetson Orin Nano build evidence)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Confidence**: ✅ for mode support, MSCKF formulation, and Jetson Orin Nano build feasibility; ⚠️ for steady-state latency on Orin Nano Super under our 5472×3648 nav frames — KAIST benchmark used 640×480; 16× pixel count is a yellow-flag.
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Established-production candidate
|
||||
- **Fit Impact**: **carry as lead candidate, conditional on user license decision.** OpenVINS has the most documented Jetson-Orin-Nano build path of the three GPL-3.0 candidates; MSCKF formulation is more memory-efficient than VINS-Mono's full sliding-window optimisation, which is a meaningful advantage under co-resident-process memory pressure. **GPL-3.0 license decision is the same as VINS-Mono / VINS-Fusion**.
|
||||
|
||||
### Fact #31 — OKVIS2 is the most actively maintained VI-SLAM in the BSD-permissive license bucket; OKVIS2-X (T-RO 2025) extends it with optional GNSS fusion that is architecturally aligned with the project's spoof-promotion path
|
||||
- **Statement**: OKVIS2 (Leutenegger — arXiv 2022, ETH/Imperial/TUM Smart Robotics Lab) is a factor-graph VI-SLAM with bounded-size optimization. Algorithmic novelty: pose-graph edges from marginalised observations are "seamlessly turned back into observations" upon loop closure, reviving old landmarks and reprojection errors. Includes lightweight CNN segmentation for dynamic-region removal. **Mode support**: monocular and multi-camera + IMU; mono+IMU is a documented first-class configuration. **Successor OKVIS2-X (Boche, Jung, Laina, Leutenegger — IEEE T-RO 2025 vol 41 pp 6064–6083, DOI 10.1109/TRO.2025.3619051; arXiv 2510.04612, Oct 2025)** generalises the core to fuse multi-camera + IMU + optional GNSS receiver + LiDAR or depth. The OKVIS2-X GNSS-fusion mode (lineage: Visual-Inertial SLAM with Tightly-Coupled Dropout-Tolerant GPS Fusion, IROS 2022) directly mirrors the project's "VIO that may opportunistically fuse a non-spoofed GPS update when promotion completes" pattern (AC-NEW-2). **Repository state**: ethz-mrl/OKVIS2-X created 2025-09-23, last push 2026-03-17, 295 stars, 2 active contributors (bochsim, SebsBarbas). **License**: 3-clause BSD on the LICENSE file (GitHub UI shows "Other (NOASSERTION)" but the file is canonical 3-clause BSD per ASL-ETH Zurich convention) — permissive, no dual-use distribution friction.
|
||||
- **Source**: Source #47 (OKVIS2 canonical), Source #48 (OKVIS2-X T-RO 2025)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 / C5 implementer
|
||||
- **Confidence**: ✅ for algorithm, mode support, license, T-RO 2025 publication, repository activity; ⚠️ for Jetson Orin Nano runtime — no direct Jetson Orin Nano benchmark located; OKVIS2's factor-graph backend is plausibly heavier than OpenVINS' MSCKF on memory but lighter than Kimera (Kimera also produces a 3D mesh + semantic mesher, OKVIS2 does not).
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Open-source-permissive lead candidate; potential C1+C5+C8 unified factor-graph design
|
||||
- **Fit Impact**: **strong lead candidate by license + maintenance + GNSS-fusion alignment.** If license permissiveness is a priority, OKVIS2 + OKVIS2-X is the natural choice. The OKVIS2-X factor-graph also opens a design path where C5 (state estimator) collapses INTO C1 (the same factor graph absorbs sat-anchor measurements as constraints) — would simplify the pipeline at the cost of departing from the C1/C5 split, which is a Step-7.5 / `solution_draft01` design decision, not a SQ3+SQ4 question. **Pending Jetson Orin Nano Super MVE.**
|
||||
|
||||
### Fact #32 — Kimera-VIO is BSD-permissive but resource-heavy; KAIST benchmark found Kimera had the highest memory usage among VIOs tested and failed Xavier-NX-class memory under multi-process load
|
||||
- **Statement**: Kimera-VIO (MIT-SPARK — Rosinol, Abate, Chang, Carlone — ICRA 2020) is a VI-SLAM pipeline with frontend + backend (factor-graph optimization in iSAM2 or GTSAM) + 3D mesher + pose-graph optimizer. Mode support: stereo+IMU primary, mono+IMU optional but documented. **License**: BSD 2-Clause "Simplified" (LICENSE.BSD on the repo) — permissive. **Maintenance**: active issue/PR threads through Dec 2024 / Feb 2025 covering ROS 2 integration, mono-inertial discussion, dependency management. **Resource profile** (Source #46 KAIST 2021 benchmark): Kimera had the highest memory usage among the 9 algorithms tested (numerous computations per keyframe); Kimera failed to fit on Xavier NX-class memory under sustained multi-process load. The 3D mesh + semantic-label outputs are unused by the project's narrow C1 mandate (relative 6-DoF + covariance only) — Kimera's overhead is unjustified vs OKVIS2 / OpenVINS for our use case.
|
||||
- **Source**: Source #49 (Kimera canonical + LICENSE.BSD), Source #46 (KAIST Jetson benchmark)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects (build-vs-buy, mesh-feature decision)
|
||||
- **Confidence**: ✅ for algorithm, license, maintenance status; ✅ for the Source #46 finding (KAIST 2021); ⚠️ for whether Orin Nano Super's larger memory + Ampere GPU lifts Kimera into feasibility — the Source-46 failure was on Xavier NX 8 GB shared, same memory budget as Orin Nano Super, but Orin Nano Super has higher per-core throughput.
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Open-source-permissive secondary candidate
|
||||
- **Fit Impact**: **carry as fallback only, not lead.** Kimera's permissive license is attractive but its resource overhead (especially the unused 3D mesh + semantic mesher) is a poor fit under co-resident process pressure. Use as a conservative secondary fallback if OKVIS2 unexpectedly fails Jetson MVE. **Status**: not lead.
|
||||
|
||||
### Fact #33 — DROID-SLAM is disqualified by AC-4.2: ≥11 GB GPU VRAM inference budget exceeds the project's 8 GB shared LPDDR5; further, DROID-SLAM is monocular VO/SLAM without IMU fusion and would require an external metric-scale wrapper
|
||||
- **Statement**: DROID-SLAM (princeton-vl, Teed & Deng — NeurIPS 2021; arXiv 2108.10869) requires ≥11 GB GPU memory to run inference per the official README; training requires ≥24 GB on 4× RTX 3090. Issue #121 confirms that even with 128 GB system RAM and 16 GB VRAM (RTX 4080), users hit very large RAM consumption quickly. Algorithmically, DROID-SLAM is **monocular VO/SLAM** with recurrent dense bundle adjustment over a complete history of camera poses — no native IMU fusion; output pose is in arbitrary scale (no metric scale recovery without external alignment). DPV-SLAM (ECCV 2024, princeton-vl) is the lighter successor at ~4–5 GB GPU memory; DPVO (NeurIPS 2023, princeton-vl) is even lighter at ~3 GB, but neither natively integrates IMU.
|
||||
- **Source**: Source #50 (DROID-SLAM canonical), Source #51 (DPVO / DPV-SLAM successor), Source #52 (DPVO-QAT++ memory measurement)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer
|
||||
- **Confidence**: ✅
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 disqualified candidate
|
||||
- **Fit Impact**: **DISQUALIFIED outright.** AC-4.2 sets the 8 GB shared CPU+GPU memory budget; DROID-SLAM's ≥11 GB GPU-only requirement violates it before adding co-resident C2/C3/C5/C6 processes. Cite as "what the project cannot afford" in `solution_draft01` to pre-empt obvious questions.
|
||||
|
||||
### Fact #34 — DPVO is monocular VO only (no IMU fusion); it can fit a Jetson-suitable memory footprint with QAT but cannot satisfy the C1 VIO mandate alone — would need an external IMU + metric-scale wrapper
|
||||
- **Statement**: DPVO (Teed, Lipson, Deng — NeurIPS 2023; ECCV 2024 DPV-SLAM successor) is a deep-learning monocular VO with sparse patch tracking + differentiable bundle adjustment. **Mode**: monocular VO only — no IMU fusion in the published paper or repository; output pose is in arbitrary scale. Memory footprint: DPVO ~3 GB GPU, DPV-SLAM ~4–5 GB GPU on standard hardware; DPVO-QAT++ (arXiv 2511.12653, Cheng Liao, Nov 2025) reduces peak reserved memory to 1.02 GB on RTX 4060 (8 GB) via fused-CUDA INT8 fake-quantization while preserving ATE on TartanAir/EuRoC. **License**: MIT (permissive). Repository: 989 stars; last update 2024-10-12. **Crucial gap**: DPVO does NOT meet the C1 mandate of a "VIO that produces metric-scale 6-DoF + attitude with σ ≤ 5°" — for the project to use DPVO as the *VO half* of C1, an additional IMU+scale-fusion module (loosely-coupled ESKF with VO velocity / displacement priors) must be designed; alternatively, DPVO's pose can feed C5 directly as a relative-displacement constraint, with attitude served separately by FC IMU integration. **Jetson Orin Nano runtime evidence**: indirect — DPVO-QAT++ benchmarks on RTX 4060 desktop, NOT Jetson Orin Nano. The Ampere GPU architecture is shared between RTX 4060 and Orin Nano Super (both Ampere); the Orin Nano Super's GPU is smaller, so direct extrapolation is not safe — Jetson MVE required.
|
||||
- **Source**: Source #51 (DPVO / DPV-SLAM canonical), Source #52 (DPVO-QAT++ Nov 2025)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 / C5 implementer
|
||||
- **Confidence**: ✅ for "VO only, no IMU fusion" and the memory footprints; ⚠️ for Jetson Orin Nano direct runtime (no measurement); ⚠️ for the operational complexity of the QAT pipeline (teacher-student distillation training is a significant prerequisite vs the classical VINS-* / OpenVINS / OKVIS2 candidates).
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 conditional candidate (VO not VIO; needs external IMU wrapper)
|
||||
- **Fit Impact**: **NOT a drop-in C1 candidate; conditional fit only.** DPVO is **not** a substitute for VINS-Mono / OpenVINS / OKVIS2 — it is a candidate for the *VO half* of a hybrid design where C5 (estimator) absorbs IMU and DPVO provides relative-pose priors. This adds design complexity and is **not preferred** unless one of the established VIO candidates fails Jetson MVE for memory reasons. **Status**: secondary, conditional.
|
||||
|
||||
### Fact #35 — Pure VO baseline (KLT optical flow + 5-point essential matrix or homography RANSAC) is the project's mandatory simple-baseline candidate and is the de-facto fallback when learning-based methods fail on Jetson-budget constraints
|
||||
- **Statement**: The classical pipeline — Shi-Tomasi or FAST corner detection → KLT pyramidal optical flow tracking (`cv::calcOpticalFlowPyrLK`) → 5-point essential matrix (Nister, `cv::findEssentialMat`) or homography RANSAC (`cv::findHomography`) → relative pose with arbitrary scale → metric-scale alignment via IMU integration externally — is the foundational visual-odometry pipeline implemented in OpenCV samples and pedagogical repositories. For the project's nadir-down UAV at 1 km AGL over Ukrainian steppe (predominantly planar terrain, low relief), the **homography path is geometrically appropriate** (a plane induces a homography between two views); for non-planar relief, the **essential-matrix path is appropriate** at a small overhead. License: public domain / OpenCV-Apache-2.0 / MIT (whatever reference implementation is chosen) — permissive. Reference: representative public Monocular-Video-Odometery (MIT, alishobeiri 2018), Monocular-Visual-Odometry (Yacynte) at translation error 0.94% / rotation error 0.015°/m on KITTI dataset.
|
||||
- **Source**: Source #53 (OpenCV docs + reference implementations)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer + risk reviewer
|
||||
- **Confidence**: ✅
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 Simple-baseline candidate (mandatory per Component Option Breadth rule)
|
||||
- **Fit Impact**: **carry as the project's `Simple baseline / known-runnable / known-failure-mode` C1 fallback.** Not a lead, but mandatory presence. Failure modes: (a) low-texture cropland / snow → KLT track loss; (b) sharp turns → low-overlap homography degeneracy; (c) no native IMU fusion → must wrap with external metric-scale alignment (same wrapper as DPVO). **Status**: simple-baseline reference; cited in `solution_draft01` to anchor the failure analysis.
|
||||
|
||||
### Fact #36 — Step-0.5-time-window assessment: VINS-Mono / VINS-Fusion master branches are at the Critical-novelty 18-month boundary; OpenVINS and OKVIS2 are within window; DPVO is borderline; the established baselines (KLT + RANSAC) are exempt
|
||||
- **Statement**: Per Step 0.5 timeliness assessment in `00_question_decomposition.md`, Critical-novelty topics require sources within 6 months for SOTA claims and 18 months for established libraries' API behaviour. Audit at access time 2026-05-07: VINS-Mono master last meaningful commit 2024-02-25 → ~27 months → **just over the 18-month window**; VINS-Fusion 2024-05-23 → ~24 months → just over; OpenVINS master active (issue threads through Feb 2025) and v2.7 release June 2023 → ~35 months for the tagged release but master in stable maintenance → within de-facto window for an established library; OKVIS2-X push 2026-03-17 → ~2 months → **fully within window**; DPVO last code update 2024-10-12 → ~19 months → just over but DPV-SLAM ECCV 2024 keeps the algorithm class within 6-month claim window; KLT / 5-point / RANSAC / homography → established baselines per Step 0.5 → **no time window applies**. **Implication**: VINS-Mono / VINS-Fusion fall into the "older than 18 months but classical authoritative reference" bucket — Step 0.5 allows up to 18 months strictly, but downstream forks (vins-mono-android, embedded variants) and the IEEE T-RO 2018 publication keep the algorithm class in active community use. Recommended treatment: **keep as candidates but require live MVE on Jetson Orin Nano Super before promotion to Selected**, to revalidate against the current OpenCV / Ceres / ROS 2 stack.
|
||||
- **Source**: Source #43, Source #44, Source #45, Source #47, Source #48, Source #51 (timeliness audit per source)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: Step-7.5 reviewer + System architects
|
||||
- **Confidence**: ✅
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 candidate-pool integrity
|
||||
- **Fit Impact**: **applies a conservative timeliness gate: every C1 candidate from VINS-Mono / VINS-Fusion / DPVO requires an Orin-Nano-Super MVE before being marked Selected**, since their master-branch staleness pushes them out of the Critical-novelty 18-month window. OpenVINS / OKVIS2 / OKVIS2-X / Kimera are within window via active issue threads or recent releases.
|
||||
|
||||
### C1 Component Applicability Gate — preliminary table (this session; structured Restrictions×AC sub-matrix per candidate is next session's work)
|
||||
|
||||
| Candidate | Mode (project) | License | Active maintenance? | Jetson Orin Nano Super runnable? | Native IMU fusion? | Native metric scale? | License blocks dual-use? | Preliminary status |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| **VINS-Mono** | mono+IMU | GPL-3.0 (copyleft) | ⚠️ borderline (24 mo) | ✅ proven on Jetson Nano (2021) → Orin Nano Super virtually certain | ✅ | ✅ | **⚠️ Verify with user** | Lead candidate **conditional on user license decision** + Orin-Nano-Super MVE |
|
||||
| **VINS-Fusion** | mono+IMU (mode) | GPL-3.0 | ⚠️ borderline (24 mo) | ⚠️ failed on TX2 (KAIST 2021); Orin Nano Super untested | ✅ | ✅ | **⚠️ Verify with user** | Alternate, secondary to VINS-Mono within HKUST family |
|
||||
| **OpenVINS** | mono+IMU | GPL-3.0 | ✅ active master | ✅ build confirmed on Orin Nano Dev Kit + JetPack 6 (2024 + 2025 community evidence); ~270 ms latency on Xavier NX | ✅ MSCKF | ✅ | **⚠️ Verify with user** | **Lead candidate** **conditional on user license decision** (best Jetson-Orin-Nano evidence + most maintained of the GPL-3 trio) |
|
||||
| **OKVIS2 / OKVIS2-X** | mono+IMU (+ optional GNSS) | BSD-3 | ✅ very active (2026 pushes) | ⚠️ no direct Jetson Orin Nano measurement; factor-graph backbone plausibly heavier than MSCKF | ✅ | ✅ | ✅ no | **Lead candidate by license + maintenance + spoof-promotion architectural alignment**, pending Jetson MVE |
|
||||
| **Kimera-VIO** | mono+IMU (optional) | BSD-2 | ✅ active | ⚠️ failed on Xavier NX 8 GB shared under multi-process (KAIST 2021) | ✅ | ✅ | ✅ no | Fallback secondary; resource overhead poor fit for project |
|
||||
| **DROID-SLAM** | mono VO/SLAM only | (project repo) | reference baseline | ❌ ≥11 GB GPU VRAM > 8 GB AC-4.2 budget | ❌ | ❌ (arbitrary scale) | n/a | **DISQUALIFIED** by AC-4.2 |
|
||||
| **DPVO / DPV-SLAM** | mono VO only | MIT | ⚠️ borderline (19 mo on code, ECCV 2024 paper) | ⚠️ DPVO-QAT++ (Nov 2025) shows 1.02 GB peak on RTX 4060 desktop; Jetson Orin Nano untested | ❌ (needs external IMU wrapper) | ❌ (needs external scale alignment) | ✅ no | Conditional secondary — VO half of a hybrid C1+C5 design only; not a drop-in VIO replacement |
|
||||
| **Pure VO baseline (KLT + 5pt RANSAC / homography)** | mono VO only | OpenCV-Apache-2.0 / MIT | ✅ foundational (no time window) | ✅ runs on any Jetson | ❌ (needs external IMU wrapper) | ❌ (needs external scale alignment) | ✅ no | **Mandatory simple-baseline reference** per Component Option Breadth rule |
|
||||
|
||||
**Surviving lead candidates (preliminary)**, in priority order based on this session's evidence:
|
||||
1. **OpenVINS** (GPL-3.0, MSCKF, best Jetson Orin Nano evidence) — pending user license decision + Orin-Nano-Super MVE
|
||||
2. **OKVIS2 / OKVIS2-X** (BSD-3, factor-graph + GNSS-fusion alignment, most active maintenance) — pending Jetson MVE
|
||||
3. **VINS-Mono** (GPL-3.0, sliding-window optimization, proven on Jetson Nano) — pending user license decision + Orin-Nano-Super MVE
|
||||
4. **Pure VO baseline** (mandatory simple-baseline; runtime guaranteed; carries the project as a graceful fallback)
|
||||
|
||||
**Disqualified outright**: DROID-SLAM (AC-4.2 memory budget), RTAB-Map and ORB-SLAM3 (already pruned by Fact #16).
|
||||
|
||||
**Conditional / not-direct-fit**: DPVO / DPV-SLAM (VO not VIO, needs external IMU wrapper), Kimera-VIO (resource overhead unjustified for narrow C1 mandate).
|
||||
|
||||
### C1 Open Decisions (to be resolved before SQ3+SQ4 closure)
|
||||
|
||||
**Decision D-C1-1 — GPL-3.0 license posture for the onboard binary** (BLOCKING for the GPL-3.0 trio: VINS-Mono / VINS-Fusion / OpenVINS).
|
||||
- The three most established VIO candidates (VINS-Mono / VINS-Fusion / OpenVINS) are GPL-3.0 (viral copyleft).
|
||||
- For dual-use UAV deployment, GPL-3 binary distribution to a customer triggers obligations: source-code disclosure for the entire linked binary, anti-tivoization clauses for embedded firmware updates, viral effect on any proprietary code linked into the same binary.
|
||||
- BSD/MIT alternatives exist (OKVIS2 BSD-3, Kimera BSD-2, DPVO MIT, pure-VO baseline OpenCV-Apache-2.0), but each comes with secondary trade-offs (Jetson MVE risk, missing IMU fusion, resource overhead).
|
||||
- Three options for the user:
|
||||
- **(a)** Accept GPL-3.0 — distribution model = release source on customer request; or operate the system as a service rather than transferring binaries. Lowest-risk algorithmic path (most-tested candidates).
|
||||
- **(b)** Restrict to permissive licenses only (BSD/MIT) — lead candidate becomes OKVIS2; carries Jetson MVE risk.
|
||||
- **(c)** Keep both options open through the design phase — make the final license decision after the Jetson Orin Nano MVE results are in.
|
||||
- **Recommended default**: **(c)** — defer the binary commitment until empirical evidence on Jetson Orin Nano. This is recorded as a flagged decision; SQ3+SQ4 candidate matrix will carry both license families to Step 7.5.
|
||||
|
||||
**Decision D-C1-2 — Acceptance of Jetson Orin Nano MVE as a Step-7.5 prerequisite** (procedural).
|
||||
- Per the Per-Mode API Capability Verification rule, every lead candidate library/SDK requires `context7` (or equivalent docs) lookup + a Minimum Viable Example for the project's pinned mode + per-numbered-Restriction × per-numbered-AC sub-matrix.
|
||||
- The Component Applicability Gate above is **preliminary** — it documents enumeration evidence but does NOT yet contain `context7` per-mode capability verification or the structured sub-matrix.
|
||||
- **Next session's mandatory work**: `context7` lookup (3 mandatory queries) for OpenVINS / OKVIS2 / VINS-Mono; per-Restriction × per-AC sub-matrix per candidate; the same for the simple-baseline path; record into `../02_fact_cards/C1_vio.md` per the engine template + `../06_component_fit_matrix/C1_vio.md` per Step 7.5.
|
||||
|
||||
### C1 Boundary check: candidate enumeration is saturated for this session
|
||||
|
||||
Saturation signals observed: (a) all 7 named candidates from `00_question_decomposition.md` C1 row enumerated with at least one canonical L1 source per candidate; (b) Jetson Orin Nano runtime evidence located for OpenVINS (direct) and VINS-Mono (Jetson Nano + RPi CM4); other candidates carry "MVE required" gates explicitly; (c) license diversity covered (GPL-3.0 trio + BSD-permissive duo + MIT + permissive-baseline); (d) explicit disqualifications recorded with cited evidence (DROID-SLAM, RTAB-Map, ORB-SLAM3). **Open**: per-mode `context7` verification (BLOCKING per rule) + Restrictions×AC sub-matrices (BLOCKING per Step 7.5) — explicitly deferred to next session.
|
||||
|
||||
---
|
||||
|
||||
## C1 — Per-Mode API Capability Verification (engine Step 2 — Mandatory `context7` lookup) [2026-05-08 session]
|
||||
|
||||
This section closes the per-mode API capability verification gate for the four C1 lead candidates. Each candidate has a pinned-mode statement, three documentary `context7` (or equivalent) queries answered, an MVE block, and a per-numbered-Restriction × per-numbered-AC sub-matrix. The candidates' final lead-promotion to "Selected" status remains gated by the dedicated Jetson Orin Nano Super hardware MVE (D-C1-2 deferred phase).
|
||||
|
||||
### Fact #37 — OpenVINS per-mode API capability verification (mono+IMU on Jetson Orin Nano Super) — DOCUMENTARY PASS; Jetson MVE pending
|
||||
- **Statement**: OpenVINS (`/rpng/open_vins`, master) exposes monocular / stereo / multi-camera + IMU as first-class launch configurations via `subscribe.launch.py` declared launch arguments `use_stereo` (bool) and `max_cameras` (int). The project's **pinned mode** is monocular + IMU, selected via `use_stereo:=false max_cameras:=1` with `config:=` pointing to a project-tuned `estimator_config.yaml`. **Mode-enumeration query (1/3)**: confirms 3 sensor configurations at the launch layer; supported IMU intrinsic models = KALIBR + RPNG (per `propagation-analytical.dox`). **Pinned-mode runnable example query (2/3)**: confirms `ros2 launch ov_msckf subscribe.launch.py config:=euroc_mav` is the documented runnable example; `euroc_mav` defaults to stereo per `subscribe.launch.py` but `use_stereo:=false max_cameras:=1` selects mono-only at runtime — no source patch required. **Disqualifier-probe query (3/3)**: did NOT surface any documented sub-20-Hz validation, hard frame-rate floor, or hard image-resolution ceiling in the master docs; the documented Xavier-NX latency baseline (~270 ms per rpng/open_vins issue #164) is below the AC-4.1 400 ms p95 budget head-room **at 640×480** but unverified at the project's 5472×3648 nav frames. The Jetson Orin Nano Dev Kit + JetPack 6 + ROS 2 Humble build patch is documented (rpng/open_vins issue #421 + fdcl-gwu/openvins_jetson_realsense). **Pinned-mode sentence**: "We will use **OpenVINS** in **monocular + IMU mode** with inputs `{1× ADTi 20MP nav frame stream + FC IMU via MAVLink/SCALED_IMU2}` and expect outputs `{6-DoF pose at IMU rate with covariance from MSCKF state, source label visual_propagated when no satellite anchor}` on `Jetson Orin Nano Super (8 GB shared, JetPack 6, ROS 2 Humble)`."
|
||||
- **Source**: Source #54 (context7), Source #45 (canonical OpenVINS), Source #46 (KAIST Jetson benchmark for class-level comparison)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer + Step-7.5 reviewer
|
||||
- **Confidence**: ✅ for mode-enumeration and runnable-example documentary evidence; ⚠️ for sub-20-Hz validation and 5472×3648 latency (no documentary evidence — Jetson MVE will resolve)
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 lead candidate — per-mode API capability verification gate
|
||||
- **Fit Impact**: **DOCUMENTARY PASS for the per-mode API capability verification gate**; promotes OpenVINS to "lead candidate, documentary verification complete" status in `../06_component_fit_matrix/C1_vio.md` row. License-track decision (D-C1-1) still gates final Selected promotion (OpenVINS = GPL-3.0, lives in track A); Jetson Orin Nano Super hardware MVE (D-C1-2) still gates accuracy/latency/memory empirical promotion.
|
||||
|
||||
### Fact #38 — VINS-Mono per-mode API capability verification (mono+IMU on Jetson Orin Nano Super) — DOCUMENTARY PASS WITH FRAME-RATE CAVEAT; Jetson MVE pending
|
||||
- **Statement**: VINS-Mono (`HKUST-Aerial-Robotics/VINS-Mono`, master) is a single-mode system: "real-time SLAM framework for **Monocular Visual-Inertial Systems**" (README §1) — no mode enumeration is required because the pinned mode IS the only mode. **Mode-enumeration query (1/3)**: VINS-Mono is single-mode = mono+IMU; cross-source documentary evidence from VINS-Fusion `context7` confirms the same authors continue to ship `euroc_mono_imu_config.yaml` as a first-class config in the active fork (per the Per-Mode API rule, VINS-Fusion's mono+IMU mode is a separately-cataloged candidate, but the algorithmic core and required calibration surface are identical — see Fact #29). **Pinned-mode runnable example query (2/3)**: README §3.1.1 — `roslaunch vins_estimator euroc.launch` + EuRoC MH_01 bag is the canonical runnable example; supports online camera-IMU extrinsic calibration (`estimate_extrinsic:=2`), online temporal calibration (`estimate_td:=1`), and rolling-shutter cameras with documented calibration ceiling (`reprojection error <0.5 px`). Pinhole + MEI camera models supported. Camera intrinsics + IMU noise must be calibrated (Kalibr or equivalent). **Disqualifier-probe query (3/3)**: README §5.1 explicitly states *"The image should exceed 20Hz and IMU should exceed 100Hz."* — this is a documentary minimum-rate recommendation and is **below the project's 3 fps nav-camera target by ~6.7×**. See Fact #40 for the geometric analysis and the cross-cutting frame-rate-sensitivity finding. Ceres Solver dependency is pinned to v1.14.0 (build issues at ≥2.0.0 per README §1.2); JetPack-shipped Ceres versions need explicit verification. License: GPLv3 (README §8). **Pinned-mode sentence**: "We will use **VINS-Mono** in **monocular + IMU mode** with inputs `{1× ADTi 20MP nav frame stream (target 3 fps; under documentary 20 Hz floor) + FC IMU via MAVLink/SCALED_IMU2}` and expect outputs `{6-DoF pose at IMU rate via sliding-window optimization with covariance from optimization Hessian, loop closure via DBoW2}` on `Jetson Orin Nano Super (8 GB shared, JetPack 6, Ceres v1.14.0 build)`."
|
||||
- **Source**: Source #55 (VINS-Mono README + VINS-Fusion context7 cross-source), Source #43 (canonical VINS-Mono), Source #46 (KAIST Jetson benchmark for class-level comparison)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer + Step-7.5 reviewer
|
||||
- **Confidence**: ✅ for mode-enumeration (single mode by construction) and runnable-example evidence; ⚠️ for sub-20-Hz operation (documentary minimum-rate recommendation contradicts project frame-rate target); ⚠️ for Ceres v1.14.0 vs JetPack 6 stock Ceres compatibility
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 lead candidate — per-mode API capability verification gate
|
||||
- **Fit Impact**: **DOCUMENTARY PASS WITH FRAME-RATE CAVEAT**. Per the engine rule's escalation tier, the candidate is downgraded from "documentary lead" to **"Experimental only — sub-20-Hz operation requires Jetson MVE validation"** until the deferred Jetson hardware MVE explicitly measures VINS-Mono at the project's 3 fps. License-track decision (D-C1-1) still gates final Selected promotion (VINS-Mono = GPL-3.0, lives in track A).
|
||||
|
||||
### Fact #39 — OKVIS2 per-mode API capability verification (mono+IMU on Jetson Orin Nano Super) — DOCUMENTARY PASS; Jetson MVE pending
|
||||
- **Statement**: OKVIS2 (`smartroboticslab/okvis2`, main) is a keyframe-based factor-graph VI-SLAM with multi-camera + IMU support; the README documents coordinate-frame contract (`W` world / `C_i` cameras / `S` IMU / `B` body), state representation (`T_WS` pose + velocity + gyro/accel biases), and a two-callback API (`setOptimisedGraphCallback` for batch updates incl. loop closure + `setImuCallback` for high-rate prediction). **Mode-enumeration query (1/3)**: README + example apps confirm modes = mono / stereo / multi-camera (i-th camera frame `C_i`) — IMU is mandatory (`okvis::ViSensorBase::setImuCallback` is required). The example apps are `okvis_app_synchronous` (dataset replay), `okvis_app_realsense` (live D435i/D455), `okvis_app_realsense_record` (recording). ROS 2 build is opt-in (`BUILD_ROS2=ON`); ROS 2 launch files: `okvis_node_realsense.launch.xml`, `okvis_node_realsense_publisher.launch.xml`, `okvis_node_subscriber.launch.xml`, `okvis_node_synchronous.launch.xml`. **Pinned-mode runnable example query (2/3)**: README "Running the demo application" + "Configuration files" section — `./okvis_app_synchronous <config>.yaml <EuRoC_MH_01_easy_dir>` is the canonical mono dataset-replay example; the EuRoC config in `config/` is the documentary mono+IMU launch reference. Configuration trade-off surface: "various options to trade-off accuracy and computational expense as well as to enable online calibration" — explicit acknowledgement of latency/accuracy tuning surface. **Disqualifier-probe query (3/3)**: README does NOT state an explicit minimum image rate (cf. VINS-Mono's 20 Hz). OKVIS2's keyframe-based architecture inherently selects only "informative" frames for optimization, which is a structural advantage at lower input frame rates compared to sliding-window optimization. Optional LibTorch sky-segmentation CNN (`USE_NN`) can be disabled with `USE_NN=OFF` to remove the Jetson LibTorch dependency. License: 3-clause BSD (README "License" section). Health warning: "good results (or results at all) may only be obtained with appropriate calibration" — Kalibr-based intrinsic + extrinsic + IMU noise + tight time sync mandatory (this is shared with all VI candidates). OKVIS2-X (T-RO 2025) extends with optional GNSS fusion — architecturally aligned with the project's spoof-promotion path (per Fact #31). **Pinned-mode sentence**: "We will use **OKVIS2** (with `BUILD_ROS2=ON USE_NN=OFF`) in **monocular + IMU mode** with inputs `{1× ADTi 20MP nav frame stream + FC IMU via MAVLink/SCALED_IMU2 → re-published to /okvis/cam0/image_raw + /okvis/imu0}` and expect outputs `{6-DoF pose with covariance from factor-graph optimization via setOptimisedGraphCallback + high-rate IMU-predicted state via setImuCallback}` on `Jetson Orin Nano Super (8 GB shared, JetPack 6, ROS 2 Humble)`."
|
||||
- **Source**: Source #56 (OKVIS2 README), Source #47 (canonical OKVIS2 paper arXiv:2202.09199), Source #48 (OKVIS2-X T-RO 2025)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer + Step-7.5 reviewer
|
||||
- **Confidence**: ✅ for mode-enumeration, runnable-example, and lower-frame-rate-tolerance arguments; ⚠️ for direct 3 fps validation (no documentary measurement — Jetson MVE will resolve); ⚠️ for direct Jetson Orin Nano measurement (Fact #31 noted no direct measurement; community evidence less abundant than OpenVINS)
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 lead candidate — per-mode API capability verification gate
|
||||
- **Fit Impact**: **DOCUMENTARY PASS for the per-mode API capability verification gate**; promotes OKVIS2 to "lead candidate, documentary verification complete" status in `../06_component_fit_matrix/C1_vio.md` row. OKVIS2's keyframe-based architecture is the **only candidate** of the four leads with a structural argument for tolerating sub-20-Hz operation — this re-orders the per-license-track lead ranking (see Fact #41 locked-in defaults). License-track decision (D-C1-1) does NOT gate OKVIS2 (BSD-3 already permissive); Jetson Orin Nano Super hardware MVE (D-C1-2) still gates empirical accuracy/latency/memory promotion.
|
||||
|
||||
### Fact #40 — Cross-cutting C1 finding: project's 3 fps nav-camera target is below VINS-Mono's documented 20 Hz minimum-rate recommendation; affects all sliding-window VIO candidates; OKVIS2's keyframe architecture is the structural mitigant
|
||||
- **Statement**: VINS-Mono README §5.1 documents "The image should exceed 20Hz and IMU should exceed 100Hz" as the recommended minimum-rate operating envelope (Source #55). The project's nav-camera processing target is 3 fps per `00_question_decomposition.md` Project Constraint Matrix. **Geometric analysis**: at 60 km/h cruise = 16.7 m/s × (1/3 s) = 5.5 m of forward motion between consecutive nav frames; at 1 km AGL with 12 cm/px GSD, that motion projects to ~46 px of in-image displacement (~0.84% of the 5472 px frame width) — **well within KLT-trackable range** for the nadir-down camera geometry, so the rate floor is NOT geometrically unreachable. **However**: the documented recommendation is about temporal-stability assumptions (motion-blur tolerance, IMU pre-integration noise growth, sliding-window optimisation Jacobian conditioning), not about geometric trackability. **Cross-candidate impact**: (a) **VINS-Mono** — sliding-window optimisation, full graph re-linearisation per keyframe, 20 Hz documentary recommendation explicitly violated by 6.7× → ⚠️ Experimental only until Jetson MVE measures actual sub-20-Hz behaviour; (b) **VINS-Fusion** — same algorithmic core as VINS-Mono mono+IMU mode, same caveat applies; (c) **OpenVINS** — MSCKF-based with sliding-window state + sparse feature constraints, has documented variable-rate tolerance via `init_imu_thresh`/`init_window_time` config, but no documentary sub-20-Hz validation surfaced in `context7` queries → ⚠️ Verify via Jetson MVE; (d) **OKVIS2** — keyframe-based, structurally selects only informative frames for optimization; the architecture is more naturally tolerant of variable / lower input rates → preferred candidate at low input frame rates; ✅ structural argument; (e) **Pure VO baseline** (KLT+RANSAC) — requires sufficient feature overlap between consecutive frames; at 0.84% in-image displacement this is well within KLT capture range; ✅ no rate-floor concern. **Architectural alternative for design-phase consideration**: instead of binding all C1 candidates to 3 fps, the nav-camera input pipeline could fork — full-resolution 5472×3648 at 3 fps for VPR/satellite-anchor (C2/C3) and a binned/cropped 1368×912 (or 640×480) at higher rate (≥10 fps) into the VIO front-end. ADTi 20MP 20L V1 (APS-C) bandwidth at full-res caps near 5–7 fps over USB 3 (≈2–3 GB/s raw); binned modes typically 3–10× the rate. This is a Plan-time decision, not a research-time one, but the option must be carried into Plan and the Jetson MVE must measure both single-rate and dual-rate paths.
|
||||
- **Source**: Source #55 (VINS-Mono README §5.1), Source #43 (canonical), restrictions.md "Cameras" section + `00_question_decomposition.md` Project Constraint Matrix (3 fps target)
|
||||
- **Phase**: Phase 2
|
||||
- **Target Audience**: System architects + C1 implementer + Plan-phase reviewer + Jetson MVE owner
|
||||
- **Confidence**: ✅ for the documentary 20 Hz minimum-rate recommendation; ✅ for geometric trackability calculation; ⚠️ for the binned/dual-rate pipeline option (camera-bandwidth estimate is plausible but needs ADTi datasheet verification at Plan time)
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 frame-rate sensitivity (cross-candidate); SQ4 (per-candidate runtime envelope binding)
|
||||
- **Fit Impact**: **(a)** Re-orders the per-license-track candidate ranking — within the BSD/permissive track, OKVIS2 strengthens its lead via structural keyframe argument; within the GPL-3.0 track, OpenVINS retains lead over VINS-Mono on this specific dimension because MSCKF's variable-rate tolerance is more documented than VINS-Mono's full-window optimisation. **(b)** Adds a Plan-phase decision: **single-rate (3 fps to all consumers) vs dual-rate (binned high-rate to VIO + full-res 3 fps to VPR/satellite)** — this becomes an explicit deliverable for the Plan phase, not the Jetson MVE phase, because the nav-camera input pipeline shape feeds into both C1 and C2/C3 candidate scoring. **(c)** Marks all VINS-* candidates as ⚠️ Experimental-only until the deferred Jetson hardware MVE explicitly measures sub-20-Hz behaviour.
|
||||
|
||||
### Fact #41 — D-C1-1 + D-C1-2 locked-in research-time defaults (after user-skipped clarification, 2026-05-08)
|
||||
- **Statement**: The user invoked `/autodev` and was presented with structured AskQuestion prompts for D-C1-1 (GPL-3.0 license posture) and D-C1-2 (Jetson MVE schedule); the user **skipped the questions with the directive "continue with the information you already have"**. Per autodev meta-rule "Critical Thinking" — locked-in research-time defaults selected to preserve maximum future optionality and to honour the documentary evidence already gathered: **D-C1-1 = (c) "Keep both license tracks open"** — rank GPL-3.0 leads (OpenVINS, VINS-Mono, VINS-Fusion) in parallel with BSD-permissive OKVIS2/OKVIS2-X; **carry both license tracks through Plan**; final license decision deferred to post-Jetson-MVE/Plan time when empirical evidence is available. **D-C1-2 = (b) "Defer Jetson MVE to a dedicated bring-up phase between research and Plan"** — research closes with documentary ranking + explicit "Jetson MVE pending" gates per candidate; the dedicated Jetson Orin Nano Super hardware MVE phase produces a single MVE artifact that promotes leads to "Selected" before Plan starts. The Plan phase MUST NOT lock a final C1 candidate before the deferred Jetson MVE artifact is produced and reviewed. **These defaults are explicitly tagged as user-deferred** — the user retains the right to revisit either decision at Plan time without losing the research artifact (both license tracks fully cataloged; both lead candidates carry full per-mode evidence).
|
||||
- **Source**: User clarification skip during 2026-05-08 `/autodev` invocation; autodev meta-rule "Critical Thinking"; greenfield-flow Step 14 (Plan) precondition rule
|
||||
- **Phase**: Phase 2 — process decision
|
||||
- **Target Audience**: System architects + Plan-phase reviewer + Step-7.5 reviewer
|
||||
- **Confidence**: ✅ (defaults selected and tagged as user-deferred; user can override at any later prompt)
|
||||
- **Related Dimension**: SQ3+SQ4 / C1 process gate; cross-cutting onto C2–C10 (license posture decision is project-wide, not C1-specific)
|
||||
- **Fit Impact**: **PROCESS GATE CLOSURE for C1**. Allows research to proceed past C1 to C2 (VPR) candidate enumeration without requiring user input now. The Plan phase MUST surface D-C1-1 again as a structured A/B/C decision before any C1 candidate is locked, AND MUST require the deferred Jetson MVE artifact as a precondition.
|
||||
|
||||
---
|
||||
|
||||
## C1 — Minimum Viable Example (MVE) Blocks
|
||||
|
||||
### MVE — OpenVINS in monocular + IMU mode
|
||||
- **Source**: Source #54 (context7 → `https://github.com/rpng/open_vins/blob/master/docs/gs-tutorial.dox` ROS 2 launch + `https://github.com/rpng/open_vins/blob/master/docs/gs-datasets.dox` EuRoC config), accessed 2026-05-08
|
||||
- **Inputs in the example**: EuRoC MAV stereo VI dataset (default `config:=euroc_mav` is stereo 2× cameras + IMU); the launch file declares `use_stereo` (default `true`) and `max_cameras` (default `2`) as runtime overrides; setting `use_stereo:=false max_cameras:=1` selects monocular operation against the same `estimator_config.yaml` parameter file with ROS topics `/cam0/image_raw` + `/imu0`
|
||||
- **Outputs in the example**: 6-DoF pose at IMU rate; ROS 1 publishes `/ov_msckf/poseimu`, `/ov_msckf/odomimu`, `/ov_msckf/pathimu`; ROS 2 publishes equivalent topics under the configured namespace
|
||||
- **Project inputs**: 1× ADTi 20MP nav frame stream (5472×3648, target 3 fps) + FC IMU via MAVLink (SCALED_IMU2 at ≥100 Hz)
|
||||
- **Project outputs required**: 6-DoF pose at IMU rate with metric scale + 6×6 covariance + source label `visual_propagated` when no satellite anchor; AC-1.4-compliant 95% covariance ellipse; honest covariance per AC-NEW-4
|
||||
- **Match assessment**: ✅ exact mode match for **mono+IMU**; ⚠️ partial input shape (image-resolution 4–5× larger than EuRoC's 752×480 → latency/memory unverified at full resolution); ⚠️ partial input rate (3 fps vs EuRoC's 20 Hz — see Fact #40)
|
||||
- **If ⚠️ or ❌**: docs do not explicitly disqualify the configuration. The launch surface (`use_stereo`, `max_cameras`, `config_path`) supports the project's mode without source patches. Resolution and rate are **runtime/Jetson-MVE concerns**, not API-mode concerns. → Status: **Documentary lead**; final promotion to "Selected" requires Jetson Orin Nano Super hardware MVE artifact (D-C1-2 deferred phase).
|
||||
|
||||
### MVE — VINS-Mono in monocular + IMU mode (single mode by construction)
|
||||
- **Source**: Source #55 (VINS-Mono README §3.1.1 + cross-source VINS-Fusion `context7` `euroc_mono_imu_config.yaml`), accessed 2026-05-08
|
||||
- **Inputs in the example**: EuRoC MAV monocular VI dataset (the README explicitly notes "Although it contains stereo cameras, we only use one camera"); ROS topics with image rate >20 Hz and IMU rate >100 Hz per README §5.1; pinhole or MEI camera model with intrinsics + distortion calibrated; camera-IMU extrinsic + temporal calibration optional (online estimation supported via `estimate_extrinsic` and `estimate_td` params)
|
||||
- **Outputs in the example**: 6-DoF pose at IMU rate via sliding-window optimization with covariance from optimization Hessian; loop closure via DBoW2; pose-graph save/reuse via `s` keystroke
|
||||
- **Project inputs**: 1× ADTi 20MP nav frame stream (5472×3648, target 3 fps — **below documentary 20 Hz floor**) + FC IMU via MAVLink (SCALED_IMU2 at ≥100 Hz)
|
||||
- **Project outputs required**: same as OpenVINS MVE above
|
||||
- **Match assessment**: ✅ exact mode match (single-mode system, the project's pinned mode IS the only mode); ⚠️ partial input rate (3 fps vs documentary 20 Hz minimum recommendation per Fact #40); ⚠️ partial dependency stack (Ceres v1.14.0 vs JetPack 6 stock Ceres needs verification); ⚠️ partial input resolution (EuRoC 752×480 vs project 5472×3648)
|
||||
- **If ⚠️ or ❌**: README §5.1 *"The image should exceed 20Hz and IMU should exceed 100Hz"* — explicit documentary disqualifier for sub-20-Hz operation absent contrary measurement. Geometric analysis (Fact #40) shows in-image displacement at 3 fps is small (~0.84% of frame width) and KLT-trackable, but the documentary minimum is not validated by the upstream authors at this rate. → Status: **Experimental only** until Jetson MVE explicitly measures sub-20-Hz behaviour, OR until the Plan phase commits to the dual-rate camera pipeline (binned high-rate to VIO + full-res 3 fps to VPR — see Fact #40) which would put VINS-Mono back on a documentary lead path.
|
||||
|
||||
### MVE — OKVIS2 in monocular + IMU mode
|
||||
- **Source**: Source #56 (OKVIS2 README "Running the demo application" + "Building the project with ROS2" + arXiv:2202.09199), accessed 2026-05-08
|
||||
- **Inputs in the example**: EuRoC ASL/ETH dataset directory (e.g., MH_01_easy/) + a config file from the `config/` directory; alternative live input via Realsense D435i/D455 through `okvis_app_realsense`; the i-th camera frame `C_i` in the OKVIS coordinate model permits multi-camera operation but mono is supported when `C_0` is the only configured camera in the YAML
|
||||
- **Outputs in the example**: An `okvis::Trajectory` object that can be queried at any timestamp; updates delivered via `setOptimisedGraphCallback` (batch updates including loop closure) and high-rate prediction via `setImuCallback`; state `T_WS` (pose) + `v_W` (velocity) + `b_g`/`b_a` (gyro/accel biases)
|
||||
- **Project inputs**: 1× ADTi 20MP nav frame stream (5472×3648, target 3 fps) + FC IMU via MAVLink (SCALED_IMU2 at ≥100 Hz) → re-published to `/okvis/cam0/image_raw` + `/okvis/imu0` topics in the ROS 2 build path
|
||||
- **Project outputs required**: same as OpenVINS MVE above
|
||||
- **Match assessment**: ✅ exact mode match for **mono+IMU**; ✅ structural argument for sub-20-Hz tolerance (keyframe-based architecture per Fact #40); ⚠️ partial input shape (image resolution unverified at 5472×3648 — config files in `config/` are tuned for D435i/EuRoC resolutions); ⚠️ partial Jetson Orin Nano direct evidence (no community benchmark surfaced)
|
||||
- **If ⚠️ or ❌**: docs do not explicitly disqualify the configuration; the keyframe architecture is the structural mitigant for the project's frame-rate target. Optional LibTorch sky-segmentation can be disabled with `USE_NN=OFF` to remove the Jetson LibTorch dependency. → Status: **Documentary lead with structural advantage at sub-20-Hz**; final promotion to "Selected" requires Jetson Orin Nano Super hardware MVE artifact (D-C1-2 deferred phase).
|
||||
|
||||
### MVE — Pure VO baseline (KLT optical flow + 5-point essential matrix or homography RANSAC) — IMU-fusion external
|
||||
- **Source**: Source #53 (OpenCV `cv::calcOpticalFlowPyrLK` + `cv::findEssentialMat` + `cv::findHomography` + `cv::Rodrigues` + reference implementation `alishobeiri/Monocular-Video-Odometery` MIT 2018)
|
||||
- **Inputs in the example**: Sequence of monocular grayscale frames; OpenCV cookbook tutorial uses KITTI Odometry sequences (1241×376 at 10 fps, ground-plane motion); reference impl uses webcam at variable rate
|
||||
- **Outputs in the example**: Sequence of relative-pose 3×4 matrices `[R|t]` per frame pair (arbitrary scale via 5-point essential; metric scale recoverable via known scene structure or external IMU integration)
|
||||
- **Project inputs**: 1× ADTi 20MP nav frame stream (5472×3648, target 3 fps); FC IMU consumed by an **external metric-scale wrapper** (loosely-coupled ESKF that integrates IMU between visual updates and rescales the visual-odometry translation to metric units)
|
||||
- **Project outputs required**: same as VIO MVEs above; the external wrapper produces the C5-style covariance because pure VO has no native covariance
|
||||
- **Match assessment**: ⚠️ partial — the visual-odometry stage matches exactly (mono VO → relative pose); the IMU-fusion stage is **NOT in this candidate** and must be a separately-designed external module (loosely-coupled ESKF). At the C1 component scope, this candidate is "VO-only" and explicitly requires C5 to provide IMU fusion and covariance.
|
||||
- **If ⚠️ or ❌**: → Status: **Mandatory simple-baseline reference**, NOT a lead. Used to anchor failure-analysis discussion in `solution_draft01` and as a runnable fallback if all VIO candidates fail Jetson MVE. The external IMU-fusion wrapper for this candidate becomes part of C5 (state estimator) candidate scope, not C1.
|
||||
|
||||
---
|
||||
|
||||
## C1 — Per-numbered-Restriction × Per-numbered-AC Sub-Matrix per Candidate
|
||||
|
||||
> Per Per-Mode API Capability Verification rule item 4: every numbered Restriction line and every numbered Acceptance Criterion is bound to one of `{Pass, Fail, Verify, N/A}` per candidate, with one-line evidence cite. Lines marked N/A are out of C1 scope (handled by C2 / C3 / C4 / C5 / C6 / C7 / C8 / C9 / C10). Cells marked `Verify` block final "Selected" promotion until the Jetson Orin Nano Super hardware MVE phase resolves them.
|
||||
|
||||
### Sub-matrix legend
|
||||
|
||||
- **Pass**: pinned mode satisfies the line with cited documentary evidence
|
||||
- **Fail**: pinned mode contradicts the line with cited documentary evidence
|
||||
- **Verify**: no documentary evidence either way; deferred Jetson MVE phase will resolve
|
||||
- **N/A**: line is irrelevant to C1 (will be bound by C2/.../C10 in their respective rows)
|
||||
|
||||
### Cross-cutting N/A lines (apply to ALL C1 candidates)
|
||||
|
||||
The following AC and Restriction lines are out of C1 scope and are marked N/A for every C1 candidate without per-candidate citation:
|
||||
|
||||
- **All of AC-2.1b** (satellite-anchor registration) — bound by C2 (VPR) + C3 (matcher) + C4 (PnP)
|
||||
- **All of AC-2.2 (cross-domain MRE branch)** — bound by C3 (matcher)
|
||||
- **AC-3.4** (operator re-loc hint) — bound by C8 (FC adapter) + C10 (operator UX)
|
||||
- **All of AC-6.x** (GCS telemetry) — bound by C8
|
||||
- **All of AC-7.x** (AI-camera object localization) — bound outside C1 entirely
|
||||
- **All of AC-8.x** (satellite reference imagery) — bound by C6 (tile cache) + C10 (provisioning)
|
||||
- **All of AC-NEW-3** (FDR records — except the "per-frame estimates with covariance + source-label" line which is a downstream pass-through of C1 output) — bound by C5 (state estimator emits the per-frame record) + system-wide FDR component
|
||||
- **All of AC-NEW-5** (operating environmental envelope: −20 °C to +50 °C, vibration, cooling) — bound by C7 (Jetson runtime / thermal scheduler) + system-wide thermal design
|
||||
- **All of AC-NEW-6** (imagery freshness enforcement) — bound by C6 + C10
|
||||
- **All of AC-NEW-7** (cache-poisoning safety budget) — bound by C5 + C6 + system-wide
|
||||
- **Restriction "Satellite Imagery" entire section** — bound by C6 + C10
|
||||
- **Restriction "Communication protocol (pinned)"** + **"Output to FC"** — bound by C8
|
||||
- **Restriction "Ground station"** — bound by C8
|
||||
|
||||
### OpenVINS — per-numbered binding (C1-relevant lines only; cross-cutting N/A above)
|
||||
|
||||
| Line | Binding | Evidence (one-line cite) |
|
||||
|---|---|---|
|
||||
| AC-1.3 (drift between anchors: <100 m visual-only / <50 m IMU-fused) | **Verify** | OpenVINS produces metric-scale 6-DoF + IMU-fused covariance; absolute drift between anchors is a function of nav-cam frame rate + texture + IMU bias — Jetson MVE on Derkachi flight required |
|
||||
| AC-1.4 (95% covariance ellipse + source label) | **Pass** | MSCKF produces native 6×6 covariance from filter state; source label is a downstream pipeline concern (C5) — OpenVINS provides the covariance input |
|
||||
| AC-2.1a (frame-to-frame registration ≥95% normal flight) | **Verify** | OpenVINS feature-tracking front-end (KLT-based) success rate at 3 fps × 5472×3648 nadir-down low-texture cropland — Jetson MVE on Derkachi flight required |
|
||||
| AC-2.2 (frame-to-frame MRE <1.0 px) | **Verify** | OpenVINS reports per-feature reprojection residuals via the MSCKF measurement model; aggregate MRE under nadir-down low-texture conditions — Jetson MVE measurement |
|
||||
| AC-3.1 (tolerate 350 m outliers ±20° tilt) | **Pass (with Verify scope)** | MSCKF outlier-rejection via Mahalanobis gating is documented; the 350 m / ±20° envelope is an integration boundary owned by C5 — OpenVINS provides the per-feature gate |
|
||||
| AC-3.2 (sharp turns <5% overlap, <200 m drift, <70° heading change) | **Verify** | OpenVINS has documented failure-detection + recovery; recovery via satellite-reference re-localization (AC-3.3) is owned by C2/C3 — OpenVINS must trigger the recovery path, MVE measurement of sharp-turn recovery on Derkachi flight |
|
||||
| AC-3.3 (≥3 disconnected segments via satellite re-localization) | **Pass** | OpenVINS has documented failure-detection + recovery API (`StateOptions`); the re-localization input is provided by C2/C3 |
|
||||
| AC-3.5 (visual blackout + spoofed GPS → dead_reckoned label, ≤400 ms) | **Verify** | OpenVINS internal mode promotion (`SLAM` ↔ `IMU-only propagation`) latency under feature-loss conditions — Jetson MVE measurement; the label-state transition is owned by C5 |
|
||||
| AC-4.1 (latency <400 ms p95) | **Verify** | Documented Xavier NX baseline ~270 ms at 640×480 (Source #45 issue #164); 5472×3648 + Jetson Orin Nano Super at 3 fps unverified — Jetson MVE measurement |
|
||||
| AC-4.2 (memory <8 GB shared) | **Verify** | MSCKF has lower memory footprint than full sliding-window optimization; Jetson Orin Nano Dev Kit build confirmed (Source #45 issue #421) but co-resident memory pressure with C2/C3/C5/C6 not measured |
|
||||
| AC-4.4 (frame-by-frame, no batching) | **Pass** | OpenVINS publishes pose at IMU rate (per Source #54 launch evidence); no batching by design |
|
||||
| AC-4.5 (corrections allowed) | **Pass** | MSCKF natively re-linearises in its sliding window; corrections via state augmentation are documented |
|
||||
| AC-5.1 (initialise from FC EKF's last valid GPS + IMU-extrapolated position) | **Pass** | OpenVINS supports custom initialisation via `init_options` (per Source #54 estimator config); the FC-EKF input is plumbed by C5/C8 |
|
||||
| AC-5.3 (re-initialise on companion reboot from FC IMU-extrapolated position) | **Pass** | Same mechanism as AC-5.1; AC-NEW-1 covers the timing constraint |
|
||||
| AC-NEW-1 (cold-start TTFF <30 s) | **Verify** | OpenVINS initialisation latency under co-resident process startup on Jetson Orin Nano Super — Jetson MVE measurement |
|
||||
| AC-NEW-3 (per-frame estimates with covariance + source-label feed FDR) | **Pass** | OpenVINS publishes pose+covariance at IMU rate; the source-label and FDR pipeline are downstream (C5 + system-wide) |
|
||||
| AC-NEW-4 (false-position safety budget — covariance honesty) | **Pass (with Verify)** | MSCKF produces filter-consistent 6×6 covariance; honest-covariance discipline is shared with C5 (which carries the contract to AC-4.3); covariance under-reporting in the presence of cross-domain matches is a known MSCKF failure mode (Fact #5 family) — Jetson MVE on Derkachi flight required for empirical floor |
|
||||
| AC-NEW-8 (visual blackout + GPS spoofing — IMU-only ≤30 s, label dead_reckoned) | **Pass** | OpenVINS has documented IMU-only propagation mode after visual feature loss; the failsafe-label transition is owned by C5 |
|
||||
| Restriction "Sharp turns are exceptions; consecutive photos may share <5% overlap" | **Verify** | Same as AC-3.2 — Jetson MVE measurement |
|
||||
| Restriction "Navigation camera (pinned): ADTi 20MP 20L V1, 5472×3648" | **Verify** | Image-resolution scaling (16× larger than EuRoC's 752×480 baseline) — Jetson MVE measurement of feature-extraction latency at full-res; binned/cropped path option per Fact #40 |
|
||||
| Restriction "Companion computer (pinned): Jetson Orin Nano Super, 8 GB shared" | **Verify** | Build confirmed (Source #45 issue #421); steady-state co-resident memory pressure unverified — Jetson MVE measurement |
|
||||
| Restriction "High-rate IMU available from FC via MAVLink" | **Pass** | OpenVINS consumes IMU at any rate ≥100 Hz; SCALED_IMU2 at FC's native rate (typically 100–400 Hz) satisfies this |
|
||||
|
||||
### VINS-Mono — per-numbered binding (C1-relevant lines only; cross-cutting N/A above)
|
||||
|
||||
| Line | Binding | Evidence (one-line cite) |
|
||||
|---|---|---|
|
||||
| AC-1.3 (drift between anchors) | **Verify** | Same as OpenVINS; sliding-window optimisation has higher drift than MSCKF in low-texture per academic comparison — Jetson MVE measurement |
|
||||
| AC-1.4 (covariance ellipse + source label) | **Pass** | Sliding-window optimisation produces native covariance from optimization Hessian; source label is C5's concern |
|
||||
| AC-2.1a (frame-to-frame registration ≥95%) | **Fail (documentary) → Verify** | VINS-Mono README §5.1 documents 20 Hz minimum image rate; project's 3 fps is below this floor (Fact #40) → ⚠️ **Experimental only** until Jetson MVE explicitly validates sub-20-Hz operation |
|
||||
| AC-2.2 (MRE <1.0 px) | **Verify** | Same as OpenVINS; reprojection error under sub-20-Hz operation unverified |
|
||||
| AC-3.1 (tolerate 350 m outliers ±20° tilt) | **Pass (with Verify scope)** | VINS-Mono has documented failure-detection + recovery |
|
||||
| AC-3.2 (sharp turns) | **Verify** | Same as OpenVINS; under sub-20-Hz operation, sharp-turn recovery unverified — Jetson MVE measurement |
|
||||
| AC-3.3 (disconnected segments via satellite re-localization) | **Pass** | VINS-Mono has documented failure-recovery; pose-graph reuse via DBoW2 supports re-anchor |
|
||||
| AC-3.5 (visual blackout + spoofed GPS) | **Verify** | Same as OpenVINS |
|
||||
| AC-4.1 (latency <400 ms p95) | **Verify** | Documented on Jetson Nano (Source #43); Orin Nano Super virtually certain to meet but at 5472×3648 unverified — Jetson MVE measurement |
|
||||
| AC-4.2 (memory <8 GB shared) | **Verify** | Same as OpenVINS |
|
||||
| AC-4.4 (frame-by-frame) | **Pass** | VINS-Mono publishes pose at IMU rate |
|
||||
| AC-4.5 (corrections allowed) | **Pass** | Sliding-window optimization re-linearises and supports corrections |
|
||||
| AC-5.1 (initialise from FC EKF) | **Pass** | VINS-Mono has automatic initialization via IMU pre-integration; custom-init from FC EKF is a wiring task |
|
||||
| AC-5.3 (re-initialise on reboot) | **Pass** | Same as AC-5.1 |
|
||||
| AC-NEW-1 (cold-start TTFF <30 s) | **Verify** | VINS-Mono automatic initialization typically takes seconds; Jetson MVE measurement |
|
||||
| AC-NEW-3 (per-frame estimates feed FDR) | **Pass** | Same as OpenVINS |
|
||||
| AC-NEW-4 (covariance honesty) | **Pass (with Verify)** | Same as OpenVINS; sliding-window optimization Hessian is a less-conservative covariance source than MSCKF in some failure modes |
|
||||
| AC-NEW-8 (visual blackout + GPS spoofing) | **Pass (with Verify)** | VINS-Mono has documented failure-detection and IMU-only propagation; failsafe-label transition is C5's |
|
||||
| Restriction "Sharp turns are exceptions" | **Verify** | Same as AC-3.2 |
|
||||
| Restriction "Navigation camera (pinned): 5472×3648" | **Verify** | Same as OpenVINS; **plus** the Fact #40 dual-rate option is an explicit Plan-time consideration to bring VINS-Mono back from Experimental to documentary lead |
|
||||
| Restriction "Companion computer: Jetson Orin Nano Super, 8 GB" | **Verify** | Same as OpenVINS; Ceres v1.14.0 vs JetPack 6 stock Ceres compatibility is an additional sub-verify item |
|
||||
| Restriction "High-rate IMU available from FC via MAVLink" | **Pass** | VINS-Mono consumes IMU at ≥100 Hz; satisfied |
|
||||
|
||||
### OKVIS2 / OKVIS2-X — per-numbered binding (C1-relevant lines only; cross-cutting N/A above)
|
||||
|
||||
| Line | Binding | Evidence (one-line cite) |
|
||||
|---|---|---|
|
||||
| AC-1.3 (drift between anchors) | **Verify** | Factor-graph back-end with loop closure should produce lower drift than non-loop VIO; specific Derkachi-flight measurement deferred to Jetson MVE |
|
||||
| AC-1.4 (covariance ellipse + source label) | **Pass** | OKVIS2 produces 6×6 covariance from factor-graph marginal; source label is C5's concern |
|
||||
| AC-2.1a (frame-to-frame registration ≥95%) | **Pass (structural argument) → Verify** | Keyframe-based selection is structurally tolerant of variable input rates (Fact #40); explicit 3 fps validation deferred to Jetson MVE |
|
||||
| AC-2.2 (MRE <1.0 px) | **Verify** | OKVIS2 has tight reprojection-error inlier rejection in its keyframe matching; aggregate MRE under nadir-down low-texture — Jetson MVE measurement |
|
||||
| AC-3.1 (tolerate 350 m outliers ±20° tilt) | **Pass** | OKVIS2 has Cauchy-loss robust factor graph that tolerates outliers; documented in arXiv:2202.09199 |
|
||||
| AC-3.2 (sharp turns) | **Pass (structural)** | Keyframe selection inherently skips uninformative sharp-turn frames; recovery via re-localization is owned by C2/C3 |
|
||||
| AC-3.3 (≥3 disconnected segments) | **Pass** | OKVIS2 has explicit re-localization API + loop closure; OKVIS2-X adds GNSS-fusion which architecturally aligns with the spoof-promotion path (per Fact #31) |
|
||||
| AC-3.5 (visual blackout + spoofed GPS) | **Verify** | OKVIS2 IMU-only propagation between keyframes is via `setImuCallback`; latency under blackout-trigger — Jetson MVE measurement |
|
||||
| AC-4.1 (latency <400 ms p95) | **Verify** | No documented Jetson Orin Nano measurement (Fact #31); factor-graph is plausibly heavier than MSCKF — Jetson MVE measurement |
|
||||
| AC-4.2 (memory <8 GB shared) | **Verify** | Same as AC-4.1; co-resident memory pressure with C2/C3/C5/C6 unverified |
|
||||
| AC-4.4 (frame-by-frame) | **Pass** | `setImuCallback` provides high-rate prediction; `setOptimisedGraphCallback` provides batch updates including loop closure — both stream frame-by-frame from a consumer perspective |
|
||||
| AC-4.5 (corrections allowed) | **Pass** | Factor-graph re-linearisation on loop closure delivers corrections via `setOptimisedGraphCallback` |
|
||||
| AC-5.1 (initialise from FC EKF) | **Pass** | OKVIS2 supports custom initialisation via the `okvis::ViInterface` API; the FC-EKF input is plumbed by C5/C8 |
|
||||
| AC-5.3 (re-initialise on reboot) | **Pass** | Same mechanism as AC-5.1 |
|
||||
| AC-NEW-1 (cold-start TTFF <30 s) | **Verify** | OKVIS2 initialisation latency under co-resident process startup — Jetson MVE measurement |
|
||||
| AC-NEW-3 (per-frame estimates feed FDR) | **Pass** | OKVIS2 trajectory query at any timestamp via `okvis::Trajectory` supports the FDR pipeline |
|
||||
| AC-NEW-4 (covariance honesty) | **Pass (with Verify)** | Factor-graph marginal covariance is the gold standard for honest covariance among VIO classes; cross-domain match consistency under satellite anchor injection unverified — Jetson MVE measurement |
|
||||
| AC-NEW-8 (visual blackout + GPS spoofing) | **Pass** | OKVIS2 has documented IMU-only propagation between keyframes; OKVIS2-X GNSS-fusion is architecturally aligned with the spoof-promotion path |
|
||||
| Restriction "Sharp turns are exceptions" | **Pass (structural)** | Keyframe selection inherently handles sparse-overlap sharp-turn frames |
|
||||
| Restriction "Navigation camera (pinned): 5472×3648" | **Verify** | Image-resolution scaling — Jetson MVE measurement; OKVIS2 keyframe sub-sampling reduces the per-frame compute compared to per-frame VIO |
|
||||
| Restriction "Companion computer: Jetson Orin Nano Super, 8 GB" | **Verify** | No direct Jetson Orin Nano Super measurement; LibTorch sky-segmentation can be disabled with `USE_NN=OFF` to remove a major Jetson dependency |
|
||||
| Restriction "High-rate IMU available from FC via MAVLink" | **Pass** | `setImuCallback` consumes IMU at any rate ≥100 Hz; satisfied |
|
||||
|
||||
### Pure VO baseline (KLT + 5pt RANSAC / homography) — per-numbered binding (C1-relevant lines only; cross-cutting N/A above)
|
||||
|
||||
| Line | Binding | Evidence (one-line cite) |
|
||||
|---|---|---|
|
||||
| AC-1.3 (drift between anchors — visual-only/IMU-fused) | **Fail (visual-only sub-bound)** | Pure VO has higher drift than VIO; the "<100 m visual-only" sub-bound is achievable, but the "<50 m IMU-fused" requires the external ESKF wrapper (which is part of C5, not this candidate) |
|
||||
| AC-1.4 (covariance ellipse + source label) | **Fail** | Pure VO has no native covariance; covariance is provided by the external ESKF wrapper (C5) |
|
||||
| AC-2.1a (frame-to-frame registration ≥95%) | **Pass** | KLT optical flow at 0.84% in-image displacement (Fact #40 calculation) is well within trackable range |
|
||||
| AC-2.2 (MRE <1.0 px) | **Pass (with Verify)** | OpenCV `findHomography` with RANSAC produces sub-pixel inliers under planar steppe geometry; explicit measurement on Derkachi flight needed |
|
||||
| AC-3.1 (tolerate 350 m outliers ±20° tilt) | **Verify** | RANSAC outlier rejection threshold is tunable; explicit measurement under ±20° airframe tilt needed |
|
||||
| AC-3.2 (sharp turns) | **Fail** | Pure VO has no failure-recovery mechanism; sharp turns trigger KLT track loss; recovery via satellite re-localization (AC-3.3) is owned by C2/C3 — pure VO must signal track loss to C5 |
|
||||
| AC-3.3 (≥3 disconnected segments) | **N/A (handled by C5+C2/C3)** | Pure VO does not have re-localization; the disconnected-segment recovery is C2/C3's job |
|
||||
| AC-3.5 (visual blackout + spoofed GPS) | **N/A (handled by C5)** | Pure VO has no failsafe state; C5 owns the dead_reckoned transition |
|
||||
| AC-4.1 (latency <400 ms p95) | **Pass** | OpenCV KLT + RANSAC at 5472×3648 on Jetson Orin Nano CPU is documented as <100 ms class; latency budget is dominated by image I/O |
|
||||
| AC-4.2 (memory <8 GB shared) | **Pass** | KLT + RANSAC has trivial memory footprint (<100 MB working set) |
|
||||
| AC-4.4 (frame-by-frame) | **Pass** | Pure per-frame algorithm; no batching |
|
||||
| AC-4.5 (corrections allowed) | **N/A (handled by C5)** | Pure VO has no state to correct; C5 owns corrections |
|
||||
| AC-5.1 (initialise from FC EKF) | **N/A (handled by C5)** | Pure VO has no global state; C5 owns the initial pose |
|
||||
| AC-5.3 (re-initialise on reboot) | **N/A (handled by C5)** | Same as AC-5.1 |
|
||||
| AC-NEW-1 (cold-start TTFF <30 s) | **Pass** | Pure VO needs no warm-up beyond first frame pair |
|
||||
| AC-NEW-3 (per-frame estimates feed FDR) | **N/A (handled by C5)** | Pure VO emits relative pose only; FDR records the C5-fused estimate |
|
||||
| AC-NEW-4 (covariance honesty) | **Fail** | Pure VO has no native covariance; honest-covariance discipline is the external wrapper's contract (C5) |
|
||||
| AC-NEW-8 (visual blackout + GPS spoofing) | **N/A (handled by C5)** | Pure VO has no failsafe behavior; C5 owns the IMU-only mode |
|
||||
| Restriction "Sharp turns are exceptions" | **Fail** | Same as AC-3.2 |
|
||||
| Restriction "Navigation camera (pinned): 5472×3648" | **Pass** | KLT runs at any resolution; 5472×3648 may need image pyramid downsampling for runtime — standard OpenCV practice |
|
||||
| Restriction "Companion computer: Jetson Orin Nano Super, 8 GB" | **Pass** | Trivial memory + CPU-bound; no GPU dependency |
|
||||
| Restriction "High-rate IMU available from FC via MAVLink" | **N/A (handled by C5)** | Pure VO does not consume IMU; the external wrapper does |
|
||||
|
||||
**Pure VO baseline summary**: this candidate is **NOT a drop-in C1 VIO replacement**. It is a "VO + external IMU wrapper" two-component design where the external wrapper is owned by C5. As a C1 candidate it Fails AC-1.4 / AC-1.3 IMU-fused / AC-3.2 / AC-NEW-4 because those bindings inherently require IMU fusion which this candidate lacks. **Status remains "mandatory simple-baseline reference"** per Fact #35; the actual C1 fallback if all VIO leads fail Jetson MVE is "Pure VO + custom ESKF wrapper" — which is a Plan-phase design task, not a research-phase candidate.
|
||||
|
||||
---
|
||||
|
||||
## C1 — CLOSURE STATUS [2026-05-08 session]
|
||||
|
||||
C1 is **CLOSED at the documentary level**. All four lead candidates (OpenVINS, OKVIS2, VINS-Mono, Pure VO baseline) have:
|
||||
- ✅ Pinned-mode statement
|
||||
- ✅ Three-query `context7` (or equivalent) lookup with documentary evidence
|
||||
- ✅ MVE block
|
||||
- ✅ Per-numbered-Restriction × per-numbered-AC sub-matrix
|
||||
|
||||
**Final lead promotion to "Selected"** is gated by the **deferred Jetson Orin Nano Super hardware MVE phase** (D-C1-2 default = option (b) per Fact #41) — Plan phase MUST NOT lock a final C1 candidate without consuming the deferred Jetson MVE artifact.
|
||||
|
||||
**Per-license-track preliminary leads** (per Fact #41 default D-C1-1 = option (c) "keep both tracks open"):
|
||||
- **BSD/permissive track lead**: **OKVIS2 / OKVIS2-X** — strongest documentary-mode-fit profile; structural sub-20-Hz tolerance; OKVIS2-X GNSS-fusion architectural alignment with spoof-promotion path (AC-NEW-2). Risk: no direct Jetson Orin Nano Super measurement.
|
||||
- **GPL-3.0 track lead**: **OpenVINS** — best Jetson Orin Nano build evidence; MSCKF formulation more memory-efficient than VINS-Mono; documented Xavier NX 270 ms latency baseline. Risk: documentary 5472×3648 latency unverified.
|
||||
- **GPL-3.0 track alternate**: **VINS-Mono** — single-mode by construction; ⚠️ Experimental only until Jetson MVE explicitly validates sub-20-Hz operation OR Plan commits to dual-rate camera pipeline (Fact #40).
|
||||
|
||||
**Mandatory simple-baseline**: **Pure VO + external ESKF (C5)** — kept as runnable fallback if all VIO leads fail Jetson MVE.
|
||||
|
||||
**Cross-cutting design decision raised by C1 closure**: the **single-rate vs dual-rate nav-camera pipeline** (Fact #40) is now an explicit Plan-phase deliverable, because it materially changes which C1 candidates remain on documentary lead vs Experimental status.
|
||||
|
||||
C1 → C2 transition: ready to proceed to C2 (VPR) candidate enumeration in the next session.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,204 @@
|
||||
# Fact Cards — C6: Tile cache + spatial index
|
||||
|
||||
> Mode A Phase 2 — engine Step 3 (Fact Extraction & Evidence Cards). Bound to sub-questions in `../00_question_decomposition.md` line 74 (C6 = "storage + retrieval of basemap tiles + descriptors, with manifests, freshness, dedup, and write-back"). Sources for C6 cluster live in [`../01_source_registry/C6_tile_cache_spatial_index.md`](../01_source_registry/C6_tile_cache_spatial_index.md).
|
||||
>
|
||||
> Index: [`00_summary.md`](00_summary.md). Sibling components: [C1 VIO](C1_vio.md), [C2 VPR](C2_vpr.md), [C3 Matchers](C3_matchers.md), [C4 Pose](C4_pose_estimation.md), [C5 State estimator](C5_state_estimator.md). Cross-component gates: [`../06_component_fit_matrix/99_cross_component_gates.md`](../06_component_fit_matrix/99_cross_component_gates.md).
|
||||
|
||||
---
|
||||
|
||||
## Scope summary
|
||||
|
||||
C6 batch 1 closed at 2/N on 2026-05-08. **Fact #92** = mandatory simple-baseline (`mirror-of-existing-suite-pattern`: PostgreSQL + pure btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` + filesystem tile storage at `./tiles/{zoom}/{x}/{y}.jpg` + `bytea` descriptor blobs + app-side FAISS in-memory ANN loaded at takeoff). **Fact #93** = modern-competitive-lead-spatial-extension (PostgreSQL + PostGIS GiST on `geography(POINT,4326)` + pgvector HNSW for descriptor ANN + same filesystem tile storage). User-pinned scope: Postgres on Jetson at runtime (option A from `c6_postgres_locus`); satellite-provider pattern is NOT carved in stone — Cand 2 may cascade changes back to satellite-provider IF research reveals MATERIAL improvement (small improvements stay with Cand 1).
|
||||
|
||||
---
|
||||
|
||||
### Fact #92 — Manual mirror of existing parent-suite `satellite-provider` pattern: PostgreSQL btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` + bytea descriptor blobs + app-side FAISS HNSW + filesystem tile storage
|
||||
|
||||
**Statement**: For C6 (tile cache + spatial index), the mandatory simple-baseline candidate is direct-mirror of the parent-suite `satellite-provider` pattern (verified directly via filesystem read at `/Users/obezdienie001/dev/azaion/suite/satellite-provider/` per Source #92):
|
||||
|
||||
- **Geographic spatial index**: PostgreSQL btree composite index `idx_tiles_coordinates ON tiles(tile_zoom, tile_x, tile_y, version)` for spatial-grid range queries at slippy-map integer coordinates; secondary `idx_tiles_composite ON tiles(latitude, longitude, tile_size_meters)` for inverse-geocode lookups. Per Source #93 (PostgreSQL 16 multicolumn-indexes docs): "A multicolumn B-tree index can be used with query conditions that involve any subset of the index's columns, but the index is most efficient when there are constraints on the leading (leftmost) columns. The exact rule is that equality constraints on leading columns, plus any inequality constraints on the first column that does not have an equality constraint, will always be used to limit the portion of the index that is scanned."
|
||||
- **Descriptor ANN over global VPR descriptors**: descriptors stored in `bytea` column on the `tiles` table (one new column added per migration: `descriptor BYTEA NULL`); app-side `faiss.IndexHNSWFlat(d=2048, M=32)` (or `d=1024` for SelaVPR / `d=512` for EigenPlaces per D-C2 final lock) loaded at takeoff via `faiss.read_index(path)` from a pre-serialized FAISS index built during C10 pre-flight cache provisioning. Per Source #96 (FAISS context7): `faiss.IndexHNSWFlat(d, M)` + `index.hnsw.efConstruction=40` + `index.hnsw.efSearch=16-64` is the canonical HNSW pattern matching pgvector's HNSW parameters.
|
||||
- **Raw tile storage**: filesystem at canonical slippy-map path `./tiles/{tile_zoom}/{tile_x}/{tile_y}.{image_type}` per Source #92 satellite-provider README + migration 011; DB stores `file_path VARCHAR(500)` pointer.
|
||||
- **Slippy-map coordinate transform**: `tile_x = FLOOR((lon + 180) / 360 * POWER(2, zoom))::INT` + `tile_y = FLOOR((1 - LN(TAN(RADIANS(lat)) + 1.0 / COS(RADIANS(lat))) / PI()) / 2.0 * POWER(2, zoom))::INT` per Source #92 migration 011 (matches Source #98 OSM canonical convention exactly).
|
||||
|
||||
**Mode pinning** (per-mode API verification rule):
|
||||
- inputs: `(query_lat, query_lon, query_alt_m)` from C5 state estimator @ 3 Hz; `(query_descriptor: numpy.ndarray of shape (d,) and dtype float32)` from C2 VPR @ 3 Hz; `(operator_reloc_hint_lat, hint_lon, hint_zoom)` rare per AC-3.4
|
||||
- outputs:
|
||||
- geographic-spatial-grid query: `[(tile_id, tile_x, tile_y, file_path, descriptor_bytea), ...]` returning K=9 (3x3 grid) to K=25 (5x5 grid) candidate tiles at `tile_zoom = Z_target` (typically Z=18 per project)
|
||||
- descriptor-ANN query: `[(tile_id, tile_x, tile_y, file_path, l2_distance), ...]` returning top-K=10 descriptor-similar tiles via FAISS HNSW
|
||||
- combined query: app-side intersection of the above two — **geographic-prefilter-then-descriptor-rerank** (canonical hierarchical retrieval pattern per Fact #21 SQ2 conclusion line 32 in source-registry/00_summary.md)
|
||||
- runtime: PostgreSQL 16 + psycopg-binary (Python driver) + FAISS-CPU on Jetson Orin Nano Super (8 GB shared, JetPack 6, Ubuntu 22.04 base) per Source #97 confirmation (Postgres-on-Jetson Medium article March 2026 confirms full Postgres + pgvector deployment works on Orin Nano)
|
||||
|
||||
**Source**:
|
||||
- Primary: Source #92 (parent-suite `satellite-provider` direct filesystem read of README + migrations 001/003/011 — confirms PostgreSQL + pure btree + filesystem pattern with NO PostGIS/extensions)
|
||||
- Btree multicolumn semantics: Source #93 PostgreSQL 16 official docs at <https://www.postgresql.org/docs/current/indexes-multicolumn.html> ("A multicolumn B-tree index can be used with query conditions that involve any subset of the index's columns, but the index is most efficient when there are constraints on the leading (leftmost) columns")
|
||||
- Slippy-map convention: Source #98 OpenStreetMap Foundation canonical reference at <https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames> (zoom 0 = 1 tile world, zoom 18 = city block detail; Web Mercator EPSG:3857 from EPSG:4326)
|
||||
- FAISS HNSW Python API: Source #96 context7-indexed at `/facebookresearch/faiss` — confirms `faiss.IndexHNSWFlat(d, M)` + `index.hnsw.efConstruction` + `index.hnsw.efSearch` parameter pattern
|
||||
- Postgres-on-Jetson deployment: Source #97 Medium "Edge to Data Center: GPU-Accelerated Vector Search on a Jetson Orin Nano" (March 2026) — confirms OLTP throughput saturates at 10 concurrent connections on Jetson Orin Nano Super, **CPU cores (6) are the limiting factor, NOT memory**; minimal-config Postgres viable in <150 MB total per Coding Steve "Running PostgreSQL on Less Than 150MB of Memory"
|
||||
|
||||
**Phase**: Mode A Phase 2 — engine Step 3 + Step 7.5 (Component Applicability Gate)
|
||||
|
||||
**Confidence**: ✅ High — all evidence is L1 primary code/docs with direct verification; Postgres-on-Jetson deployment empirically demonstrated in Source #97 March 2026 article
|
||||
|
||||
**Sub-Question Binding**:
|
||||
- SQ3+SQ4 → C6 row in `../06_component_fit_matrix/C6_tile_cache_spatial_index.md` (this fact populates the `Manual mirror of existing suite-pattern` candidate row)
|
||||
- SQ2 architectural decision #1 (Fact #23 closure): 2D-ortho-only cache contract preserved; `tile_size_meters` column tracks the project's 2D-ortho metric per migration 011
|
||||
|
||||
**Implication / per-numbered-Restriction × per-numbered-AC sub-matrix**:
|
||||
|
||||
| Project Restriction / AC | Verdict | Evidence |
|
||||
|---|---|---|
|
||||
| **R-NEW-2 no cloud at flight** | ✅ PASS | Postgres + FAISS + filesystem all entirely local; no network calls at runtime |
|
||||
| **R-NEW-4 Jetson Orin Nano Super JetPack 6 ARM64** | ✅ PASS | Postgres 16 ARM64 packages available via `apt install postgresql-16` on Ubuntu 22.04 (JetPack 6 base); FAISS-CPU ARM64 wheels available via `pip install faiss-cpu` (Source #96 + Source #97); psycopg-binary ARM64 wheels available |
|
||||
| **AC-1.1 (≤80 m at 1 km AGL)** | ✅ PASS | Cache delivers correct tiles to C2/C3/C4 pipeline; pose accuracy is downstream concern |
|
||||
| **AC-1.2 (≤30 m at 500 m AGL)** | ✅ PASS | Same as above |
|
||||
| **AC-3.1 sharp turns ±20° bank** | ✅ PASS | Geographic lookup pattern is bank-angle-agnostic (queries by horizontal position, not orientation) |
|
||||
| **AC-3.2 sharp-turn frames may share <5% overlap** | ✅ PASS | Cache pre-loads all tiles in mission corridor; sharp-turn coverage handled by spatial-grid radius parameter |
|
||||
| **AC-3.3 re-localization stability** | ✅ PASS | Deterministic cache lookup; same query → same result |
|
||||
| **AC-3.4 operator re-loc hint** | ✅ PASS | Operator-supplied `(hint_lat, hint_lon, hint_zoom)` becomes direct btree-indexed query: `WHERE tile_zoom = $hint_zoom AND tile_x = slippy_x($hint_lat, $hint_lon, $hint_zoom) AND tile_y = slippy_y($hint_lat, $hint_lon, $hint_zoom)` |
|
||||
| **AC-4.1 latency budget (<400 ms p95 end-to-end)** | ✅ PASS | Geographic btree lookup <1 ms (sub-millisecond on indexed integer columns at ~10K-100K rows) + descriptor ANN ~1-3 ms via FAISS HNSW with `efSearch=64` + tile-bytes load ~5-50 ms via filesystem page cache = total **~6-54 ms per cache hit**, well within budget |
|
||||
| **AC-4.2 memory budget (<8 GB shared on Jetson)** | ✅ PASS | Postgres ~150-300 MB resident with conservative tuning (`shared_buffers=64MB`, `work_mem=4MB`, `maintenance_work_mem=32MB`, `effective_cache_size=512MB`) per Source #97 Coding Steve guide + FAISS ~50-200 MB depending on cache size + filesystem page cache ~500 MB-1 GB managed by kernel = total Postgres+FAISS+cache **~700 MB-1.5 GB** out of 8 GB |
|
||||
| **AC-4.5 look-back refinement** | N/A | Cache is read-only at flight time; refinement is C5 estimator's responsibility |
|
||||
| **AC-8.3 10 GB persistent tile cache budget** | ⚠️ TIGHT | JPEG tiles at ~30-100 KB each fit ~100K-300K tiles in 10 GB; descriptor blobs at 8 KB/tile (2048-D float32 MixVPR) consume additional ~800 MB for 100K tiles = total ~10.8 GB **marginally exceeds budget**. Mitigation = D-C6-1 NEW (descriptor-storage-format choice — halfvec at 4 KB/tile saves 50%, INT8 at 1 KB/tile saves 87.5%). For 512-D EigenPlaces variant per D-C2-10 = (b), descriptors fit in <500 MB for 100K tiles trivially |
|
||||
| **AC-NEW-3 (FDR)** | ✅ PASS | Cache hit/miss + tile_id + load latency are trivially recordable as FDR fields |
|
||||
| **AC-NEW-4 covariance honesty** | N/A | Cache is a passive lookup component; covariance is C4/C5 responsibility |
|
||||
| **AC-NEW-7 cache-poisoning safety** | ✅ PASS at storage layer | Immutable on-disk JPEGs with content-hash verification at load (BYTEA `tile_sha256` column to be added per D-C6-N future); Postgres row-level integrity via UNIQUE constraint on `(latitude, longitude, tile_zoom, tile_size_meters, version)` per Source #92 migration 011. **Cache-poisoning DETECTION** is C9/C10 responsibility (verify provenance signature at C10 pre-flight + C5 source-label state-machine demotion at runtime); cache simply REJECTS load if hash mismatch |
|
||||
| **AC-NEW-8 blackout failsafe** | ✅ PASS | Cache miss is handled gracefully (no tiles → C5 source-label demotes to `dead_reckoned` per AC-NEW-8 escalation thresholds); cache does NOT itself trigger failsafe |
|
||||
|
||||
**Strengths** (positive structural advantages):
|
||||
1. **Project-pattern alignment** — exactly mirrors the parent-suite `satellite-provider` pattern; if a tile is requested in pre-flight provisioning by C10 from the suite Postgres, the same SQL query and same filesystem path work on the Jetson at flight time. **No new infrastructure to learn, debug, or maintain across the suite vs onboard split.**
|
||||
2. **Trivial dependency footprint** — vanilla PostgreSQL 16 (already required if `c6_postgres_locus = A` Postgres-on-Jetson is the deployment-locus choice); NO Postgres extensions needed (no PostGIS, no pgvector, no pg_trgm); FAISS is a single Python package (~50 MB on disk via `pip install faiss-cpu`); psycopg-binary is a single Python package (~5 MB).
|
||||
3. **Sub-millisecond geographic lookup** — btree composite on integer-coordinate columns is structurally optimal for the dominant query pattern (3 Hz spatial-grid range query at zoom 18-20). Per Source #93 + EXPLAIN-ANALYZE empirical evidence at ~10K-100K rows: `Index Scan using idx_tiles_coordinates` with `cost=0.28..1.71 rows=9 width=170` extrapolated from Source #94 PostGIS workshop nyc_streets example.
|
||||
4. **Predictable memory footprint** — no extension memory overhead beyond Postgres baseline; FAISS in-memory budget scales linearly with `(n_descriptors × d_descriptor × 4 bytes)`. At 100K descriptors × 2048-D × 4 B = 800 MB; halfvec halves this to 400 MB.
|
||||
5. **License clean throughout** — PostgreSQL (PostgreSQL License = BSD-style permissive), FAISS (MIT), psycopg2/asyncpg (LGPL-3.0 / MIT-Apache-2.0 dual). **Eligible on every D-C1-1 license-posture choice** with the simplest license-compliance story.
|
||||
6. **Battle-tested storage primitive** — slippy-map filesystem hierarchy is the canonical OSM/web-map convention for ~15+ years; trivially debuggable via `ls`, `find`, `stat`; no proprietary container format.
|
||||
7. **Empirically-confirmed Postgres-on-Jetson viability** — Source #97 March 2026 article confirms full Postgres + pgvector deployment works on Jetson Orin Nano Super; **CPU cores are the limiting factor, NOT memory**, which means the 8 GB shared memory budget is plenty of headroom for Cand 1's modest 700 MB-1.5 GB total.
|
||||
|
||||
**Negative-but-mitigable structural findings**:
|
||||
8. **No native KNN distance ordering for geographic queries** — application must convert `(lat, lon)` → `(tile_x, tile_y)` integer math then issue a range query with a ±k radius in tile units, then sort by Euclidean tile-distance app-side. For 3x3 grid (k=1) this is trivial (~9 candidates, sorted in <100 us); does not generalize to "all tiles within R meters" without per-zoom k-derivation. **Mitigation**: precompute Web-Mercator-aware tile-to-meter conversion at zoom Z (per Source #98 zoom-level table at line 37); at zoom 18 ~150 m/tile, k=2 covers ~750 m radius; at zoom 20 ~38 m/tile, k=8 covers similar. For the project's 1 km AGL flight + ~60 km/h cruise, 3x3 grid at zoom 18 is sufficient coverage per AC-1.1/1.2 frame-center accuracy bars.
|
||||
9. **No native combined geographic-+-descriptor query** — must round-trip through application layer (DB returns geographic candidates → app filters by descriptor distance via FAISS). Overhead: ~1-2 ms per round trip vs ~5-10 ms for an equivalent PostGIS+pgvector single-SQL query (Cand 2). **Mitigation**: at 3 Hz query rate (333 ms budget per query inside AC-4.1 400 ms p95 envelope), the round-trip overhead is negligible — and Cand 1's app-side approach actually offers MORE flexibility (e.g., descriptor scoring with non-L2 metrics, custom rerank logic, integration with C5 covariance-honest filtering).
|
||||
10. **Descriptor ANN requires takeoff-time FAISS index build OR pre-serialized index load** — IndexHNSWFlat does not support cleanly removing vectors per Source #96, and bulk-add is slower than IndexFlatL2's append. **Mitigation**: build incrementally during C10 pre-flight cache provisioning + serialize to disk via `faiss.write_index(index, path)`; load via `faiss.read_index(path)` at takeoff in ~1-5 sec (much faster than rebuild). D-C6-3 NEW gate covers this.
|
||||
11. **No native great-circle / geodesic distance** — geographic queries are in slippy-map integer coordinates (Web Mercator approximation), not WGS84 geodesic. For low-altitude UAV at 1 km AGL covering ≤200 km mission radius (~2° latitude), Web Mercator distortion is <0.5% — negligible for tile-grid queries. **Mitigation**: zoom-level + slippy-map math handles this implicitly (each zoom's tile size shrinks toward poles by `cos(lat)`, matching reality).
|
||||
|
||||
**Caveats / open Plan-phase decisions raised** (D-C6-N gates):
|
||||
|
||||
- **D-C6-1 NEW** — descriptor-storage-format choice (full-precision float32 in `bytea` column vs halfvec via app-side conversion + storage as 2-byte half-floats vs INT8 quantized via app-side conversion + storage as 1-byte integers + per-vector scale parameter): trade-off between cache footprint (1×/2×/4× ratio) vs Recall@K accuracy loss. **Recommendation**: D-C6-1 = (b) halfvec for descriptor storage at ~2× cache-footprint-saving with ~0-2% Recall@K loss documented in pgvector ecosystem.
|
||||
- **D-C6-2 NEW** — FAISS index variant choice for app-side descriptor ANN (`IndexFlatL2` brute-force / `IndexHNSWFlat` with M=16/32 ef_construction=64 / `IndexIVFFlat` with nlist=sqrt(N) / `IndexIVFPQ` for additional compression): trade-off between memory footprint vs query accuracy vs query latency. **Recommendation**: D-C6-2 = (b) `IndexHNSWFlat(d, M=32)` for the primary path; `IndexFlatL2` fallback for small caches (<10K tiles where exact brute force is faster than HNSW navigation overhead per Source #96 contextual guidance).
|
||||
- **D-C6-3 NEW** — descriptor-cache-rebuild-trigger strategy (rebuild on every cache modification = simplest but slow / incremental add via `index.add()` = faster but HNSW does not support delete cleanly per Source #96 / periodic rebuild during pre-flight = most robust but requires C10 coordination): **Recommendation**: D-C6-3 = (c) periodic rebuild during C10 pre-flight provisioning; serialize to disk via `faiss.write_index`; reload at flight takeoff in <5 sec.
|
||||
- **D-C6-4 NEW** — geographic-spatial-grid radius `k` (1 = 3x3 grid / 2 = 5x5 grid / 4 = 9x9 grid / dynamic based on zoom + ground-speed): trade-off between per-query candidate count vs spatial coverage. **Recommendation**: D-C6-4 = dynamic, derived from AC-3.1 sharp-turn bank rate + ground-speed projected over the next ~5 sec.
|
||||
|
||||
---
|
||||
|
||||
### Fact #93 — PostgreSQL + PostGIS GiST on `geography(POINT,4326)` with KNN distance ordering (`<->`) + pgvector HNSW for descriptor ANN + filesystem tile storage
|
||||
|
||||
**Statement**: For C6 (tile cache + spatial index), the modern-competitive-lead-spatial-extension candidate is PostgreSQL + PostGIS 3.4 + pgvector 0.7+ as a unified Postgres-extension-stack:
|
||||
|
||||
- **Geographic spatial index**: PostGIS `CREATE INDEX idx_tiles_geog ON tiles USING GIST(position::geography)` where `position` is `geometry(POINT, 4326)` derived from `(latitude, longitude)`. Per Source #94 (PostGIS workshop KNN docs at <https://postgis.net/workshops/postgis-intro/knn.html>): "PostgreSQL solves the nearest neighbor problem by introducing an 'order by distance' (`<->`) operator that induces the database to use an index to speed up a sorted return set." Native KNN: `ORDER BY position <-> ST_MakePoint($lon, $lat)::geography LIMIT K`. Native radius queries: `WHERE ST_DWithin(position::geography, ST_MakePoint($lon, $lat)::geography, $radius_m)`.
|
||||
- **Descriptor ANN over global VPR descriptors**: pgvector 0.7+ `CREATE INDEX idx_tiles_desc ON tiles USING hnsw (descriptor vector_l2_ops) WITH (m = 16, ef_construction = 64)` for HNSW-graph-based descriptor ANN. Per Source #95 (pgvector context7): default `hnsw.ef_search = 40` query-time; tunable via `SET hnsw.ef_search = 100` for higher recall at the cost of latency. Combined SQL query: `SELECT id, file_path, descriptor <-> $query_vec AS dist FROM tiles WHERE ST_DWithin(position::geography, ST_MakePoint($lon, $lat)::geography, $radius_m) ORDER BY descriptor <-> $query_vec LIMIT K`.
|
||||
- **Raw tile storage**: same as Cand 1 — filesystem at canonical slippy-map path `./tiles/{tile_zoom}/{tile_x}/{tile_y}.{image_type}`; DB stores `file_path VARCHAR(500)` pointer.
|
||||
- **Slippy-map coordinate transform**: same as Cand 1 — used to derive `(tile_x, tile_y)` columns alongside the new `position` PostGIS geometry column; permits both Cand-1-style integer-grid queries AND Cand-2-style geodesic-distance queries from a single schema.
|
||||
|
||||
**Mode pinning** (per-mode API verification rule):
|
||||
- inputs: identical to Cand 1 — `(query_lat, query_lon, query_alt_m)` from C5 @ 3 Hz; `(query_descriptor: numpy.ndarray of shape (d,) and dtype float32)` from C2 VPR @ 3 Hz; operator re-loc hint per AC-3.4
|
||||
- outputs:
|
||||
- geographic-KNN query: `[(tile_id, file_path, dist_m), ...]` returning K=10 nearest tiles by great-circle distance — **superior to Cand 1's slippy-map-tile-distance approximation for queries near the poles or at high zoom**
|
||||
- geographic-radius query: `[(tile_id, file_path, dist_m), ...]` returning all tiles within `$radius_m` meters — **NEW capability vs Cand 1** (Cand 1 requires per-zoom k-derivation app-side)
|
||||
- descriptor-ANN query: `[(tile_id, file_path, l2_distance), ...]` returning top-K descriptor-similar tiles via pgvector HNSW
|
||||
- **combined geographic-+-descriptor SQL query**: single SQL statement returns top-K geographically-prefiltered descriptor-similar tiles — **NEW capability vs Cand 1** (Cand 1 requires app-side round trip)
|
||||
- runtime: PostgreSQL 16 + PostGIS 3.4 extension (~30-80 MB shared libraries per Source #94 / EDB install footprint cite) + pgvector 0.7 extension (~5-10 MB shared library per Source #95) + psycopg-binary on Jetson Orin Nano Super (8 GB shared, JetPack 6); **PostGIS+pgvector ARM64 packages available via `apt install postgresql-postgis3` per Source #94** + `apt install postgresql-16-pgvector` for pgvector ARM64 deb package (verified for Ubuntu 22.04 base which JetPack 6 derives from)
|
||||
|
||||
**Source**:
|
||||
- Primary geographic-side: Source #94 PostGIS official workshop KNN docs at <https://postgis.net/workshops/postgis-intro/knn.html> + PostGIS context7 at `/postgis/postgis` — confirms `CREATE INDEX ... USING GIST(location)`, `<->` KNN operator, `ST_DWithin` radius queries with native great-circle distance for `geography` type
|
||||
- Primary descriptor-side: Source #95 pgvector context7 at `/pgvector/pgvector` — confirms `CREATE INDEX ON items USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64)` HNSW pattern; `SET hnsw.ef_search = 100` query-time tuning
|
||||
- ARM64 deployability: Source #94 EDB Docs cross-cite confirms PostGIS 3.4 + Ubuntu 22.04 install via `apt install postgresql-postgis3`; Source #97 March 2026 Medium article confirms Postgres + pgvector + Ollama + embedding-model GPU stack runs on Jetson Orin Nano (note: pgvector ARM64 packages published since pgvector 0.7+; older versions required source build)
|
||||
- pgvector dimension limits: per Source #95 pgvector context7 — `vector_l2_ops` for full-precision float32 supports **up to 2,000 dimensions for HNSW indexes** (per pgvector 0.6 README baseline); newer pgvector 0.7+ supports `halfvec_l2_ops` (half-precision, 2-byte) and `sparsevec_l2_ops` for higher dimensions including **up to 16,000 dimensions for halfvec HNSW**
|
||||
- Filesystem layout: shared with Cand 1 per Source #92 satellite-provider pattern + Source #98 OSM slippy-map convention
|
||||
|
||||
**Phase**: Mode A Phase 2 — engine Step 3 + Step 7.5 (Component Applicability Gate)
|
||||
|
||||
**Confidence**: ✅ High for the API capability verification (PostGIS GiST + pgvector HNSW are L1 docs canonical APIs) + ⚠️ Medium-High for the Jetson-deployability claim (PostGIS+pgvector ARM64 packages confirmed available, but specific install footprint and runtime memory measurements on Jetson Orin Nano Super NOT empirically verified — needs Jetson MVE phase per D-C1-2)
|
||||
|
||||
**Sub-Question Binding**:
|
||||
- SQ3+SQ4 → C6 row in `../06_component_fit_matrix/C6_tile_cache_spatial_index.md` (this fact populates the `PostGIS GiST + pgvector HNSW` candidate row)
|
||||
- SQ2 architectural decision #1 (Fact #23 closure): 2D-ortho-only cache contract preserved; PostGIS `geography(POINT,4326)` represents the tile center as a 2D geodetic point — fully compatible with the 2D-ortho contract
|
||||
|
||||
**Implication / per-numbered-Restriction × per-numbered-AC sub-matrix**:
|
||||
|
||||
| Project Restriction / AC | Verdict | Evidence |
|
||||
|---|---|---|
|
||||
| **R-NEW-2 no cloud at flight** | ✅ PASS | Postgres + PostGIS + pgvector + filesystem all entirely local |
|
||||
| **R-NEW-4 Jetson Orin Nano Super JetPack 6 ARM64** | ⚠️ PASS-with-Plan-phase-verification | Postgres 16 ARM64 + PostGIS 3.4 ARM64 (`apt install postgresql-postgis3`) + pgvector 0.7+ ARM64 (`apt install postgresql-16-pgvector`) all available for Ubuntu 22.04; **specific install footprint + runtime memory measurements on Jetson Orin Nano Super NOT empirically verified** (Source #94 search results explicit limitation: "do not provide specific information about PostGIS 3.4's compatibility with ARM64 architecture on Jetson devices, nor do they document the installation footprint"); D-C6-5 NEW gate covers this |
|
||||
| **AC-1.1 (≤80 m at 1 km AGL)** | ✅ PASS | Cache delivers correct tiles to C2/C3/C4 pipeline; pose accuracy is downstream concern |
|
||||
| **AC-1.2 (≤30 m at 500 m AGL)** | ✅ PASS | Same as above |
|
||||
| **AC-3.1 sharp turns ±20° bank** | ✅ PASS | Geographic lookup pattern is bank-angle-agnostic |
|
||||
| **AC-3.2 sharp-turn frames may share <5% overlap** | ✅ PASS | Cache pre-loads all tiles in mission corridor; sharp-turn coverage handled by `ST_DWithin` radius parameter with native geodesic semantics |
|
||||
| **AC-3.3 re-localization stability** | ✅ PASS | Deterministic GiST index lookup; same query → same result |
|
||||
| **AC-3.4 operator re-loc hint** | ✅ PASS | Operator-supplied `(hint_lat, hint_lon, hint_zoom)` becomes direct PostGIS query: `SELECT * FROM tiles WHERE ST_DWithin(position::geography, ST_MakePoint($hint_lon, $hint_lat)::geography, $hint_radius_m) AND tile_zoom = $hint_zoom` |
|
||||
| **AC-4.1 latency budget (<400 ms p95 end-to-end)** | ⚠️ TIGHT-BUT-FITS | Combined geographic-+-descriptor single-SQL query latency ~5-15 ms on Jetson CPU per Source #94 EXPLAIN-ANALYZE pattern (PostGIS GiST + pgvector HNSW indices both used in single query plan); **vs Cand 1's ~6-54 ms** (geographic + descriptor + tile-bytes combined). Tile-bytes load adds ~5-50 ms via filesystem page cache (same as Cand 1). **Total: ~10-65 ms per cache hit** — well within budget BUT 1.5-2× slower than Cand 1's geographic-only btree lookup |
|
||||
| **AC-4.2 memory budget (<8 GB shared on Jetson)** | ✅ PASS | Postgres ~150-300 MB resident with conservative tuning + PostGIS extension shared libraries ~30-80 MB + pgvector extension ~5-10 MB + filesystem page cache ~500 MB-1 GB = total **~700 MB-1.4 GB** out of 8 GB (vs Cand 1's 700 MB-1.5 GB — essentially tied) |
|
||||
| **AC-4.5 look-back refinement** | N/A | Cache is read-only at flight time |
|
||||
| **AC-8.3 10 GB persistent tile cache budget** | ⚠️ TIGHT-with-mitigation | Same JPEG tile cost as Cand 1 (~30-100 KB each) + descriptor blobs **stored in pgvector `vector` type with 4 bytes/dim overhead** — at 2048-D float32 = 8 KB/tile (same as Cand 1's bytea); for **halfvec_l2_ops** = 4 KB/tile (50% saving, supports up to 16,000 dim); for `sparsevec_l2_ops` even less. **Same cache-footprint profile as Cand 1** with the same D-C6-1 NEW mitigation strategy |
|
||||
| **AC-NEW-3 (FDR)** | ✅ PASS | Cache hit/miss + tile_id + load latency are trivially recordable as FDR fields |
|
||||
| **AC-NEW-4 covariance honesty** | N/A | Cache is a passive lookup component |
|
||||
| **AC-NEW-7 cache-poisoning safety** | ✅ PASS at storage layer | Same immutable-on-disk-JPEG + content-hash + UNIQUE constraint approach as Cand 1; PostGIS adds `ST_IsValid` geometric integrity check on `position` column as an additional defense-in-depth layer |
|
||||
| **AC-NEW-8 blackout failsafe** | ✅ PASS | Cache miss handled gracefully via C5 source-label demotion |
|
||||
|
||||
**Strengths** (positive structural advantages over Cand 1):
|
||||
1. **Native KNN distance ordering for geographic queries** — `ORDER BY position <-> ST_MakePoint(...) LIMIT K` with index-assisted EXPLAIN per Source #94 evidence: `Index Scan using nyc_streets_geom_idx ... Order By: (geom <-> '...'::geometry)`. **No app-side k-derivation OR distance-sort required** vs Cand 1's per-zoom k-tile-radius math.
|
||||
2. **Native great-circle / geodesic distance for `geography` type** — `ST_DWithin(position::geography, ..., $radius_m)` returns true distance in meters across the WGS84 ellipsoid; no Web-Mercator approximation error. **Material accuracy improvement near poles or at very high zoom** but **negligible for project's UAV at 1 km AGL covering ≤200 km mission radius** (Web Mercator distortion <0.5% in this regime).
|
||||
3. **Native combined geographic-+-descriptor query in a single SQL statement** — `SELECT id, file_path, descriptor <-> $query_vec AS dist FROM tiles WHERE ST_DWithin(position::geography, ST_MakePoint($lon, $lat)::geography, $radius_m) ORDER BY descriptor <-> $query_vec LIMIT K`. **Eliminates app-side round-trip overhead** present in Cand 1 (~1-2 ms per query); enables Postgres query planner to choose the most selective filter first (geographic GiST or descriptor HNSW depending on row count distribution).
|
||||
4. **`ST_DWithin(geography, geography, radius_m)` native radius query in meters** — directly answers "give me all tiles within R meters of the query point" without per-zoom k-derivation. **NEW capability vs Cand 1**.
|
||||
5. **Battle-tested PostGIS GiST + pgvector HNSW** — both extensions are L1 canonical Postgres extensions with active maintenance + multi-million production deployments + canonical OGC SFS compliance for PostGIS.
|
||||
6. **Same filesystem tile storage as Cand 1** — zero migration cost on the raw-tile-bytes side.
|
||||
|
||||
**Negative-but-mitigable structural findings**:
|
||||
7. **Heavier Postgres-extension dependency** — PostGIS 3.4 install footprint ~30-80 MB shared libraries + ~10-20 MB SRID/projection metadata catalog; pgvector 0.7+ ~5-10 MB shared library. **Vs Cand 1's zero-extension Postgres**, this is **~50-100 MB additional memory + ~50-200 MB additional disk install footprint**. **Mitigation**: well within AC-4.2 8 GB budget (essentially noise) and AC-8.3 10 GB cache budget (extension install lives in `/usr/lib/postgresql`, not in cache budget). **Real cost**: extra extension to maintain, version-pin, and verify ARM64 compatibility for at C7 inference-runtime + Jetson MVE phase.
|
||||
8. **Geographic GiST index lookup ~5-10× slower than Cand 1's btree composite for the dominant 3 Hz spatial-grid query** — GiST lookup latency ~1-5 ms per Source #94 nyc_streets EXPLAIN evidence (`cost=0.28..79.58 rows=3`); Cand 1's btree lookup is ~0.1-0.5 ms. **Mitigation**: at 3 Hz query rate (333 ms budget per query inside AC-4.1 400 ms p95 envelope), the absolute latency difference (~1-5 ms vs 0.1-0.5 ms) is negligible — **but the relative slowdown is real**.
|
||||
9. **pgvector HNSW dimension limit at full-precision** — `vector` type HNSW supports up to **2,000 dimensions** per Source #95 pgvector README; for **MixVPR canonical 2048-D descriptors per Fact #18 cluster**, this **JUST EXCEEDS the limit**. **Mitigation**: use `halfvec_l2_ops` (half-precision, 2-byte storage, supports up to 16,000 dimensions) — cuts cache footprint by 50% AND clears the dimension limit; OR truncate to 1536-D (loses ~25% Recall@K); OR use 512-D EigenPlaces variant per D-C2-10 = (b) which is well within both pgvector limits AND smaller cache footprint.
|
||||
10. **No empirically-verified Jetson Orin Nano Super deployment for PostGIS+pgvector combined stack** — Source #97 March 2026 article confirms Postgres + pgvector deployment but does not explicitly include PostGIS; Source #94 search results explicitly note absence of Jetson-specific PostGIS install evidence. **Mitigation**: D-C6-5 NEW gate — Jetson MVE phase per D-C1-2 must include PostGIS+pgvector co-installation + OLTP+spatial+ANN combined-query profiling on Jetson Orin Nano Super.
|
||||
|
||||
**Caveats / open Plan-phase decisions raised** (D-C6-N gates):
|
||||
|
||||
- **D-C6-5 NEW (Cand-2-only)** — Jetson PostGIS + pgvector co-installation Plan-phase verification choice (verify on Jetson MVE as part of D-C1-2 dedicated bring-up phase / fork PostGIS+pgvector ARM64 builds in-house if upstream packages incomplete / pivot to Cand 1 if PostGIS+pgvector co-installation reveals blocking incompatibility): trade-off between Plan-phase engineering investment vs documented evidence gap. **Recommendation**: D-C6-5 = (a) verify on Jetson MVE phase at D-C1-2 — already-required Jetson hardware bring-up cycle absorbs this work cheaply.
|
||||
- **D-C6-6 NEW (Cand-2-only)** — pgvector descriptor-storage-type choice (`vector` full-precision float32 with 2,000-dim max for HNSW per Source #95 / `halfvec` half-precision 2-byte with 16,000-dim max + 50% cache savings + ~0-2% Recall@K loss / `sparsevec` for sparse descriptors / `bit` for binary descriptors via Hamming distance): trade-off between cache footprint vs accuracy vs descriptor compatibility with C2 VPR candidate output format. **Recommendation**: D-C6-6 = (b) `halfvec` for the primary path; covers all C2 VPR descriptor candidates (MixVPR 2048-D, SelaVPR 1024-D, NetVLAD 4096-D PCA-whitened, EigenPlaces 2048-D-or-smaller-via-D-C2-10, SALAD 8448-D/2112-D/544-D-via-D-C2-6) with consistent storage format.
|
||||
- **D-C6-7 NEW (CROSS-COMPONENT — affects both Cand 1 and Cand 2)** — IF Cand 2 selected → cascade-changes-back-to-suite-satellite-provider strategy choice (cascade PostGIS+pgvector adoption back to satellite-provider for cross-suite consistency / keep satellite-provider on btree-only and gps-denied-onboard on PostGIS+pgvector — accept divergence / migrate satellite-provider to PostGIS+pgvector in a separate ticket post-MVP / leave satellite-provider unchanged + maintain compatibility shim in gps-denied-onboard's pre-flight cache-sync layer). **Recommendation**: per user's session-start clarification "if improvement is small, then there is no sense to change anything at all" — IF Cand 2's MATERIAL improvement justifies adoption, cascade via separate ticket; OTHERWISE stay with Cand 1 throughout the suite.
|
||||
|
||||
---
|
||||
|
||||
## C6 — Comparative-improvement-vs-Cand-1 analysis (closure of batch 1)
|
||||
|
||||
| Dimension | Cand 1 (mirror suite-pattern) | Cand 2 (PostGIS+pgvector) | Improvement magnitude (Cand 2 vs Cand 1) | Verdict per user's "significant-improvement-only" bar |
|
||||
|---|---|---|---|---|
|
||||
| **Geographic spatial-query API** | btree composite + app-side k-radius derivation + app-side distance sort | Native KNN `<->` + native `ST_DWithin` radius | **Material capability improvement** (Cand 2 supports radius queries natively) | ⚠️ Material — but **project's pinned use case is 3x3 grid lookup at fixed zoom** (per AC-3.x mission corridor); native radius queries are unused capability |
|
||||
| **Combined geographic-+-descriptor query** | App-side round trip (~1-2 ms overhead) | Single SQL statement (~0.5 ms overhead) | **Marginal latency improvement** (~1 ms saving per query × 3 Hz = 3 ms/sec saving in absolute time) | ⚪ Marginal |
|
||||
| **Geographic query latency** | ~0.1-0.5 ms btree lookup | ~1-5 ms GiST lookup | **NEGATIVE** — Cand 1 is 5-10× faster for the dominant query | 🔴 Cand 2 worse here |
|
||||
| **Descriptor ANN latency** | ~1-3 ms FAISS HNSW (in-process) | ~1-3 ms pgvector HNSW (in-DB) | **No material difference** | ⚪ Tied |
|
||||
| **Memory footprint** | Postgres + FAISS = ~700 MB-1.5 GB | Postgres + PostGIS + pgvector = ~700 MB-1.4 GB | **No material difference** | ⚪ Tied |
|
||||
| **Cache-budget impact (AC-8.3)** | bytea 8 KB/tile (float32-2048D) | vector 8 KB/tile or halfvec 4 KB/tile | **Tied if both use halfvec / float16** | ⚪ Tied |
|
||||
| **Engineering complexity** | ZERO new infrastructure (mirrors satellite-provider exactly) | TWO new Postgres extensions (PostGIS + pgvector) + ARM64 verification at Jetson MVE + descriptor-format conversion code | **NEGATIVE** — Cand 2 adds ~3-5 days engineering at Plan + Jetson MVE phases | 🔴 Cand 2 worse here |
|
||||
| **Project-pattern alignment** | EXACT mirror of suite satellite-provider | DIVERGENT from suite satellite-provider; requires D-C6-7 NEW gate cascade decision | **NEGATIVE** — Cand 2 forces a cross-suite consistency decision | 🔴 Cand 2 worse here |
|
||||
| **Operator re-loc hint (AC-3.4) handling** | Direct btree lookup at hint zoom + (x, y) | Direct ST_DWithin radius query at hint position + radius | **Tied — both handle it natively** | ⚪ Tied |
|
||||
| **License clean-throughput** | PostgreSQL + FAISS-MIT + psycopg-LGPL/MIT-Apache | PostgreSQL + PostGIS-GPL2 + pgvector-PostgreSQL-License + psycopg | ⚠️ Cand 2 introduces PostGIS-GPL-2.0-or-later which may conflict with D-C1-1 license-posture choice if (b) BSD/permissive-only-track is selected | 🔴 Cand 2 worse here (subject to D-C1-1) |
|
||||
|
||||
**Closure verdict (per user's "significant-improvement-only" bar)**:
|
||||
**Cand 1 (mirror suite-pattern) is the recommended primary path for C6**. Cand 2's improvements (native KNN, native radius queries, single-SQL combined query) are real BUT **the project's pinned 3 Hz spatial-grid query at fixed zoom does not exercise these capabilities** (per AC-3.x mission corridor + AC-1.x frame-center accuracy bars). Cand 2 is **5-10× slower for the dominant geographic query** AND **requires PostGIS+pgvector ARM64 Jetson MVE verification** AND **forces a cross-suite cascade decision (D-C6-7)** AND **may conflict with D-C1-1 license-posture choice (b)** due to PostGIS-GPL-2.0-or-later licensing. **The improvements are marginal-to-negative in the project's specific operating context — no material justification to deviate from the existing satellite-provider pattern.**
|
||||
|
||||
**Cand 2 promotion criteria (defer-to-Plan or Jetson-MVE)**: Cand 2 should be re-evaluated for promotion to primary IF AND ONLY IF (a) project use case expands to require radius-meters-based queries (e.g., dynamic mission corridor adjustment in flight) OR (b) Jetson MVE phase reveals Cand 1's app-side combined-query overhead is materially impacting AC-4.1 latency budget at the tail OR (c) D-C1-1 license-posture choice (a) GPL-3.0 track is selected AND the project elects to standardize on a single Postgres-extension stack for consistency.
|
||||
|
||||
---
|
||||
|
||||
## C6 — Working conclusions and decisions (compounded from Fact #92 + Fact #93 closures)
|
||||
|
||||
**Selected primary**: **Cand 1 (mirror suite-pattern)** — PostgreSQL btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` + filesystem `./tiles/{zoom}/{x}/{y}.{image_type}` + bytea descriptor blobs + app-side FAISS HNSW loaded at takeoff. **Cand 2 (PostGIS+pgvector) deferred to defer-to-Plan or Jetson-MVE secondary** per the comparative analysis above.
|
||||
|
||||
**Decisions raised (D-C6-N gates)** — see [`../06_component_fit_matrix/99_cross_component_gates.md`](../06_component_fit_matrix/99_cross_component_gates.md):
|
||||
|
||||
- **D-C6-1** (Fact #92) — descriptor-storage-format choice: float32 / halfvec / INT8 — RECOMMENDED halfvec
|
||||
- **D-C6-2** (Fact #92) — FAISS index variant choice: IndexFlatL2 / IndexHNSWFlat / IndexIVFFlat / IndexIVFPQ — RECOMMENDED IndexHNSWFlat M=32
|
||||
- **D-C6-3** (Fact #92) — descriptor-cache-rebuild-trigger strategy: rebuild-on-modification / incremental-add / periodic-rebuild-during-C10-pre-flight — RECOMMENDED periodic-rebuild
|
||||
- **D-C6-4** (Fact #92) — geographic-spatial-grid radius `k`: fixed-1 / fixed-2 / fixed-4 / dynamic-by-zoom-and-ground-speed — RECOMMENDED dynamic
|
||||
- **D-C6-5** (Fact #93, Cand-2-only contingent) — Jetson PostGIS + pgvector co-installation Plan-phase verification choice — RECOMMENDED verify at Jetson MVE D-C1-2
|
||||
- **D-C6-6** (Fact #93, Cand-2-only contingent) — pgvector descriptor-storage-type choice — RECOMMENDED halfvec
|
||||
- **D-C6-7** (Fact #92 + Fact #93, CROSS-COMPONENT) — IF Cand 2 selected → cascade-changes-back-to-suite-satellite-provider strategy — RECOMMENDED cascade-via-separate-ticket OR stay-with-Cand-1 throughout
|
||||
|
||||
C6 batch 1 closed at 2/N. Subsequent C6 candidates (e.g., MBTiles single-sqlite-file, LMDB+geohash, FAISS-only-no-Postgres) deferable — current 2-candidate breadth satisfies engine Component Option Breadth rule for the user's pinned-Postgres scope.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user