aboutsummaryrefslogtreecommitdiff
path: root/test/test_rite_of.ml
Commit message (Collapse)AuthorAgeFilesLines
* fix(of): break the movable-BVM-memorial tie per a CDWDS NotificationLukasz Kasprzak2026-08-271-27/+38
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Mary, Mother of the Church (Easter+50) and the Immaculate Heart of Mary (Easter+69) are both movable obligatory memorials that can land on a FIXED obligatory memorial's own date -- e.g. 2011-06-13 and 2015-06-13, both against Anthony of Padua. Both candidates banded identically at Tabula III.10 (100, both universal Memoria_obligatoria), a tie band could not break, so Precedence.resolve's kernel-level alphabetical Slug.compare tie-break silently picked instead -- 892 days for Mater Ecclesiae and 1109 for the Immaculate Heart across 1583-9999, all one shape (measured against the pre-fix alphabetical order directly, zero unexplained). Searched the corpus rather than inventing a rule. colitur's two previously-checked primary sources really are silent: the 2018 decree (AAS 110, 437-438) never addresses universal-calendar coincidence, and Normae n. 14's third clause resolves only two AD-LIBITUM memorials colliding. A third source resolves it: the CDWDS's own "Notification on the Memorial of the Blessed Virgin Mary, Mother of the Church" (24 March 2018 -- same dicastery and signatories as the decree; published only on vatican.va, confirmed absent from the AAS 2018 combined index) states that when this memorial "coincides with another Memorial of a Saint or Blessed... the Memorial of the Blessed Virgin Mary is to prevail," and extends the identical reasoning to the Immaculate Heart of Mary by name. This is a rubric, not colitur's own reasoned choice. Implemented as a sub-rank of 95, strictly between Tabula entries 9 and 10 -- the same "fits between neighbours" technique this module already uses elsewhere -- scoped to the two named slugs rather than [subject = Bvm], since the Notification's own reasoning is specifically about a memorial's link to a movable solemnity of the Lord, not a blanket Marian precedence. Golden pin updated: test_rite_of.ml's 2011-06-13 tie now pins Mary, Mother of the Church as observed (was Anthony of Padua, labelled "known arbitrary"), with the header rewritten to state the outcome now rests on the Notification, not a coin-flip. The litcal oracle allow-list gains L10: litcal's own grade vocabulary has no representation for a 95 sub-rank (everything Memoria_obligatoria reads "Memorial"), a representational gap in litcal, not a computational disagreement -- the identity axis is untouched and needed no new entry.
* fix(of): dispatch Holy Family's Normae n.35(a) fallback (W2)Lukasz Kasprzak2026-08-261-58/+78
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | temporal_of.ml's temporal only ever reached holy_family's own correct 26-31 December / 30 December fallback logic through sunday_slug, which returns None immediately for a non-Sunday date. In a year 25 December is itself a Sunday (26-31 December then holding no Sunday of its own), the feast vanished entirely and fell through to an ordinary Christmas ferial slug -- confirmed on 2022, 2033, 2039, 2044, 2050 (and roughly 1583..9999 domain-wide, one year in seven). temporal's dispatch now consults holy_family directly, independent of weekday, between the sunday_slug and christmas_feria_slug branches, carrying the identical identity the Sunday case already builds (subject Lord, holy_family_names, rank Festum). holy_family and anchors were already correct and needed no change. Added a direct example-based test for the fallback across five affected years plus a control for the unaffected Sunday case, and a domain-wide property (Holy Family is observed in every liturgical year 1583-9999) folded into both the 200-sample QCheck run and the exhaustive sweep -- the property that would have caught this directly. Un-pinned the now-fixed behaviour everywhere it was recorded as known-wrong: test_rite_of.ml's own 1583 pin (rewritten to assert the fix), test_validate_of.ml's own independent exhaustive-sweep counter and landmark-year filter (found via make check, not the initial survey), and data/of/expected-divergences-litcal.sexp's L2/L3 allow-list entries against the litcal oracle (closed and removed, with a dedicated regression test replacing the allow-list's own silence).
* fix(of): anticipate St Joseph onto 18 March per Normae n. 56(f)Lukasz Kasprzak2026-08-261-53/+57
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | W1: when 19 March (St Joseph) falls on Palm Sunday, colitur sent him forward to Easter+9 instead of anticipating the solemnity backward to 18 March, the one rule in the whole Normae transfer machinery that names an earlier date. Live in 16 of 1583-2100 (1595, 1606, 1617, 1690, 1758, 1769, 1780, 1815, 1826, 1837, 1967, 1978, 1989, 2062, 2073, 2084). Blocked on a kernel contract: Rite.t.transfer_target required its result be strictly later than the impeded date, an obligation argued purely from the EF's RG 96. Traced against Calendar's actual placement pass rather than assumed unsafe: the round loop re-resolves the whole year fresh every round, and its two safety nets (~start/~stop; the round-count guard) both test the target's own value with no comparison against origin, so a bounded backward jump converges the same way a bounded forward one does. The one requirement that stays load-bearing is target <> origin: Precedence.resolve never deduplicates by slug, so a candidate returning its own argument unchanged would collide with itself in the same round's contest. Relaxed the obligation accordingly (rite.mli) and added the fourth transfer_target branch in Precedence_of, ahead of the existing three (Precedence_of.transfer_target, Rule 0). calendar.ml needed no logic change, only two comments that asserted "every genuine transfer moves forward" as a blanket fact. Unpinned the two tests that asserted the old wrong (forward) behaviour and replaced them with assertions of the correct one, plus a new direct unit test of the backward branch across two independent years. EF output is untouched: data/ef/ and lib/rites/rite_ef/ carry no diff, and colitur day/readings for 2026, 1583 and 9999 are byte-identical against a build of the prior commit. OF's own 2005-2050 window carries none of the 16 affected years and shows zero unexpected diffs; the full 1583-9999 domain still reaches a fixed point under the exhaustive sweep.
* feat(of-lectionary): hand-author the Christmas Day Mass, close the gapLukasz Kasprzak2026-08-261-20/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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(of): pin the Mary Mother of the Church / Anthony of Padua tieLukasz Kasprzak2026-08-261-1/+59
| | | | | | | | | | | | | | | | | | | data/of/amendments/006-mary-mother-of-the-church.sexp's own header documented, at length, that Easter+50 can land on 13 June and tie with Anthony of Padua at Tabula III.10 (both universal Memoria_obligatoria) -- the ledger's remedy (F-MEMORIAL-TIE) asked to document the lacuna AND pin the current behaviour so it cannot drift silently. Only the documentation half was done. Add test_mater_ecclesiae_anthony_tie_2011_known_arbitrary, in the same style as the Joseph/Palm Sunday and Holy Family fallback pins already in this file, but labelled KNOWN ARBITRARY rather than KNOWN WRONG: no rubric decides this collision (the 2018 decree is silent on it, and Normae n. 14's third clause resolves only the ad-libitum/ad-libitum case), so colitur's Slug.compare tie-break is a generic kernel fallback, not a colitur-invented rule. Asserts the 2011 Easter/offset arithmetic by hand, the current observed slug, and that the loser is recorded in `omitted` rather than silently dropped.
* fix(of-temporal): make anchors agree with temporal on the Nativity VigilLukasz Kasprzak2026-08-261-1/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Temporal_of.named correctly guards the Nativity Vigil: when 24 December falls on a Sunday it is the Fourth Sunday of Advent (Tabula I.2 outranks I.3), not the Vigil, and named returns None so temporal's dispatch falls through to the ordinary Sunday slug. anchors, however, still listed ("of-nativity-vigil", 24 December) unconditionally -- a regression from the earlier R8 fix, which added the guard to named but never updated anchors to match. In 2028 and 2034, anchors claimed the Vigil where temporal actually returns "of-advent-sunday-4". anchors exists precisely as an independent restatement whose stated purpose is to catch an accidental single-site drift rather than leaving it invisible -- it caught exactly this drift, just later than it should have, only once Validate.run was wired for the OF rite for the first time (nothing before that compared anchors against named/temporal, so the two were free to disagree unnoticed). Fixed by restating named's own guard exactly: the Vigil entry is omitted on a Sunday year rather than replaced, since the Fourth Sunday of Advent is an ordinary generic week-numbered Sunday, not one of the named days anchors exists to restate. Audited every other anchors entry the same way, across the full 1584-9997 domain (test_temporal_of.ml's own exhaustive sweep, run under COLITUR_EXHAUSTIVE_SWEEP=1): no further drift found. The sweep does surface one already-known, already-pinned mismatch -- the "of-holy-family" entry, in any year 26-31 December holds no Sunday (Normae n.35(a)'s own 30-December fallback) -- but it is a different shape, not a second instance of this bug: there anchors computes the right date and it is temporal that fails to reach it, which test_rite_of.ml already found, pinned and deferred as out of scope. Corrected that file's own stale comment, which still described the now-fixed Vigil disagreement as an open gap. New tests in test_temporal_of.ml cover both a Sunday-24-December year (2028, 2034) and a non-Sunday one, checking every anchors entry against temporal directly, plus a positive assertion that the Vigil entry is correctly present or absent depending on the year.
* feat(of): assemble Rite_of.context and wire --rite of into the CLILukasz Kasprzak2026-08-261-0/+340
Task 5 of Phases 3-5 (the payoff task): bundles Tasks 1-4's separately built pieces (Temporal_of, Precedence_of, Rubrics_of, Lectionary_of) into a (Vocab_of.season, Vocab_of.rank) Colitur_kernel.Rite.t, and wires colitur day/readings --rite of <year> into the CLI. Default stays ef; every pre-existing invocation is byte-identical (asserted directly in test/cli.t and against a real v1.0.0 build for three years, plus git diff --stat v1.0.0..HEAD over lib/rites/rite_ef/, lib/kernel/, data/ef/ is empty). No kernel change was needed, confirming the spec's central claim. season_runs needed real thought rather than the brief's own suggested Vocab_of.seasons: Temporal_of.season's own 'first run'/'second run' comments confirm Ordinary Time is genuinely interrupted by Lent and Easter over one liturgical year, so the expected run-length-compressed sequence names it twice, six runs over five seasons -- exactly the case Rite.t.season_runs's own doc comment already names as its illustration for why this field is rite-supplied rather than derived. easter/fixed_key are as specified, each carrying its own citation (Gregorian computus; the 2002 Missal's one bissextilis occurrence is a leap-year table entry, not a kalends-doubling rule, so fixed_key is identity). Follows rite_ef.ml's template and its lectionary-parameter lesson exactly: lectionary is caller-supplied, not closed over. test/test_rite_of.ml resolves the real assembled rite (calendar-2002 .sexp + all 13 amendment overlays + lectionary.sexp) through Calendar and Validate.run, the same discipline test_validate.ml/test_rite_ef.ml already apply to EF. This is the first time rite_of has been checked this way, and it surfaced two new, real, cited gaps outside this task's own scope to fix: Temporal_of never reaches Normae n.35(a)'s 30-December Holy Family fallback in a year with no Sunday in 26-31 December (first hit 1583, the domain floor), and Temporal_of.anchors disagrees with temporal on 24 December when that date is itself a Sunday (Advent IV outranks the Vigil, first hit 2006). Both pinned as known-wrong, not fixed, the same treatment the brief's own pre-known St Joseph/Palm Sunday gap (Normae n.56(f)) gets, pinned on 2062. A third gap was found in data/of/lectionary.sexp's own coverage (audited against one civil year only, so the other weekday-cycle letter is unaudited and at least one pairing is asymmetric on shipped data) -- that file is excluded from this task, so the wide 2005-2050 sweep checks structural invariants only and leaves the citation-chain checks to the small, individually-audited landmark-year set. make check (COLITUR_EXHAUSTIVE_SWEEP=1): exit 0, 867 tests, ~316s.