diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-26 13:57:14 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-26 13:57:14 +0200 |
| commit | 03d3c00ccdde318207c8b4fdc456e5e64d6b4abf (patch) | |
| tree | eaa8b77b549f6751594b2868798c7ca2d1b3ca70 /test/test_validate_of.ml | |
| parent | 9b8821f7b914c94f5b2c8eeda05407ee921b3d5a (diff) | |
| download | colitur-03d3c00ccdde318207c8b4fdc456e5e64d6b4abf.tar.gz colitur-03d3c00ccdde318207c8b4fdc456e5e64d6b4abf.zip | |
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.
Diffstat (limited to 'test/test_validate_of.ml')
| -rw-r--r-- | test/test_validate_of.ml | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/test/test_validate_of.ml b/test/test_validate_of.ml index a8a6001..5c64710 100644 --- a/test/test_validate_of.ml +++ b/test/test_validate_of.ml @@ -14,20 +14,26 @@ down, not a replacement for Task 5's own tests (which stay as they are, including their own three pinned defects -- see below). - THE THREE KNOWN, PINNED-NOT-FIXED GAPS (Task 5's own report; do not - relitigate here, only avoid papering over them): + THE KNOWN, PINNED-NOT-FIXED GAPS (Task 5's own report; do not relitigate + here, only avoid papering over them). Originally three; now two -- see + item 2's own CLOSED note: 1. Normae n. 35(a)'s Holy Family fallback is unreached whenever Christmas Day is itself a Sunday (test_rite_of.ml's own [is_known_holy_family_fallback_gap]/ [test_holy_family_fallback_1583_known_wrong_ferial]) -- fires on roughly one year in seven, first hit at 1583. - 2. The lectionary (data/of/lectionary.sexp) was audited against only one - civil year (2026) -- surfaces here as [Validate]'s own - ["citations-unresolved"]/["formulary"] gap on 25 December every year - (test_rite_of.ml's own [is_known_nativity_gap]), and, more broadly, - as a citation-chain gap this file's own comparators (which never - touch citations/formulary at all -- see the "what this layer cannot - see" note at the end) cannot see beyond that one symptom either way. + 2. CLOSED, fix wave I8 (final-review.md, 2026-08-25-colitur-of-phases- + 3-5). Used to read: "The lectionary (data/of/lectionary.sexp) was + audited against only one civil year (2026) -- surfaces here as + [Validate]'s own [\"citations-unresolved\"]/[\"formulary\"] gap on 25 + December every year". tools/bootstrap_lectionary_of.ml's own + [hand_authored] table now injects the Christmas Day Mass directly + (Isa 52:7-10/John 1:1-18, OLM 1981's own "16 Ad Missam in die"), so + this fires on ZERO years now, verified across the whole domain by + [test_exhaustive_domain_sweep]'s own [nativity_gap_years] counter + below -- not merely assumed from the fix. [is_known_nativity_gap] + itself is kept, as a dedicated "this must never recur" check, not + deleted. 3. St Joseph / Palm Sunday (Normae n. 56(f)) -- invisible to [Validate.run] entirely: the impeded solemnity is still transferred exactly once, to SOME later date, so no structural check @@ -98,6 +104,12 @@ 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 +(* CLOSED, fix wave I8 (final-review.md, 2026-08-25-colitur-of-phases-3-5): + see test_rite_of.ml's own [is_known_nativity_gap] header for the + citation and the full argument (this predicate is duplicated from that + file, this file's own header already states why -- not shared through a + .mli). Kept as an explicit "this must never fire again" check, no longer + part of [is_known_gap]'s own filter below. *) let is_known_nativity_gap (f : Val.failure) = (f.Val.check = "citations-unresolved" || f.Val.check = "formulary") && ends_with ~suffix:"12-25" f.Val.date @@ -109,7 +121,10 @@ let contains ~substring s = let is_known_holy_family_fallback_gap (f : Val.failure) = f.Val.check = "anchor" && contains ~substring:"of-holy-family" f.Val.detail -let is_known_gap f = is_known_nativity_gap f || is_known_holy_family_fallback_gap f +(* Fix wave I8: [is_known_nativity_gap] deliberately excluded -- see its own + header just above. A recurrence now surfaces as an ordinary unexpected + failure everywhere this predicate is used to filter. *) +let is_known_gap f = is_known_holy_family_fallback_gap f let unexplained_failures year = List.filter (fun f -> not (is_known_gap f)) (run year) @@ -268,6 +283,12 @@ let test_exhaustive_domain_sweep () = for y = 1583 to 9998 do let fs = run y in let hf = List.exists is_known_holy_family_fallback_gap fs in + (* Fix wave I8: expected to be [false] every single year now -- kept + as a live measurement, not deleted, so a regression anywhere in + the domain increments this counter AND (via [is_known_gap] no + longer absorbing it) fails the loop below immediately, on the + first year it recurs, rather than only being caught by the + summary assertion after the full sweep completes. *) let nat = List.exists is_known_nativity_gap fs in if hf then incr holy_family_gap_years; if nat then incr nativity_gap_years; @@ -288,33 +309,39 @@ let test_exhaustive_domain_sweep () = (not (List.exists (fun f -> f.Val.check = "coverage") fs_9999)); Alcotest.(check bool) "9999: seasons check flags the truncated final year as incomplete" true (List.exists (fun f -> f.Val.check = "seasons") fs_9999); - Alcotest.(check (list string)) "9999: nothing OTHER than the documented seasons truncation (and the three \ - known, pinned gaps) fired" + Alcotest.(check (list string)) "9999: nothing OTHER than the documented seasons truncation (and the two \ + remaining known, pinned gaps) fired" [ "seasons" ] (List.sort_uniq compare (List.map (fun f -> f.Val.check) (List.filter (fun f -> not (is_known_gap f)) fs_9999))); - (* Both known gaps are real and not vacuous across the FULL domain, not - merely on the handful of years the sampled property happens to draw - -- the Nativity gap fires on literally EVERY year (25 December - always exists); the Holy Family gap fires on roughly one year in - seven (whenever 25 December is a Sunday). Pinned as a range, not an - exact count, deliberately: the exact figure is a real, computable - fact about the Gregorian calendar's own 400-year cycle, but pinning - it to the digit would make this test fail the moment a future - COLITUR_EXHAUSTIVE_SWEEP run's own domain bounds shift by even one - year at either edge, for a reason having nothing to do with - colitur's own correctness. *) - Alcotest.(check int) "the Nativity citation/formulary gap fires on every one of the 8 416 swept years" - 8416 !nativity_gap_years; + (* The Holy Family gap is real and not vacuous across the FULL domain, + not merely on the handful of years the sampled property happens to + draw -- it fires on roughly one year in seven (whenever 25 December + is a Sunday). Pinned as a range, not an exact count, deliberately: + the exact figure is a real, computable fact about the Gregorian + calendar's own 400-year cycle, but pinning it to the digit would + make this test fail the moment a future COLITUR_EXHAUSTIVE_SWEEP + run's own domain bounds shift by even one year at either edge, for a + reason having nothing to do with colitur's own correctness. *) Alcotest.(check bool) "the Holy Family fallback gap fires on a real, non-trivial fraction of years \ (roughly one in seven)" true - (!holy_family_gap_years > 1000 && !holy_family_gap_years < 1400) + (!holy_family_gap_years > 1000 && !holy_family_gap_years < 1400); + (* CLOSED, fix wave I8: the Nativity gap used to fire on literally every + one of the 8 416 swept years (25 December always exists). Now + exactly zero -- across the WHOLE domain, not merely the 4 landmark + years test_rite_of.ml's own [test_landmark_years] already checks, + which is the entire reason this dedicated exhaustive counter is kept + rather than deleted alongside the rest of the old gap-tracking. *) + Alcotest.(check int) "the Nativity citation/formulary gap fires on NONE of the 8 416 swept years (fix \ + wave I8 -- was 8 416)" + 0 !nativity_gap_years end let suite = ( "Validate (OF, real data: Rite_of.context)", - [ Alcotest.test_case "landmark years validate cleanly (modulo the three known gaps)" `Quick test_landmark_years; + [ Alcotest.test_case "landmark years validate cleanly (modulo the two remaining known gaps)" `Quick + test_landmark_years; Alcotest.test_case "year 9999 does not raise; seasons flags the clamp, nothing else (beyond the known \ gaps) fires" `Quick test_year_9999_does_not_raise; |
