# POI Queue: Priority Ordering + 5/min Rate Cap + Confidence-Scaled Decision Window

**Task**: AZ-683_scan_controller_poi_queue_and_window
**Name**: POI queue ordered by confidence × proximity × age + 5/min hard cap + decision-window mapping
**Description**: Maintain the POI queue ordered by `confidence × proximity_to_current_camera × age_factor`. Hard-cap output to ≤5 POIs/min. Map confidence to operator-decision deadline: 40% → 30 s, 100% → 120 s, linear; below 40% the POI is NOT surfaced. Timeout → forget. Decline → IgnoredItem append (via dispatch in task 46).
**Complexity**: 5 points
**Dependencies**: AZ-640_initial_structure, AZ-682_scan_controller_state_machine
**Component**: scan_controller
**Tracker**: AZ-683
**Epic**: AZ-635

## Problem

The 5-POI/min cap is a product-level invariant (operator cognitive load). The decision window is confidence-scaled because the operator deserves more time on ambiguous targets and less on obvious ones. The priority ordering keeps the most actionable POI in front of the operator first. Confidence < 40 % means "don't surface" — silent suppression, not a low-priority enqueue.

## Outcome

- `PoiQueue` with ordered insertion by `priority = f(confidence, proximity, age)`.
- Hard cap: rolling 60-s window tracks POIs surfaced; new POI surface request blocked if cap would be exceeded; blocked POI stays in queue for later.
- `decision_window(confidence)` returns `Duration` per the linear 40 % → 30 s / 100 % → 120 s mapping; returns `None` for confidence < 40 %.
- Timeout → `forget` (POI removed from queue, no IgnoredItem).
- Decline command from `operator_bridge` → emit `MapObjectsAction::AppendIgnored(mgrs, class_group)` (dispatched by task 46).
- Health: `pois_in_queue`, `pois_per_min`.

## Scope

### Included
- Priority-ordered queue.
- Rate cap with rolling-window enforcement.
- Decision-window mapping.
- Timeout → forget.

### Excluded
- State machine (task 43).
- Evidence ladder (task 45).
- MapObjects dispatch (task 46).
- Gimbal issuance (task 47).
- Operator command dispatch (`operator_bridge` task 41).

## Acceptance Criteria

**AC-1: Priority ordering correct**
Given 3 POIs with `(confidence, proximity, age) = (0.9, 0.5, 0), (0.6, 0.9, 0), (0.7, 0.6, 60)`
When `next()` is called repeatedly
Then the order respects `confidence × proximity × age_factor`.

**AC-2: 5/min hard cap**
Given 10 POIs above 40 % confidence in 30 s
When the cap window is queried
Then at most 5 are surfaced; the rest remain queued until window rolls.

**AC-3: Decision window linear mapping**
Given confidences `[0.40, 0.70, 1.00]`
When `decision_window(c)` is called for each
Then the returned `Duration` is `[30 s, 75 s, 120 s]` (linear).

**AC-4: Sub-40 % not surfaced**
Given a POI with confidence 0.39
When considered for surface
Then `decision_window` returns `None`; the POI is NOT surfaced.

**AC-5: Timeout forgets**
Given a surfaced POI whose deadline expires with no operator action
When timeout fires
Then the POI is removed from the queue; no IgnoredItem is created.

## Non-Functional Requirements

**Performance**
- Queue insertion: ≤1 ms p99.
- Cap-window check: O(window_size) where window_size is small (5).

**Product**
- 5/min hard cap is a non-negotiable invariant from `description.md §8`.

## Runtime Completeness

- **Named capability**: priority POI queue + 5/min rate cap + confidence-scaled deadline.
- **Production code that must exist**: real priority math; real cap enforcement; real linear mapping.
- **Unacceptable substitutes**: ignoring the 5/min cap "for testing" in production is unacceptable.
