From f03567a04b68ab19b5f16f0b6d56d9c08b14c818 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 17 Aug 2026 16:00:23 +0200 Subject: test(oracle): a second oracle year, 2038, closing step 4's blind spot Register section 6.7 recorded that step 4 of the reading chain -- the Common route -- had no external witness of any kind, and proved it by mutation: corrupting a Common citation left both the 16801-day differential and the 730-day oracle green. This closes that. 2038 is the only year in 2005-2050 in which two of the five Common-routed saints are the observed office (Perpetua and Felicitas on 6 March, Frances of Rome on 9 March). 365 days were captured live, one request per day, zero failures. A separate fixture, not more rows on the existing one. sources.md already records that the live endpoint has drifted from lectio's archived 2026-2027 snapshot; merging two versions of one source behind a single set of expectations would make any future disagreement unattributable -- calendar or drift, no way to tell. Nothing in the 2038 comparison is checked against the older fixture, and its provenance file says so, along with the fact that a live capture is not reproducible byte-for-byte on demand the way a snapshot-derived one is. 338 of 365 days match. 27 differ, every one of them in a named, already-adjudicated class, none unexplained: 13 the BVM Saturday votive Mass (M26 shape 1), 7 colour (M21), 2 Judith (M28), 2 Christ the King's week (M26 shape 2b), 1 Christmas multi-Mass (M27), 1 Perpetua's Common, 1 new. Each was decided in a different year, so 2038 re-confirms them independently -- the point of a second window is not new rulings but evidence the old ones are not artefacts of their own year. Two findings came out of it. Perpetua and Felicitas: missalemeum serves the Common of Virgins and calls them "Virgins and Martyrs" in its own oration, where the Missal directs "Missa Me exspectaverunt, de Communi non Virginum I loco" (scan1:27634-27635). Both Commons share the Introit Ps 118:95-96, which is exactly why the calendarium qualifies its direction, and both women were mothers. Verdict colitur; the mechanism is located on missalemeum's side, not merely asserted. Passion Tuesday: the Missal prints "Dan. 14, 27 et 28-42" (scan1:11106) and colitur reproduces that two-part form where missalemeum collapses it to 27-42. Same verses; the convention is deliberate, appearing also in the Seven Sorrows and the Common of Non-Virgins. Verdict colitur, cosmetic. Citations are notation-normalised before comparing, as layer 3 already does: Ecclus/Sir, Joann/John, Luc/Luke, Matth/Matt. Each pair was added because a real row needed it, and no target contains its own source as a substring, so the set is idempotent. Not compared, stated rather than left to be found: commemorations and observed-identity. That machinery is built around a date-literal 28-entry allow-list specific to 2026-2027, and re-deriving it for a second year is its own task. 2038 compares rank, colour, Epistle, Gospel. The extractor's day count was hardcoded to 730, which silently forbade any other window. It is now a parameter defaulting to 730, so the existing documented command keeps its guard and a partial fetch still fails loudly instead of producing a short fixture that passes a comparison it never ran. Teeth, by re-running section 6.7's own experiment: corrupting the Common of Non-Virgins II now reddens four tests, two of them external-oracle, where the same mutation previously reddened neither oracle layer. Residual: isidore-of-seville is still unwitnessed and needs 2035 or 2046; gregory-the-great and patrick are never the observed office in any year 2005-2050, so no fixture in that range can reach them. Register section 6.8 and 6.9. --- tools/extract_missalemeum_oracle.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/extract_missalemeum_oracle.py b/tools/extract_missalemeum_oracle.py index 1abc574..6d3f8f0 100644 --- a/tools/extract_missalemeum_oracle.py +++ b/tools/extract_missalemeum_oracle.py @@ -111,10 +111,19 @@ def extract_citation(sections, section_id, date, label): def main(): - if len(sys.argv) != 3: - print(f"usage: {sys.argv[0]} ", file=sys.stderr) + # (added 2026-08-17, the 2038 oracle extension) is the + # number of day-files this run MUST produce, stated by the caller rather + # than hardcoded. It used to be a bare `!= 730`, which silently forbade + # extracting any window other than the original 2026-2027 pair. It stays + # MANDATORY-in-effect via its default so the existing documented command + # keeps its own guard unchanged: a partial fetch (a dropped HTTP request, + # an interrupted unpack) must fail loudly here rather than quietly + # produce a short fixture that then "passes" a comparison it never ran. + if len(sys.argv) not in (3, 4): + print(f"usage: {sys.argv[0]} [expected-days]", file=sys.stderr) return 2 snapshot_dir, out_path = sys.argv[1], sys.argv[2] + expected_days = int(sys.argv[3]) if len(sys.argv) == 4 else 730 src = os.path.join(snapshot_dir, "missalemeum", "en") rows = [] for fname in sorted(os.listdir(src)): @@ -153,8 +162,8 @@ def main(): f"|{cit_first}|{cit_gospel}" ) - if len(rows) != 730: - print(f"ERROR: expected 730 days, got {len(rows)}", file=sys.stderr) + if len(rows) != expected_days: + print(f"ERROR: expected {expected_days} days, got {len(rows)}", file=sys.stderr) return 1 with open(out_path, "w", encoding="utf-8") as f: -- cgit v1.3