mirror of
https://github.com/azaion/autopilot.git
synced 2026-06-22 13:41:11 +00:00
[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>
This commit is contained in:
@@ -208,7 +208,10 @@ fn ac4_mavlink_loss_does_not_trigger_autopilot_rtl() {
|
||||
target_follow_active: false,
|
||||
});
|
||||
// Assert — never fire while mavlink is down
|
||||
assert!(!out.rtl_should_fire, "rtl fired at +{ms} ms with mavlink down");
|
||||
assert!(
|
||||
!out.rtl_should_fire,
|
||||
"rtl fired at +{ms} ms with mavlink down"
|
||||
);
|
||||
last_state = out.state;
|
||||
}
|
||||
// Assert
|
||||
@@ -328,10 +331,7 @@ impl MissionDriver for AutoDriver {
|
||||
/// Drive the executor through telemetry until it reaches `FlyMission`.
|
||||
/// Uses real time with a short tick interval so the test finishes in
|
||||
/// well under a second.
|
||||
async fn drive_to_fly_mission(
|
||||
handle: &MissionExecutorHandle,
|
||||
tel_tx: &watch::Sender<Telemetry>,
|
||||
) {
|
||||
async fn drive_to_fly_mission(handle: &MissionExecutorHandle, tel_tx: &watch::Sender<Telemetry>) {
|
||||
// mission_reached_final stays false so the FSM idles in FlyMission.
|
||||
let t = Telemetry {
|
||||
link_up: true,
|
||||
@@ -408,8 +408,7 @@ async fn ac2_driver_issues_rtl_once_and_transitions_fsm() {
|
||||
// Arrange — spawn the lost-link driver with fast thresholds
|
||||
let spy = Arc::new(SpyCommandIssuer::default());
|
||||
let (op_tx, op_rx) = watch::channel(true);
|
||||
let (mavlink_events_tx, mavlink_events_rx) =
|
||||
broadcast::channel::<mavlink_layer::LinkEvent>(8);
|
||||
let (mavlink_events_tx, mavlink_events_rx) = broadcast::channel::<mavlink_layer::LinkEvent>(8);
|
||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||
|
||||
let driver = LostLinkDriver::new(
|
||||
@@ -432,7 +431,10 @@ async fn ac2_driver_issues_rtl_once_and_transitions_fsm() {
|
||||
break;
|
||||
}
|
||||
if StdInstant::now() >= deadline {
|
||||
panic!("RTL never fired within 2 s; ladder state={:?}", ladder_handle.state().await);
|
||||
panic!(
|
||||
"RTL never fired within 2 s; ladder state={:?}",
|
||||
ladder_handle.state().await
|
||||
);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(5)).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user