FICTIONAL TRAINING-HISTORY MIGRATION — 12 October 2026 All six activities and destination observations are invented. No account or workout file was imported. These are reconciliation examples, not service tests. Run locally with Python 3.9 or later (standard library only): python3 verify_migration.py expected.csv first-pass.csv python3 verify_migration.py expected.csv reconciled.csv The first command exits 1 with exactly three problems, although both counts are six. The second exits 0. Different local dates with equivalent UTC instants pass; timezone-less timestamps are rejected. COLUMNS source_key: a manually reviewed mapping to one original activity. The script does not discover identities or read destination identifiers. start_time: ISO 8601 with Z or an explicit UTC offset. sport: a manually normalized category; it must match exactly. elapsed_seconds: elapsed duration, not moving time; tolerance 1 second. distance_meters: known source distance; tolerance 1 metre. A blank source value means unknown/not required, not zero. Destinations that recalculate distance need a separately justified reconciliation policy. has_route / has_heart_rate / has_power: 1 means present, 0 absent. Required source fields must be present. These flags do not prove values, units, sample counts, sampling times, sport-specific details, notes, photos or social content match. Keep your real source/destination ledger private. The checker has no network or account access. Passing its bounded checks is not proof of upload acceptance or a complete migration; inspect the destination and important streams too.