# FT-P-07 + FT-N-02 — Sharp-turn recovery (positive + negative twin)

**Task**: AZ-414_ft_p_07_ftn_02_sharp_turn
**Name**: Sharp-turn recovery via satellite reference + legitimate frame-to-frame failure expected (AC-3.2)
**Description**: Implement FT-P-07 (recovery within 3 frames of turn end; drift ≤ 200 m, heading change handled) AND FT-N-02 (during turn, source_label is `visual_propagated` or `dead_reckoned`; covariance grows; recovery exercised in FT-P-07). Both scenarios share the sharp-turn segment fixture.
**Complexity**: 3 points
**Dependencies**: AZ-406, AZ-407
**Component**: Blackbox Tests / Positive + Negative (epic AZ-262)
**Tracker**: AZ-414
**Epic**: AZ-262 (E-BBT)

## Problem

Sharp turns are a documented degradation case (AC-3.2). The system must label the turn frames correctly (FT-N-02) AND recover when the turn ends (FT-P-07) — both halves must be measured to validate the failure-path correctness.

## Outcome

- pytest scenario at `e2e/tests/positive/test_ft_p_07_sharp_turn_recovery.py` (FT-P-07) and `e2e/tests/negative/test_ft_n_02_sharp_turn_failure.py` (FT-N-02).
- Both replay the sharp-turn segment of Derkachi (identified by gyro_z spikes in `SCALED_IMU2`).
- FT-P-07 asserts: source_label returns to `satellite_anchored` within 3 frames of turn end; drift since pre-turn anchor ≤ 200 m; heading change up to 70° handled.
- FT-N-02 asserts: during turn, source_label ∈ `{visual_propagated, dead_reckoned}`; covariance grows monotonically; transitions to satellite_anchored after turn (handed off to FT-P-07 for the recovery assertion).
- Synthetic-gyro-overlay fallback: if the natural Derkachi flight has no sharp turn meeting AC-3.2 thresholds, both scenarios fall back to a synthetic gyro overlay; this fact is flagged in the FDR record + CSV `evidence_paths`.

## Scope

### Included
- Sharp-turn segment identification via gyro_z spikes in `data_imu.csv`.
- Synthetic-gyro overlay fallback path (use the same approach as outlier injector for determinism).
- FT-P-07 recovery assertions (label transition, drift, heading-change tolerance).
- FT-N-02 during-turn assertions (label, monotonic covariance).

### Excluded
- Multi-segment satellite re-localization — owned by FT-P-08 (AZ-415).
- Outlier-injection tolerance — owned by FT-N-01 (AZ-424).

## Acceptance Criteria

**AC-1: turn-segment identification**
Given Derkachi `data_imu.csv`
Then the test computes gyro_z magnitude per IMU row and identifies segments where ≥3 consecutive rows have `|gyro_z| > AC-3.2 threshold`. If no segment meets the threshold, the synthetic-overlay fallback fires and the FDR + CSV mark this as `synthetic-overlay`.

**AC-2: FT-N-02 during-turn label**
Given a turn segment
Then for every frame inside the segment, source_label ∈ `{visual_propagated, dead_reckoned}` (no `satellite_anchored` during the turn).

**AC-3: FT-N-02 monotonic covariance**
Given the during-turn frames
Then `cov_semi_major_m` is non-decreasing across consecutive frames within the turn segment.

**AC-4: FT-P-07 recovery within 3 frames**
Given a turn-end timestamp
Then the next satellite_anchored emission occurs within ≤3 frames after that timestamp.

**AC-5: FT-P-07 drift bound**
Given the recovery anchor
Then `‖propagated_centre_at_turn_end − recovery_anchor_centre‖ ≤ 200 m`.

**AC-6: FT-P-07 heading-change envelope**
Given the heading delta from pre-turn to post-turn anchor
Then heading changes up to 70° are handled (the recovery still occurs within the 3-frame budget at heading deltas in [0°, 70°]).

**AC-7: parameterization**
Given conftest parameterization
Then both scenarios run per `(fc_adapter, vio_strategy)`.

## System Under Test Boundary

End-to-end through public boundaries.

- **Allowed**: outbound message stream (`source_label`, `cov_semi_major_m`); FDR for the synthetic-overlay flag.
- **Forbidden**: stubbing C1 VIO failure mode, monkeypatching the source-label state machine.

## Constraints

- Synthetic-gyro overlay fallback is determined per-run by checking the natural fixture; the choice is logged into FDR and CSV `evidence_paths`.
- The sharp-turn threshold per AC-3.2 is the project's authoritative value (gyro_z magnitude + duration); this test reads that threshold from the test-spec environment, not from a hardcoded constant.

## Document Dependencies

- `_docs/02_document/tests/blackbox-tests.md` § FT-P-07, § FT-N-02
- `_docs/02_document/tests/test-data.md` § Image processing quality / Resilience
