# 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>` 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).