# Gimbal Command Issuance + Mission Hint Emission + Component-Health Gates

**Task**: AZ-686_scan_controller_gimbal_issuance
**Name**: Emit GimbalCommand per state tick + middle-waypoint hint on confirm + react to component-health degradations
**Description**: Translate state-machine transitions into `GimbalCommand`s (yaw / pitch / zoom): in `ZoomedOut` issue sweep commands; in `ZoomedIn { roi }` issue smooth-pan plan steps; in `TargetFollow` issue centre-on-target commands. On operator confirm, hand `middle-waypoint hint` to `mission_executor`. React to component-health degradations per `description.md §6 Failure Modes` (gimbal not ready → stay in state + alert; detection_client red → continue sweep, no Tier-1 POIs; etc.).
**Complexity**: 3 points
**Dependencies**: AZ-640_initial_structure, AZ-682_scan_controller_state_machine, AZ-683_scan_controller_poi_queue_and_window, AZ-684_scan_controller_evidence_ladder, AZ-654_gimbal_zoom_out_sweep, AZ-655_gimbal_smooth_pan_plan, AZ-656_gimbal_centre_on_target, AZ-648_mission_executor_state_machine
**Component**: scan_controller
**Tracker**: AZ-686
**Epic**: AZ-635

## Problem

The state machine + queue + evidence ladder produce DECISIONS; this task produces ACTIONS. The gimbal commands per state are sharp: `ZoomedOut` = sweep, `ZoomedIn` = smooth-pan plan from Tier 2, `TargetFollow` = centre-on-target. Component-health failures must produce explicit fallback behaviour (per `description.md §6`); the controller never silently drops a scan step.

## Outcome

- On `ZoomedOut` tick: emit `GimbalCommand::SweepStep` consistent with `gimbal_controller`'s sweep primitive (task 15).
- On `ZoomedIn { roi }` tick: emit the next pan-plan step from `Tier2Evidence.pan_plan` (or hold if plan is exhausted).
- On `TargetFollow { target_id }` tick: emit `GimbalCommand::CentreOnTarget { target_id }`.
- On operator confirm: emit `MissionAction::MiddleWaypointHint { target_mgrs, target_class }` to `mission_executor`.
- On `gimbal_controller` health red: stay in current state; surface alert; do NOT advance ticks that depend on gimbal acknowledgement.
- On `detection_client` health red: continue `ZoomedOut`; emit no Tier-1 POIs; movement candidates still flow.
- On `movement_detector` health red: continue; lose movement-candidate enqueueing.
- On `semantic_analyzer` health red: skip Tier 2; surface POIs with Tier-1-only evidence; flag in operator overlay.
- On `operator_bridge` disconnected: pause POI surfacing; continue `ZoomedOut`; resume on reconnect.

## Scope

### Included
- Per-state gimbal command emission.
- Middle-waypoint hint emission.
- Component-health-driven fallback behaviour table.

### Excluded
- State machine itself (task 43).
- Queue + cap (task 44).
- Evidence ladder (task 45).
- MapObjects dispatch (task 46).
- Gimbal primitives (tasks 15-17).
- Mission executor APIs (tasks 9-13).

## Acceptance Criteria

**AC-1: Per-state gimbal command**
Given current state `ZoomedOut | ZoomedIn { roi } | TargetFollow { target_id }`
When `tick` produces an action
Then the emitted `GimbalCommand` matches the per-state contract (sweep / pan-plan step / centre-on-target).

**AC-2: Operator confirm emits mission hint**
Given an operator confirm for POI X
When processed
Then `MissionAction::MiddleWaypointHint { target_mgrs: X.mgrs, target_class: X.class_group }` is emitted exactly once.

**AC-3: Gimbal red stays in state**
Given current state `ZoomedOut` and `gimbal_controller` health = red
When `tick` runs
Then no new gimbal command is emitted; state is unchanged; an alert is surfaced; health → yellow on scan_controller.

**AC-4: Detection red continues sweep without Tier-1**
Given current state `ZoomedOut` and `detection_client` health = red
When `tick` runs
Then sweep continues (gimbal commands still emitted), Tier-1 POIs are NOT surfaced; movement-candidate POIs still surface.

**AC-5: Semantic red surfaces Tier-1-only POIs**
Given `ZoomedIn { roi }` and `semantic_analyzer` health = red
When the zoom-in hold completes
Then any surfaced POI carries Tier-1-only evidence; the operator overlay shows the degraded flag.

## Non-Functional Requirements

**Performance**
- Gimbal command emit overhead: ≤2 ms p99.
- Zoom-out → zoom-in transition: ≤2 s including physical zoom (per `description.md §8`).

## Contract

- Canonical typed models: `data_model.md §GimbalCommand`, `§POI`.

## Runtime Completeness

- **Named capability**: per-state gimbal issuance + mission hint + health-driven fallback.
- **Production code that must exist**: real per-state command synthesis; real health-fallback table.
- **Unacceptable substitutes**: silently advancing the state when gimbal is red (commands fall on the floor) is unacceptable.
