# Versioned market-valuation cache audit

Use this checklist for read-only reviews of valuation jobs that reuse historical quotes while changing an algorithm/source key.

## Trace the complete lineage

1. Identify the idempotency tuple and deterministic run-ID inputs. Verify the algorithm/source version participates in both so an algorithm change creates a distinct run without colliding with the old one.
2. Seed or simulate an existing completed or partial v1 run, then execute v2 for the same cutoff and input fingerprint. Do not test v2 only against an empty database.
3. Compare before/after rows for every shared input table, especially quote and FX upserts. A preserved run or snapshot is insufficient if its `market_prices` or `fx_rates` rows are repointed to the new `run_id`, overwritten, or otherwise lose old provenance.
4. Require the new run to identify reused inputs specifically. A generic cache reason is inadequate when the snapshot or audit lacks the cached row ID, original run ID, provider, symbol, source timestamp, or another immutable lineage reference.

## Exact-cutoff cache boundary

A cached quote should be accepted only when all applicable invariants hold:

- instrument ID matches;
- stored `price_date` equals the effective cutoff exactly;
- parsed source timestamp is not after the cutoff under explicit timezone/date semantics;
- provider and provider symbol match the currently approved mapping;
- currency matches the mapping/instrument expectation;
- close is valid and positive;
- original quality is eligible and is never silently upgraded.

Probe negative counterexamples independently: prior/future date, future timestamp, wrong provider, wrong symbol, wrong currency, zero/invalid close, and stale/error/conflict quality.

## Quality and coverage honesty

Preserve source quality separately from age-derived freshness. If a cached row is marked `stale`, do not classify it as fresh merely because its timestamp is on the cutoff date. Coverage, valuation quality, reason codes, and displayed freshness must use the conservative combined quality.

Audit counters by their literal names:

- `price_stored` counts writes attributable to this run, not all usable quotes;
- if cached inputs count toward coverage, expose that separately, such as `price_reused`;
- a complete status may include an explicit cache reason, but must not erase stale or degraded quality.

## Deterministic runtime probes

Beyond the ordinary green suite, run two disposable-database probes:

1. **v1 to v2 provenance:** execute v1 partial, capture quote/FX IDs and `run_id`s, execute v2 at the same cutoff, then assert the v1 run, snapshots, and referenced source rows remain unchanged while a distinct v2 run/snapshot is added.
2. **Stale cache:** seed an exact-date, correctly mapped cached quote with `quality_status='stale'`, force the live provider to miss, and assert coverage/status remain explicitly degraded with `stale_price` preserved.

Also compare reported `*_stored` counters with actual row-count deltas attributable to the new run.

## Review-report shape

When the user requests concrete findings only, return severity, exact current-file line references, the violated invariant, and a concrete observed or deterministic failure mode. Tie test-gap findings to a demonstrated risky branch rather than listing generic missing tests.