# IgnoredItem Set + End-of-Pass Sweep

**Task**: AZ-666_mapobjects_store_ignored_and_pass_sweep
**Name**: IgnoredItem set + end-of-pass removed-candidate sweep
**Description**: `IgnoredItem` set keyed by `(MGRS, class_group)`. `is_ignored(MGRS, class_group)` suppression query. End-of-pass sweep: after a region's pass ends, return objects in the region that were not re-observed as `removed_candidate`s.
**Complexity**: 3 points
**Dependencies**: AZ-640_initial_structure, AZ-665_mapobjects_store_h3_classify
**Component**: mapobjects_store
**Tracker**: AZ-666
**Epic**: AZ-633

## Problem

When the operator declines a POI, the (MGRS, class_group) pair is added to the `IgnoredItem` set; subsequent detections matching the pair are suppressed BEFORE they reach the queue. Separately, when a scan pass over a region ends (signal from `scan_controller` / `mission_executor`), MapObjects that were known in the region but NOT re-observed during the pass should be flagged `removed_candidate` — the operator (not the system) decides actual removal.

## Outcome

- `IgnoredSet::append(item: IgnoredItem)` stores the entry.
- `is_ignored(mgrs, class_group) -> bool` answers in O(1).
- `MapObjectsStore::end_of_pass(region_bbox) -> Vec<RemovedCandidate>` returns objects in the region that were NOT re-observed since the pass started.
- Per-region pass tracker (start_ts, observed_ids) maintained.

## Scope

### Included
- `IgnoredSet` using a `HashSet<(H3Cell, ClassGroup)>` keyed structure.
- Class-group resolution (read group from config; e.g. `military_vehicle_group`, `concealed_position_group`, `movement_candidate`).
- Per-region pass tracker.
- End-of-pass sweep query.

### Excluded
- H3 classify (task 26).
- Pre-flight hydrate (task 28).
- Persistence (task 29).
- Append to `pending_observations` / `pending_ignored` (task 28).

## Acceptance Criteria

**AC-1: Ignored item suppresses subsequent detections**
Given `append(IgnoredItem { mgrs: M1, class_group: G })`
When `is_ignored(M1, G)` is called
Then it returns `true`; calls for other pairs return `false`.

**AC-2: End-of-pass returns un-observed objects**
Given a store with MapObjects at `M1, M2, M3` in region `R`
When the pass starts at `t0`, only `M1` is re-observed, and `end_of_pass(R)` is called at `t1`
Then it returns `[M2, M3]` as `RemovedCandidate`s.

**AC-3: End-of-pass excludes ignored**
Given `M2` was un-observed AND `is_ignored(M2.mgrs, M2.class_group) == true`
When `end_of_pass(R)` is called
Then `M2` is NOT in the returned list (ignored objects are not surfaced as removed-candidates).

## Non-Functional Requirements

**Performance**
- `is_ignored` p99 ≤1 ms.
- `end_of_pass` p99 ≤50 ms for a 30 km × 30 km region with ≤1 000 known objects.

## Runtime Completeness

- **Named capability**: IgnoredItem suppression + end-of-pass sweep.
- **Production code that must exist**: real HashSet + real per-region pass tracker.
- **Unacceptable substitutes**: re-querying the store for every detection without an `IgnoredSet` cache is unacceptable (latency violation).
