Files
troupe-standup/wizard-work/ledger/CHECK-2026-11-01-openmeteo-weather
T

60 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# CHECK — ledger: open-meteo weather extract (2026-11-01).
#
# Exits 0 iff the committed table (2026-11-01-openmeteo-weather.csv) is a
# faithful re-derivation of the committed raw source snapshot (openmeteo-source-2026-11-01.json).
# The CSV's own generator is NOT imported; the table is rebuilt cell-by-cell from
# the source JSON with plain python. No `|| true` / `; exit 0` fallback: the
# last command's exit code is the verdict.
set -u
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$DIR" || exit 2
python3 - <<'PY'
import csv
import json
import sys
src = json.load(open("openmeteo-source-2026-11-01.json"))
rows = list(csv.DictReader(open("2026-11-01-openmeteo-weather.csv")))
def cell(value):
# Numbers round-tripped by the generator: keep as str() so csv and json
# representations must agree exactly.
return str(value)
expected = []
for city, info in src.items():
g = info["geocode"]
w = info["weather"]
expected.append({
"city": city,
"country": g["country"],
"lat": cell(g["lat"]),
"lon": cell(g["lon"]),
"current_time": w["current_time"],
"temperature_2m": cell(w["temperature_2m"]),
"apparent_temperature": cell(w["apparent_temperature"]),
"relative_humidity_2m": cell(w["relative_humidity_2m"]),
"weather_code": cell(w["weather_code"]),
"weather_desc": w["weather_desc"],
"wind_speed_10m": cell(w["wind_speed_10m"]),
"today_max": cell(w["today_max"]),
"today_min": cell(w["today_min"]),
"today_precip": cell(w["today_precip"]),
})
if len(rows) != len(expected):
print("ROW COUNT MISMATCH csv=%d expected=%d" % (len(rows), len(expected)))
sys.exit(1)
for r, e in zip(rows, expected):
for key in e:
if r.get(key) != e[key]:
print("CELL MISMATCH row=%r column=%r csv=%r src=%r" % (r.get("city"), key, r.get(key), e[key]))
sys.exit(1)
print("rows=%d cities=%s re-derived from source snapshot — PASS" % (len(rows), ", ".join(r["city"] for r in rows)))
PY