f5d119fbe7
Add check_matched_pair_drift() at module level in store.py — read-only audit of the Claim.matched_remittance_id ↔ Remittance.claim_id FK pair. Logs WARNING on drift with up to 5 examples of each of two cases (claim-side and remit-side), returns the count of drifted rows. Wired into api.py::lifespan right after db.init_db() and ensure_clearhouse_seeded(), wrapped in try/except so a query failure logs but doesn't crash boot. The symmetric-write + symmetric-clear invariants on manual_match / manual_unmatch were already correct; this commit pins them with focused regression tests in test_store_match_invariant.py (8 tests covering both directions, both happy-path, rollback pin, and drift-check unit behavior). PCN asymmetry in the fixture prevents the auto-match inside CycloneStore.add (Task 10) from pre-pairing, so manual_match is the only writer. Migration 0016 adds the missing ix_claims_matched_remittance_id index — the drift check scans WHERE matched_remittance_id IS NOT NULL on every boot and would become a full-table scan past ~10k claims. Symmetric with ix_remittances_claim_id (added in 0007). Migration tests bumped from head=15 to head=16.