aboutsummaryrefslogtreecommitdiff
path: root/scripts/build-oracle-ef.sh
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-12 17:15:03 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-12 17:15:03 +0200
commit3b32c002d3eddda5ece9422442717657b9fee63b (patch)
tree5dd82811c100de6daa995bebd115a12434296508 /scripts/build-oracle-ef.sh
parent2386a4551aec94252168a8554269ee423d516882 (diff)
parentc655c525ef07deafb113a291489b396c81d7ce4a (diff)
downloadlectio-3b32c002d3eddda5ece9422442717657b9fee63b.tar.gz
lectio-3b32c002d3eddda5ece9422442717657b9fee63b.zip
Merge branch 'fix/ef-precedence-defects': seven EF calendar defects
Fixes seven defects in the EF calendar, each found by differential and oracle comparison against an independently-written engine and each backed by a cited paragraph of the Rubricae Generales verified against the 1962 Missal: RG 96 transfers must skip II-class days (the Precious Blood was landing on the Visitation) RG 91 a II-class privileged feria yields to an equal-class feast (St Matthew was losing to the September Ember Wednesday) RG 11 all Sundays of Advent, Lent and Passiontide are I class (only Advent I was), which also settles St Joseph on a Lent Sunday RG 131 Rose on Gaudete and Laetare, which the EF path never emitted RG 122 Holy Thursday is white and the sanctoral generator itself, whose rank inference had tagged 15 III-class feasts as commemorations, dropped four entries to slug collisions, and mis-tagged three class fields. The EF oracle test asserted Season only, which is why none of this ever failed. It now asserts rank and colour, with a cited allow-list. Two commemorations had been deleted on a primary-source claim the primary source contradicts: the Archivum Liturgicum transcription silently drops commemoration lines where the photographic scans carry them. Six of the seven affected dates are now present; the seventh (25 December) is blocked by an ingestion limit that reads only the first of three Christmas Masses, recorded at its cause. Known gap, recorded in source: RG 95/97/98 chained transfers, where two I-class feasts translate to the same day.
Diffstat (limited to 'scripts/build-oracle-ef.sh')
-rwxr-xr-xscripts/build-oracle-ef.sh56
1 files changed, 30 insertions, 26 deletions
diff --git a/scripts/build-oracle-ef.sh b/scripts/build-oracle-ef.sh
index 2864551..32cb385 100755
--- a/scripts/build-oracle-ef.sh
+++ b/scripts/build-oracle-ef.sh
@@ -1,38 +1,42 @@
#!/usr/bin/env bash
-# build-oracle-ef.sh — generate the EF (1962) regression oracle by fetching
-# missalemeum's per-date proper API (the same source lectio's trad scraper uses,
-# built on Divinum Officium data) for 2025-2026.
+# build-oracle-ef.sh — build the EF (1962) regression oracle from the committed
+# missalemeum snapshot (sources/snapshot.tar.gz, missalemeum/en/YYYY-MM-DD.json,
+# 2026-01-01 .. 2027-12-31, 730 days), not a live fetch, so the oracle is
+# reproducible offline and pinned to a known-good snapshot.
#
-# NOT run by `go test`. Requires network + curl + jq + GNU date. From repo root:
+# Three things about this data that cost hours to learn (see oracle_ef_test.go):
+# 1. info.id looks like "sancti:MM-DD:rank:colour", but its embedded rank is
+# the rank of the PROPERS USED that day, not the day's own rank (e.g.
+# 2026-01-02 is a class-4 feria whose id is "sancti:01-01:1:w" because it
+# reuses the Circumcision's propers). Extracted here for provenance only
+# -- never parse rank/colour out of it. Use info.rank/info.colors.
+# 2. info.colors is an array; 14 of 730 days carry two values (Gaudete/
+# Laetare "pv", Palm Sunday "rv", Good Friday "bv", Holy Saturday "vw").
+# The Go test compares by membership, not equality.
+# 3. A two-colour value on a weekday can be a proper-reuse artifact (a feria
+# inside Gaudete/Laetare week reusing the Sunday's own propers) rather
+# than a claim about that weekday's own colour.
+#
+# From repo root:
# scripts/build-oracle-ef.sh
# Writes internal/calendar/testdata/oracle-ef.json:
-# { "YYYY-MM-DD": {"tempora": "...", "title": "...", "rank": N, "colour": "w"} }
-# tempora is "" when missalemeum returns null (then the temporal identity is in
-# title); the Go test derives the season from tempora-or-title.
+# { "YYYY-MM-DD": {"id":"...", "tempora":"...", "title":"...", "rank":N, "colours":["w",...]} }
set -euo pipefail
out=internal/calendar/testdata/oracle-ef.json
-mkdir -p "$(dirname "$out")"
work=$(mktemp -d)
+trap 'rm -rf "$work"' EXIT
-for y in 2025 2026; do
- d="$y-01-01"
- while [ "$(date -d "$d" +%Y)" = "$y" ]; do
- echo "$d"
- d=$(date -d "$d +1 day" +%F)
- done
-done > "$work/dates"
+tar xzf sources/snapshot.tar.gz -C "$work" missalemeum/en
-fetch() {
- local d="$1"
- local j
- j=$(curl -sf --max-time 25 "https://www.missalemeum.com/en/api/v5/proper/$d" || true)
- printf '%s' "$j" | jq -c --arg d "$d" \
- '{($d): (.[0].info | {id:(.id // ""), tempora:(.tempora // ""), title:.title, rank:.rank, colour:(.colors|join(""))})}' \
- 2>/dev/null || true
-}
-export -f fetch
+jq -s '
+ map({(.[0].info.date): {
+ id: (.[0].info.id // ""),
+ tempora: (.[0].info.tempora // ""),
+ title: .[0].info.title,
+ rank: .[0].info.rank,
+ colours: .[0].info.colors
+ }}) | add
+' "$work"/missalemeum/en/*.json > "$out"
-xargs -P 12 -I{} bash -c 'fetch "$@"' _ {} < "$work/dates" | jq -s 'add' > "$out"
echo "wrote $out ($(jq 'length' "$out") days)" >&2
-rm -rf "$work"