From 03d3c00ccdde318207c8b4fdc456e5e64d6b4abf Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 26 Aug 2026 13:57:14 +0200 Subject: feat(of-lectionary): hand-author the Christmas Day Mass, close the gap colitur readings --rite of printed "- | -" on 25 December every year -- lectio's own 988 keys never included the Christmas DAY Mass at all, only the Vigil (already correctly noted, but left unfilled, in tools/bootstrap_lectionary_of.ml's own named_overrides comment). Sourced, not guessed: docs/research/of/olm-1981-ocr.txt:4513-4520, "16 Ad Missam in die", the same primary authority this module already cites for the cycle rules. First reading and Gospel only, matching this file's own scope everywhere else (First/Gospel is the kernel's own boundary, I7, a separate deferred task) -- Isaiah 52:7-10 / John 1:1-18 (OLM's own LONGER form; the file's LINEAGE section already discloses that short/long-form choices are not modelled anywhere in this data, so this is an application of an existing limitation, not a new one). Injected via a new hand_authored table in the generator, merged into entries before assert_reachable/Lectionary.of_entries -- there is no ini section to derive this from. One new lookup_any call (readings' own existing temporal-slug fallback, unmodified) now resolves BOTH the formulary and the citations for 25 December from the same entry, so both halves of the "citations-unresolved"/"formulary" gap close together, not just the citation half. Verified across the WHOLE domain, not assumed: test_validate_of.ml's exhaustive sweep (COLITUR_EXHAUSTIVE_SWEEP=1, all 8 416 years) now asserts the Nativity gap fires on NONE of them, down from all 8 416 before this fix -- and is kept as a live, dedicated "must never recur" counter rather than deleted. test_rite_of.ml's landmark-year check and test_lectionary_of.ml's 2026 coverage pins are updated the same way (the unresolved-day set that used to be pinned as {25 December} is now pinned as empty, not merely a count going to zero). A concrete golden pin (test_golden_of.ml) locks the exact citations through the full resolved pipeline. data/of/lectionary.sexp regenerated (771 entries, was 770); its own SHA-256 re-pinned. make check (COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force, unpiped, foreground): exit 0, 895 tests, ~536s. --- test/test_rite_of.ml | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'test/test_rite_of.ml') diff --git a/test/test_rite_of.ml b/test/test_rite_of.ml index a1892ae..5e369b8 100644 --- a/test/test_rite_of.ml +++ b/test/test_rite_of.ml @@ -77,21 +77,25 @@ let real_of_rite = Rite_of.context ~lectionary:real_of_lectionary let run year = Val.run real_of_rite real_of_layer ~year -(* data/of/lectionary.sexp's own provenance header names ONE informational - temporal-slug gap: [of-nativity] (25 December -- Christmas Day itself) - has no entry, because niedziela.pl's own source keys the Nativity's - several Masses (Vigil/Night/Dawn/Day) differently than a single flat - slug can address, and [Lectionary_of.readings] has no fallback beyond - its own three-step chain (unlike EF's RG 299 preceding-Sunday rule, - which OF's own OLM Praenotanda gives no equivalent for -- see - lectionary_of.mli's own citation). This makes {!Colitur_kernel.Validate - .run}'s ["citations-unresolved"] check fire exactly once a year, on 25 - December, on real shipped data -- a documented, measured gap in - lectionary_of's own data file (out of this task's scope to touch or - close: lectionary_of.* is excluded from this task's brief), not a defect - this module's wiring introduced. Named and filtered explicitly, never - silently dropped, so a future SECOND gap (a regression) still reddens - this test. *) +(* CLOSED, fix wave I8 (final-review.md, 2026-08-25-colitur-of-phases-3-5). + This paragraph used to describe a LIVE gap: data/of/lectionary.sexp's + own provenance header named ONE informational temporal-slug gap, + [of-nativity] (25 December -- Christmas Day itself), because + niedziela.pl's own source never covered the Christmas DAY Mass at all + (only the Vigil), which made {!Colitur_kernel.Validate.run}'s + ["citations-unresolved"]/["formulary"] checks fire every year, on 25 + December, on real shipped data. tools/bootstrap_lectionary_of.ml's own + [hand_authored] table now injects that entry directly (Isaiah 52:7-10 / + John 1:1-18, OLM 1981's own "16 Ad Missam in die", + docs/research/of/olm-1981-ocr.txt:4513-4520) -- a primary-source + citation, not a guess, the same discipline every other hand-authored + entry in this project follows. [is_known_nativity_gap] is kept, not + deleted, but is no longer in [is_known]'s own filter below: it now + exists ONLY as an explicit, named "this must never fire again" check + ({!check_year_allowing_known_gaps}'s own dedicated assertion) -- a + regression here surfaces as an ordinary unexpected-failure test error, + not a silently-absorbed known gap, which is the whole point of moving a + predicate out of the filter once its own defect closes. *) let ends_with ~suffix s = let ls = String.length s and lx = String.length suffix in ls >= lx && String.sub s (ls - lx) lx = suffix @@ -141,18 +145,19 @@ let is_known_holy_family_fallback_gap (f : Val.failure) = let check_year_allowing_known_gaps year = let fs = run year in - let is_known f = is_known_nativity_gap f || is_known_holy_family_fallback_gap f in + (* Fix wave I8: [is_known_nativity_gap] is deliberately NOT part of + [is_known] any more -- see that predicate's own header. Only the + Holy Family fallback gap is still filtered out here. *) + let is_known f = is_known_holy_family_fallback_gap f in let unexpected = List.filter (fun f -> not (is_known f)) fs in (match unexpected with | [] -> () | fs -> Alcotest.failf "%d: %s" year (String.concat "; " (List.map Val.failure_to_string (List.filteri (fun i _ -> i < 5) fs)))); - let nativity_gaps = List.filter is_known_nativity_gap fs in Alcotest.(check int) - (Printf.sprintf "%d: exactly the two documented of-nativity checks (citations-unresolved + \ - formulary), no more" year) - 2 (List.length nativity_gaps) + (Printf.sprintf "%d: no of-nativity citations-unresolved/formulary gap (fix wave I8 -- was 2)" year) + 0 (List.length (List.filter is_known_nativity_gap fs)) (* Landmark years, the same choice test_validate.ml's own [test_landmark_years] makes for EF: both domain edges plus two ordinary -- cgit v1.3