Files
autopilot/_docs/03_implementation/batch_08_cycle1_report.md
T
Oleksandr Bezdieniezhnykh 8a4bd00526 [AZ-650] mission_executor pre-flight BIT (F9) gate (batch 8)
AZ-650 (mission_executor pre-flight Built-In Test):
- BitEvaluator trait + BitItemStatus { Pass, Degraded, Fail, Skipped }
  + BitReport + BitOverall fusion. Pluggable per-item evaluators so
  the composition root decides which dependencies are wired today.
- BitController owns evaluator list + mpsc ack channel + sticky-pass
  + ack deadline. Publishes bit_ok via tokio watch — composition root
  pipes it into the telemetry projection where the existing FSM
  bit_ok guard already consumes it (no FSM changes needed).
- BitState { Idle, Pass, AwaitingAck { report_id }, Failed { reason } }
  with broadcast::Sender<BitEvent> for operator-side observability.
  Sticky-pass semantics: once Pass is reached (directly or via signed
  ack on a Degraded report), the controller stops re-evaluating —
  BIT is a one-shot pre-flight gate, not a continuous monitor.
- BitDegradedAck arrives pre-validated by operator_bridge; the
  controller only matches report_id and applies the operator id to
  the audit log.
- Concrete evaluators landed today (3 of 12 spec items, the rest
  depend on components still in todo/):
  - StateDirFreeSpaceEvaluator (dir creatable/readable; statvfs is
    documented follow-up).
  - WallClockBoundEvaluator (chrono::Utc::now vs configurable bound).
  - MissionLoadedEvaluator (waypoint count via Arc<Mutex<usize>>).
  - MapObjectsSyncedEvaluator (maps SyncState -> BIT status per Q9).

Tests:
- ac1_all_pass_proceeds, ac2_fail_blocks_transition,
  ac3_degraded_requires_signed_ack (+ mismatched_ack supplement),
  ac4_degraded_ack_timeout_fails_the_bit — all 4 ACs green.
- Pure next_state table covered by lib unit tests.
- Per-evaluator unit tests for Pass/Fail/Degraded branches.

Quality gates:
- cargo fmt: clean.
- cargo clippy -p mission_executor --tests -- -D warnings: 0 warns.
- cargo test --workspace: all green.
- Pre-existing flake in state_machine::ac3_bounded_retry_then_success
  (batch 7 report) remains pre-existing — passes on rerun.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 19:12:48 +03:00

6.6 KiB

Batch 8 (cycle 1) implementation report

Tasks: AZ-650 Component scope: mission_executor Result: PASS_WITH_WARNINGS — proceed; flagged items below.

Tasks

AZ-650 mission_executor_bit_f9 — Pre-flight Built-In Test (F9)

Outcome: Implemented. All four acceptance criteria green.

Production code added:

  • crates/mission_executor/src/internal/bit.rs

    • BitEvaluator trait — pluggable per-item evaluator.
    • BitItem, BitItemStatus { Pass, Degraded, Fail, Skipped }, BitOverall, BitReport — typed report surface.
    • BitDegradedAck — pre-validated by operator_bridge (AZ-689 lane); this layer only matches report_id.
    • BitController — owns evaluators + ack mpsc + sticky-pass semantics + ack timeout deadline.
    • BitControllerHandle — read-side: bit_ok() watch, state() watch, subscribe() broadcast, last_report().
    • BitState { Idle, Pass, AwaitingAck { report_id }, Failed { reason } }.
    • BitEvent { Generated, StateChanged, AckTimedOut }.
  • crates/mission_executor/src/internal/bit_evaluators.rs

    • StateDirFreeSpaceEvaluator — verifies the state directory is creatable/readable. (See limitations.)
    • WallClockBoundEvaluator — sanity-checks wallclock vs. configurable minimum (default 2024-01-01).
    • MissionLoadedEvaluator — fails if waypoints empty.
    • MapObjectsSyncedEvaluator — reads MapObjectsStoreHandle::sync_state and maps to BIT status per spec (Synced/FreshBoot=Pass, CachedFallback=Degraded, Degraded/Failed=Fail).

Tests:

  • crates/mission_executor/tests/bit_controller.rs (5 tests):
    • ac1_all_pass_proceeds (AC-1).
    • ac2_fail_blocks_transition (AC-2).
    • ac3_degraded_requires_signed_ack (AC-3).
    • ac3_mismatched_ack_is_ignored — supplement.
    • ac4_degraded_ack_timeout_fails_the_bit (AC-4).
  • Module unit tests in internal::bit::tests (5 tests) cover the pure next_state table.
  • Module unit tests in internal::bit_evaluators::tests (7 tests) cover each concrete evaluator.

AC coverage

AC Behaviour Test Status
AC-1 All-pass → bit_ok = true; controller in Pass; overall = Pass ac1_all_pass_proceeds PASS
AC-2 Any Fail → bit_ok = false; controller Failed { reason }; report observable ac2_fail_blocks_transition PASS
AC-3 Degraded → AwaitingAck; matching signed ack → Pass; bit_ok = true ac3_degraded_requires_signed_ack PASS
AC-4 Degraded ack timeout → Failed { reason: "ack_timeout …" }; bit_ok stays false ac4_degraded_ack_timeout_fails_the_bit PASS

Code review

Spec compliance: PASS. All four ACs implemented with test seams that demonstrate the spec'd state transitions.

Architecture compliance: PASS. Controller follows the same pattern as LostLinkDriver (AZ-651): owns its inputs (evaluators + ack mpsc), publishes a bit_ok watch channel that the composition root pipes into the telemetry projection where the existing FSM bit_ok guard already consumes it. No FSM changes required.

SRP: PASS.

  • bit.rs — controller + types + state machine.
  • bit_evaluators.rs — concrete BitEvaluator impls only.
  • Pure next_state function isolated for table-driven testing.

Runtime completeness: PASS_WITH_WARNINGS. Three of the twelve BIT items listed in the spec have concrete production implementations today (state_dir_free_space, wall_clock_bound, mission_loaded, mapobjects_synced_or_cached_acked). The remaining nine (mavlink_link, gimbal_link, camera_rtsp, detection_grpc, movement_telemetry_sync_ready, tier2_session_ready, vlm_session_ready, operator_bridge_session) depend on components that are still in _docs/02_tasks/todo/ (gimbal — AZ-653..656; frame_ingest — AZ-657..659; operator_bridge — AZ-689; tier2/vlm sessions — TBD). The trait + registry is in place; each remaining evaluator is one file's worth of work that lands alongside its component. This matches the existing project convention (skill-driven sequential implementation; no premature stubs).

Test discipline: PASS. Each AC maps to one named test. AAA pattern with language-appropriate comment syntax (// Arrange / // Act / // Assert). Mocks are used for BitEvaluator-injection only — controller behaviour is exercised end-to-end.

Known limitations (warnings)

  1. StateDirFreeSpaceEvaluator does not call statvfs. The current implementation verifies that the directory is creatable/readable. A real free-space check requires either fs2, nix::sys::statvfs, or a platform-specific syscall. The evaluator preserves min_free_bytes in its API so the upgrade is a one-file change. Logged here so the operator-surface team knows the field is approximate.

  2. Nine BIT items are not yet wired (see Runtime completeness above). When their components land, each evaluator is one ~30-line file that plugs into the existing BitController::new(_, evaluators, _) registry.

  3. mission_loaded mirror channel. MissionLoadedEvaluator reads an Arc<Mutex<usize>> that the composition root mirrors from the FSM's mission vec each time it changes. This adds one cheap clone per mission update; documented in the type's docstring.

Auto-fix attempts during the batch

  • tracing::warn! Send-safety fix in lost_link.rs carried over from batch 7; cargo fmt adjusted some struct-variant formatting in the same file. No logic changes.
  • Initial next_state had a bug where the Degraded branch reset *ack_deadline on every tick (the report id changed each cycle). Fixed by making the AwaitingAck branch sticky — same report_id, untouched deadline — and by introducing a sticky_pass flag so Pass is one-shot (BIT is a pre-flight gate, not a continuous monitor).
  • Clippy doc-overindented-list-items fix on MapObjectsSyncedEvaluator's docstring.

Test reproduction

cargo build -p mission_executor --tests
cargo test  -p mission_executor                  # 29 tests; 0 failed
cargo clippy -p mission_executor --tests -- -D warnings
cargo test --workspace                            # all green; pre-existing flake in
                                                  # state_machine::ac3_bounded_retry_then_success
                                                  # remains pre-existing per batch 7 report

Candidates for batch 9

  • AZ-652 mission_executor_safety_and_resume — 5 pts. All deps (AZ-648/649/643/647) in done/.
  • AZ-653 gimbal_a40_transport — opens up the gimbal_link BIT evaluator slot.

Batch 9 sizing: AZ-652 alone is a sensible scope (geofence + battery thresholds + middle-waypoint re-upload + post-flight push are 6 ACs across 3 concerns).