# Geofence + Battery Enforcement + Middle-Waypoint Re-Upload + Post-Flight Trigger

**Task**: AZ-652_mission_executor_safety_and_resume
**Name**: Geofence + battery thresholds + middle-waypoint re-upload + post-flight push trigger
**Description**: Continuous safety enforcement (INCLUSION + EXCLUSION geofences honoured equally; battery thresholds with operator override). Mission re-upload on middle-waypoint hint. Mission revert on target-follow ending. Trigger post-flight MapObjects push on `POST_FLIGHT_SYNC` entry.
**Complexity**: 5 points
**Dependencies**: AZ-640_initial_structure, AZ-648_mission_executor_state_machine, AZ-649_mission_executor_telemetry_forwarding, AZ-643_mavlink_ack_demux_and_signing, AZ-647_mission_client_mapobjects_push
**Component**: mission_executor
**Tracker**: AZ-652
**Epic**: AZ-636

## Problem

The state machine alone is not enough — three continuous concerns must run on every tick:

1. **Geofence enforcement**: both INCLUSION and EXCLUSION violations trigger RTL. The earlier C++ behaviour silently ignored EXCLUSION; the new design rejects that.
2. **Battery / fuel thresholds**: RTL at `battery ≤ rtl_threshold` (default 25 %); land-now at `battery ≤ hard_floor` (default 15 %); operator override only via signed command.
3. **Middle-waypoint re-upload + target-follow revert**: on operator confirm, recompute and re-upload (`MISSION_CLEAR_ALL` → re-upload → `MISSION_SET_CURRENT(0)`); on target-follow ending, recompute and re-upload the original mission from current position.

Plus the post-flight trigger: on `POST_FLIGHT_SYNC` entry, hand off to `mission_client::push_mapobjects_diff`.

## Outcome

- `GeofenceMonitor::tick(uav_telemetry, mission_geofences)` triggers RTL on INCLUSION exit or EXCLUSION entry within ≤500 ms; alert is observable.
- `BatteryMonitor::tick(sys_status, ext_sys_state)` triggers RTL at `≤rtl_threshold`, land-now at `≤hard_floor`; signed operator-override is honoured and audit-logged.
- `MissionRePlanner::on_middle_waypoint(hint)` computes the patched mission and issues the re-upload sequence; result is observable.
- `MissionRePlanner::on_target_follow_release(reason)` recomputes the original mission from the current position and re-uploads.
- On entry to `POST_FLIGHT_SYNC`, the executor calls `mission_client::push_mapobjects_diff(mission_id, diff)`; result is logged; the machine still reaches `DONE` even on push failure (push surface manual-replay warning).

## Scope

### Included
- Continuous geofence check using `geo` crate or equivalent (point-in-polygon).
- Continuous battery check using `SYS_STATUS` + `EXTENDED_SYS_STATE`.
- Re-upload sequence helpers.
- Post-flight push trigger.

### Excluded
- Middle-waypoint computation algorithm (`scan_controller` provides the hint with `target_mgrs` + `target_class`; the executor only handles re-upload mechanics).
- Operator signature validation (`operator_bridge`).
- The actual push (`mission_client` task 08).
- The audit log persistence layer (lives in `shared::audit`).

## Acceptance Criteria

**AC-1: INCLUSION geofence exit triggers RTL**
Given a multirotor flying inside an INCLUSION polygon
When the UAV position crosses outside the polygon
Then RTL is triggered within ≤500 ms; the alert is observable; the state machine transitions to `LAND`.

**AC-2: EXCLUSION geofence entry triggers RTL**
Given a multirotor flying outside an EXCLUSION polygon
When the UAV position crosses into the polygon
Then RTL is triggered within ≤500 ms (parity with INCLUSION); the alert is observable.

**AC-3: Battery thresholds**
Given a multirotor flying with battery at 30 %
When `SYS_STATUS` reports battery at 24 %
Then RTL is triggered; transition to `LAND`.
When (in a separate scenario) `SYS_STATUS` drops below 15 %
Then `MAV_CMD_NAV_LAND` is issued (land-now); health → red.

**AC-4: Signed operator override of battery RTL**
Given the battery monitor would otherwise RTL at 24 %
When a signed `BatteryOverride { until_ts }` is received from `operator_bridge`
Then RTL is suppressed until `until_ts`; the override is recorded with operator id + rationale in the audit log.

**AC-5: Middle-waypoint re-upload sequence**
Given a confirmed POI yields a middle-waypoint hint
When `on_middle_waypoint` is invoked
Then the sequence `MISSION_CLEAR_ALL` → upload all waypoints → `MISSION_SET_CURRENT(0)` is issued in order, completing in ≤2 s end-to-end.

**AC-6: Post-flight push trigger**
Given the executor enters `POST_FLIGHT_SYNC`
When the entry guard runs
Then `mission_client::push_mapobjects_diff(mission_id, diff)` is called exactly once; the executor reaches `DONE` regardless of push success.

## Non-Functional Requirements

**Performance**
- Geofence response time: ≤500 ms from violation detection to RTL command.
- Middle-waypoint re-upload: ≤2 s end-to-end.

**Reliability**
- Both geofence variants enforced; symmetric behaviour.
- No infinite retry on re-upload — bounded by the executor's transition-retry budget.

## Runtime Completeness

- **Named capability**: geofence enforcement (both variants) + battery thresholds + re-upload sequence + post-flight push trigger.
- **Production code that must exist**: real point-in-polygon; real `SYS_STATUS` decode; real `MAV_CMD_*` issuance.
- **Unacceptable substitutes**: ignoring EXCLUSION (the pre-existing C++ bug) is unacceptable; ignoring battery overrides without signed proof is unacceptable.
