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