Implements the replay-mode CLI dispatcher per ADR-011 (replay-as-
configuration):
- src/gps_denied_onboard/cli/replay.py: argparse with all 6 required
args (--video, --tlog, --output, --camera-calibration, --config,
--mavlink-signing-key) plus --pace and --time-offset-ms; path
validation, calibration JSON schema-validation, config mutation
(mode='replay' + replay sub-block + signing-key hex on dev_static
field), dispatch into runtime_root.main(config).
- runtime_root.main() now accepts an optional Config (additive,
backward-compat). Adds dedicated catch for ReplayInputAdapterError
mapping to EXIT_FDR_OPEN_FAILURE (2) so the CLI's exit-code matrix
holds end-to-end (AC-9 + epic AZ-265 AC-8).
- Signing-key contents stored as hex; redacted in startup banner.
- Top-level except logs full traceback via logger.exception + stderr
print and exits 1.
The CLI does NOT call compose_root directly — it builds a Config and
hands it to the shared airborne main, which calls compose_root, which
branches on config.mode (AZ-401 / replay protocol Invariant 11).
Tests: 22 unit tests covering AC-1..AC-10 + extras (signing-key
redaction, file-not-dir validation, dev_static propagation, unhandled
exception traceback). Full regression: 2085 passed (+22) green; no
new flaky tests.
Co-authored-by: Cursor <cursoragent@cursor.com>