# Test — Wire-Contract Enum Compliance

**Task**: AZ-459_test_wire_contract_enums
**Name**: Enum compliance + MediaType hygiene
**Description**: Implement every blackbox test that asserts the SPA's on-wire enum values (`AnnotationStatus`, `MediaStatus`, `Affiliation`, `CombatReadiness`, `MediaType`, `AnnotationSource`) match the contract pinned in `enum_spec_snapshot.json`, plus the MediaType magic-literal hygiene check.
**Complexity**: 2 points
**Dependencies**: AZ-456_test_infrastructure
**Component**: 07_dataset + 06_annotations + cross-cutting (Blackbox Tests)
**Tracker**: AZ-459
**Epic**: AZ-455

## Problem

`AC-04` and `AC-29` require the UI to send/accept the exact numeric values from the suite spec. Today the UI carries drift (documented in `enum_spec_snapshot.json` § `ui_drift_summary`) — for `AnnotationStatus` the UI sends `Edited=1` while the contract pins `Edited=20`. Tests must FAIL on the drift so the regression is visible until the Phase B fix lands; they must NOT silently accept the wrong values.

## Outcome

- 4 test scenarios pass (or fail loudly to document the drift) per the contract pin.
- Tests load `_docs/00_problem/input_data/enum_spec_snapshot.json` once per test file and compare runtime values against the pinned values.
- `verification_pending: true` enums (`CombatReadiness`, `MediaType`) are quarantined with a clear marker until the Step 4 .NET-service inspection lands.

## Scope

### Included

| Scenario | Profile | Source file | results_report row |
|----------|---------|-------------|--------------------|
| FT-P-04 — AnnotationStatus enum on the wire | static + fast | blackbox-tests.md | 14 |
| FT-P-05 — MediaStatus / Affiliation / CombatReadiness enums match the spec | static + fast | blackbox-tests.md | 15, 16, 17 |
| FT-P-06 — detection wire payload — affiliation + combatReadiness in spec value sets | fast + e2e | blackbox-tests.md | 18, 19 |
| FT-N-15 — MediaType magic-literal / magic-string hygiene | static + fast | blackbox-tests.md | per FT-N-15 |

### Excluded

- Annotation save body shape (covered in 05_test_annotations_endpoint).
- DetectionClasses ordering / hotkey path (covered in 17_test_detection_classes).

## Acceptance Criteria

**AC-1: Snapshot-driven assertion**
Given `_docs/00_problem/input_data/enum_spec_snapshot.json` is the contract pin,
When any test in this task runs,
Then it loads the snapshot and asserts the runtime wire value matches the pinned value per row 14, 15, 16, 17, 18, 19 of `results_report.md`.

**AC-2: Drift surfaces, not silently passes**
Given the UI today drifts on `AnnotationStatus` (Edited=1 vs spec 20) and similar,
When the test runs against today's UI,
Then it FAILS with a message naming the enum and the observed-vs-expected pair. (It does NOT pass by re-reading the UI's value as authoritative.)

**AC-3: verification_pending markers**
Given `CombatReadiness` and `MediaType` carry `verification_pending: true` in the snapshot,
When the test sees the flag,
Then it emits a clear QUARANTINE marker (CSV `Result: QUARANTINE`) and a comment naming the resolution path (Step 4 .NET-service inspection).

**AC-4: MediaType magic-literal hygiene (FT-N-15)**
Given the source tree at HEAD,
When the static check scans `src/` for hardcoded numeric `MediaType` literals,
Then any literal not wrapped in the typed enum is flagged.

## System Under Test Boundary

- System under test: the actual fetch URLs and payloads issued by the SPA, the rendered DOM that surfaces enum-derived state, and (for FT-N-15) the source tree itself.
- Allowed stubs: MSW handlers that capture the outbound request and assert the numeric values.
- Disallowed: importing `src/types/index.ts` and comparing the snapshot to it — that's a tautology. The test compares the snapshot to the RUNTIME wire output. Importing the typed enum SHAPES for declaration is fine per `P9` / black-box discipline (the enums are the wire contract).
- Expected observables compared against `_docs/00_problem/input_data/expected_results/results_report.md` rows 14-19.

## Constraints

- Snapshot must be read once per module; cache via Vitest module-level import.
- FT-N-15 runs as a `ripgrep`-driven static check from `scripts/run-tests.sh --static-only`.

## Risks & Mitigation

**Risk 1 — verification_pending lifts mid-implementation**
- *Risk*: If Step 4 .NET-service inspection lands while these tests are being implemented, the snapshot rewrites and a previously-QUARANTINEd test may flip to PASS or FAIL.
- *Mitigation*: tests read the snapshot at runtime — they auto-adapt. The QUARANTINE marker is conditional on the runtime `verification_pending` flag.
