Greenfield Steps 1-6 baseline for the autopilot rewrite from legacy Qt/C++ to a Rust workspace. - Remove legacy Qt/C++ tree (ai_controller, drone_controller, misc/camera, python_scaffold, root Dockerfile, autopilot.pro, legacy main.py / requirements.txt). - Add _docs/00_problem (problem, restrictions, acceptance criteria, security approach, input data + fixtures). - Add _docs/01_solution/solution_draft01. - Add _docs/02_document (architecture, system-flows, data_model, glossary, decision-rationale, deployment, 13 component descriptions, tests/ specs, FINAL_report, module-layout). - Add _docs/02_tasks/todo with 47 task specs (AZ-640..AZ-686, one bootstrap + 46 component tasks) and _dependencies_table.md. - Add .cursor/rules/artifact-srp.mdc (single-responsibility rule for canonical _docs artifacts). - Track autodev state in _docs/_autodev_state.md (Step 6 completed, ready for Step 7 Implement). Jira: bootstrap AZ-626; component epics AZ-627..AZ-639; tasks AZ-640..AZ-686. Total complexity 173 points across 12 epics. Co-authored-by: Cursor <cursoragent@cursor.com>
Input Data
Runtime inputs the autopilot consumes when flying, plus reference fixtures + expected-output assertions for tests. All fixtures live inside this workspace (fixtures/) — never reach into sibling repos at ../ for inputs. The autopilot repo is self-sufficient.
Layout
| Path | Owns |
|---|---|
data_parameters.md |
Description of runtime input shapes (camera, telemetry, gRPC, mission JSON, operator commands, VLM IPC) + the categories of reference data tests need + Tier-1/Tier-2 class catalogue. |
services.md |
Per-external-service test-mock requirements: what shape of mock/fixture each of the 7 external systems needs and the acquisition status of each. |
fixtures/README.md |
File-by-file manifest of every fixture in this directory: SHA-256, size, upstream provenance, which expected_results/results_report.md rows consume it. |
fixtures/images/ |
Real aerial frames (5 images, ~9 MB total) — Tier-1 inputs for detection-quality assertions (L1, D2, D6). |
fixtures/videos/ |
Real reconnaissance video (1 clip, 12 MB) for frame-rate floor + sequence tests (T3). |
fixtures/movement/ |
Wide-area movement-detection visual reference clips (4 clips, ~23 MB total). No paired gimbal.csv / telemetry.csv — ego-motion compensation (M1–M4) cannot run against these alone. |
fixtures/semantic/ |
Concealed-position semantic reference frames (4 PNGs, ~11 MB total) + data_parameters.md describing the new YOLO primitive classes the examples motivate. Starter set only, not a graded eval set. |
fixtures/schemas/ |
Detection-result contract schemas (JSON + JSON-schema) for D6. |
fixtures/sql/ |
Database init script — reference only; not directly asserted by an autopilot AC. |
expected_results/results_report.md |
The input → quantifiable-expected-output mapping consumed by /test-spec Phase 1. Every row keys off an AC in ../acceptance_criteria.md; deferred rows carry a structured <DEFERRED: <shape>; ref <pointer>> tag. |
Why fixtures are local
The autopilot repo MUST be self-sufficient — a developer with only the autopilot clone (no parent suite checked out) MUST be able to run the test specifications. Cross-repo ../ paths are forbidden in results_report.md and in any test runner script. When a sibling repo (../detections/, ../e2e/, ../missions/, etc.) is the upstream source of a fixture, we copy it in and SHA-pin it in fixtures/README.md so upstream drift is detectable.
Suite-level coupling that still matters
Even though fixtures are local, the underlying contracts the fixtures embody come from suite-level decisions. When those decisions change, the fixtures here go stale:
- Tier-1 detection model / classes — when
../detectionsships a new model theexpected_detections.jsonbaseline goes stale; D1, D2, D6 rows inresults_report.mdmust be re-recorded. mission-schema— shared between autopilot and themissionsrepo. Schema changes break the mission JSON contract; the mock fixtures for Mp1–Mp5 (when authored) must re-pin.- Detection classes catalogue — class IDs 0..18 are governed at the suite level. Autopilot's normalised-box output uses the same IDs. The 5 new Tier-1 classes documented in
data_parameters.md → "Class catalogue"must land in the suite catalogue before D1 can be measured.
Today these couplings are tracked manually. The monorepo-e2e skill at the suite root will eventually own the drift detection.
Fixture gaps and the project policy on /test-spec Phase 3
/test-spec Phase 3 has a hard 75% coverage gate on rows with real input fixtures + real expected results. Today's coverage is well below that gate (see expected_results/results_report.md → "Coverage Status"). Project policy as of 2026-05-19: rather than block the autodev flow at the gate, each deferred row is registered with a structured <DEFERRED: <shape>; ref <pointer>> tag in results_report.md, pointing at the per-service acquisition path in services.md or at an open architecture question (Q-tag). Deferred rows become release-gate items, not development-gate items. The acceptance_criteria.md → "Acceptance Gates (project-level)" hardware/replay benchmark requirement remains a hard release blocker.
Summary of open gaps (authoritative list lives in services.md and fixtures/README.md):
- Paired
gimbal.csv+telemetry.csvfor the 4 movement clips — highest priority (blocks M1–M4 + tightens L6/L7). User-confirmed unavailable today (2026-05-19). - Annotated multi-season eval set (concealed positions + footpaths).
- Mock
missionsAPI exchanges + mock/mapobjectsround-trip. - Mock Ground Station session traces.
- ArduPilot SITL traces.
- Operator-command envelopes (blocked on Q9).
- VLM I/O pairs.
- GPS / NTP drift scripts.
Closing each gap is its own workstream tracked in Jira; the autodev flow does not block on them.
Adding new fixtures
- Drop the file under
fixtures/<images|videos|movement|semantic|schemas|sql|gimbal|telemetry|mavlink|vlm|operator|mapobjects>/<descriptive-name>.<ext>— create the subdirectory if it does not exist. - Compute SHA-256 (
shasum -a 256 <file>). - Add a row to the matching subsection in
fixtures/README.md(file path, size, SHA, upstream provenance, whichresults_report.mdrows consume it). - Replace the matching
<DEFERRED: ...>placeholder(s) inexpected_results/results_report.mdwith the local pathfixtures/<...>. - If the fixture replaces a service mock, also update
services.md → "Coverage summary by service"to reflect the new acquisition status. - If the fixture is binary and large (> 50 MB) consider gitignoring it + adding an acquisition script per the e2e pattern; for everything in the current set, direct commit is fine.