diff options
| -rw-r--r-- | lib/rites/rite_ef/temporal_ef.ml | 180 | ||||
| -rw-r--r-- | test/test_temporal_ef.ml | 131 |
2 files changed, 301 insertions, 10 deletions
diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml index 4b59ff4..2188ce3 100644 --- a/lib/rites/rite_ef/temporal_ef.ml +++ b/lib/rites/rite_ef/temporal_ef.ml @@ -580,6 +580,143 @@ let ferial_rank d s = let weekday_word d = Date.weekday_to_string (Date.weekday d) +(* RG 91 entry 27, "Officium sanctae Mariae in sabbato" -- the votive Office of + the BVM on Saturday. Caput IX of the Rubricae Generales, both photographic + scans and the electronic transcription, word for word (docs/research/ + rules-register.md §4/§6; no scan-vs-transcription conflict -- RG 78/79 are + General Rubrics prose, not the Mass-propers body text the transcription is + documented elsewhere as missing almost all of): + + "78. In sabbatis, in quibus occurrit Officium de feria IV classis, fit + de sancta Maria in sabbato. + 79. Officium sanctae Mariae in sabbato incipit a Matutino et explicit + post Nonam." + + -- "On Saturdays on which the Office of a IV-class feria occurs, [the + Office] is made of Holy Mary on Saturday [instead]. The Office of Holy + Mary on Saturday begins at Matins and ends after None." RG 78's own + protasis is exactly "otherwise unoccupied IV-class Saturday": WHICH + Saturdays qualify is not a season list to hand-maintain -- it is simply + every Saturday whose temporal candidate would otherwise be + {!Vocab_ef.Class4} (RG 91 entry 28's own unqualified ferial catch-all, + [ferial_rank] above), from ANY season that ferial rank reaches + (Septuagesima, Time after Epiphany, Time after Pentecost, and ordinary + Paschaltide Saturdays outside the privileged Easter/Pentecost octaves, and + the Christmastide ferial stretches [christmastide_feria_slug] builds -- + Advent/Lent/Passiontide Saturdays are already Class2/Class3, higher than + IV class, so RG 78's protasis never fires there, and Ember/Rogation/ + privileged-octave Saturdays are excluded the same way). Nothing else is + needed to decide "otherwise unoccupied": {!Precedence_ef.band}'s own + entry-27 branch already reads [rank = Class4 && weekday = Sat] on the + TEMPORAL candidate unconditionally (312 966 times across the domain, per + the task report) and only ever WINS the day (becomes [observed]) when + nothing of better table position contests it -- exactly RG 78's own + condition, decided by the existing occurrence machinery, not re-derived + here. When a real sanctoral feast DOES win such a Saturday outright, RG + 78's protasis is false for that day (the IV-class Office never "occurs" + there to begin with), and this candidate simply loses/omits exactly as + the plain ferial candidate it replaces already did (RG 26, {!disposition} + in precedence_ef.ml) -- verified: no change to {!Precedence_ef.band}, + {!Precedence_ef.disposition} or {!Precedence_ef.admit} was needed for + this, since RANK stays {!Vocab_ef.Class4} either way and none of those + three functions reads slug/colour/name to decide who wins, what a loser's + fate is, or how many commemorations are admitted. + + Rank: IV class, RG 91's own table position, unconditional ("Dies + liturgici IV classis: 27. Officium sanctae Mariae in sabbato. 28. Feriae + IV classis." -- both scans, register §4). + + Colour: white, ALWAYS, regardless of season -- RG 120(b) (Caput XVIII, + "De coloribus paramentorum", "B) De colore albo"), both photographic + scans: "120. Adhibetur color albus in Officio et Missa de festis: ... b) + B. Mariae Virg." -- white is used in the Office and Mass of feasts ... of + the Blessed Virgin Mary. NOT RG 119 (the "de Tempore" white rule for + Christmastide/Paschaltide) or RG 127/128 (season green/violet): this + Office is never "de Tempore" for colour purposes, so it overrides + [season_colour] unconditionally, including on Septuagesima (violet) and + Time-after-Epiphany/-Pentecost (green) Saturdays -- confirmed against the + oracle (missalemeum, 1 August 2026, a Time-after-Pentecost Saturday: + white, not the season's green). The Missal's own "Missae de sancta Maria + in sabbato" section (both scans) carries no per-Mass colour override the + way some other votive Masses do elsewhere in the same scan ("In hac Missa + adhibetur color albus") -- it needs none, RG 120(b) already settles it + unconditionally for every occurrence. + + Name: "Officium sanctae Mariae in sabbato" -- RG 91 entry 27's own table + title AND RG 79's own heading, both photographic scans and the electronic + transcription, word for word. Latin only, not English -- the same + zero-circularity discipline {!holy_family_sunday}/{!holy_name_names}/ + {!triduum_names} already established: an English name would mean reading + missalemeum's own title text, the oracle this axis is compared against, + to decide colitur's own "ground truth" name. + + Subject: [Bvm] -- simply true (RG 91 entry 27's own title names the BVM + directly) and currently inert for precedence purposes: neither + {!Precedence_ef.band}, {!Precedence_ef.disposition} nor + {!Precedence_ef.admit} tests [subject = Bvm] anywhere today (only [= + Lord] is ever read) -- the same "tagged anyway because it is simply true" + reasoning {!triduum_names}'s own [subject = Lord] tag already used for + the identical shape. Checked for a live interaction with the one other + [Bvm]-tagged entry this codebase's data carries + (data/ef/adjustments.sexp's `most-holy-name-of-mary`, 12 September, + Class3 Feast, not Commemoration_only): whenever 12 September falls on a + Saturday it wins outright over any Class4 candidate ({!Precedence_ef.band} + entry 24 beats entry 27 on table order alone), so this Office and that + entry can never coexist as a winner/commemorated-loser pair -- no live + RG 112(d) witness is created by this tag. + + Slug: UNCHANGED -- deliberately reuses whatever + [christmastide_feria_slug]/the generic <season>-<week>-<weekday> ferial + fallback would already have produced for this date (e.g. + "ef-septuagesima-2-saturday", "ef-time-after-pentecost-8-saturday"), not + a new bespoke key. Two independent reasons, not one: + (1) PRECEDENT: the SAME shape as the Sacred Triduum ({!triduum_names}'s + own citation above) -- "the slug deliberately STAYS the generic ... + key... identified structurally... never off the slug" -- and + {!Precedence_ef.band}'s own entry-27 branch already reads [rank = Class4 + && weekday = Sat] on the temporal candidate structurally, never its slug, + so nothing needs a bespoke key to find this office. + (2) A bespoke season-independent slug would have been actively WRONG: + [Colitur_kernel.Validate]'s own ["slugs"] check (validate.ml) asserts + every OBSERVED slug is sighted at most once per liturgical year, verified + with ZERO exceptions across the whole 1583-9999 domain before this task + (register/CLAUDE.md's own carried item 4) -- a single uniform + "ef-bvm-saturday" would be sighted 4-9 times in most liturgical years + (every otherwise-unoccupied Saturday), breaking that invariant for real, + not merely in theory (confirmed by writing it that way first: [Validate]'s + own landmark-years test failed immediately, 1583 alone sighting it on 5 + dates). Reusing the season-keyed ferial slug keeps the invariant intact + with no change to [Validate] at all, since season+week+weekday is already + guaranteed unique within a liturgical year by construction. It also + dovetails with the FIVE numbered "Missae de sancta Maria in sabbato" the + Missal's own Common of the BVM prints immediately afterward ("MISSAE DE + S. MARIA IN SABBATO QUAE DICI ETIAM POSSUNT ALIIS DIEBUS UT VOTIVAE DE B. + MARIA VIRGINE, IUXTA RUBRICAS VEL, EX INDULTO, PRO TEMPORUM DIVERSITATE": + I "Tempore Adventus", II "A Nativitate Domini usque ad Purificationem", + III "A die 3 Februarii usque ad feriam IV Hebdomadae sanctae", IV + "Tempore Paschali", V "A festo Ss. Trinitatis usque ad sabbatum ante + dominicam I Adventus" -- both photographic scans, word for word, matching + the oracle's own "V Mass of the B. V. M." title on a Time-after-Pentecost + Saturday): a season-keyed slug leaves room for a future lectionary + bootstrap (Plan 4) to map each one onto its corresponding numbered Mass's + propers, the same way [sunday_slug]'s own season-keyed Sunday slugs + already anchor the ordinary lectionary. RG 309(a)'s own words -- "Missae + quae pro sancta Maria in sabbato, IUXTA TEMPORUM DIVERSITATEM, in Missali + assignantur" -- confirm this is a MASS-TEXT selection detail (which + PROPERS are said), not an OFFICE-identity one; colitur computes no + citations/readings at all yet ([citations] is empty on every day) -- + deliberately not modelled further here, recorded per the task report. The + Missal's own five-season partition for the Mass numbering does not even + align with this rite's own RG 71-77 season boundaries (its own "III" + spans Septuagesima, all of Lent and most of Passiontide as ONE bracket), + one further reason not to try to derive a "Mass number" field from + [Vocab_ef.season] here. *) +let bvm_saturday_names = + Colitur_kernel.Names.of_list + [ (Colitur_kernel.Lang.of_string_exn "la", "Officium sanctae Mariae in sabbato") ] + +let is_bvm_saturday d (rank : Vocab_ef.rank) = Date.weekday d = Date.Sat && rank = Class4 + let temporal d = let y = Date.year d in let easter = Computus.gregorian_easter y in @@ -773,8 +910,22 @@ let temporal d = else ( match christmastide_feria_slug d with | Some slug -> - build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s) - ~week:(week d) () + (* Every Christmastide feria this branch builds is + Class4 ([ferial_rank]'s own catch-all -- Christmastide + is never Advent/Lent/Passiontide), so + [is_bvm_saturday]'s rank test is always true here; the + weekday is the only real condition. See + [bvm_saturday_names]'s own citation above for the full + argument (rank/colour/name/subject) -- the SLUG stays + [slug], the same one this branch would otherwise have + built, per that same citation's own "Slug" paragraph + (not re-quoted at this function's two call sites). *) + if is_bvm_saturday d Class4 then + build ~subject:Colitur_kernel.Subject.Bvm ~names:bvm_saturday_names ~season:s ~slug + ~colour:Colour.White ~rank:Class4 ~week:(week d) () + else + build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s) + ~week:(week d) () | None -> (* The days between Ash Wednesday and Lent I have proper Masses and belong to no numbered week. *) @@ -784,6 +935,26 @@ let temporal d = ~slug:(Printf.sprintf "ef-lent-after-ashes-%s" (weekday_word d)) ~colour:Colour.Violet ~rank:Class3 ~week:None () else + let week_n = week d in + let slug = + Printf.sprintf "ef-%s-%d-%s" (season_slug_word s) + (Option.value week_n ~default:0) (weekday_word d) + in + if is_bvm_saturday d (ferial_rank d s) then + (* RG 78 (Caput IX, "De sancta Maria in sabbato") -- + see [bvm_saturday_names]'s own citation above for + the full argument. This is the ordinary-season + half of the two call sites: Septuagesima, Time + after Epiphany, Time after Pentecost, and + ordinary Paschaltide Saturdays outside the + privileged Easter/Pentecost octaves are exactly + the seasons [ferial_rank] gives Class4 outside + Christmastide (the other call site, above). The + SLUG stays [slug], just computed above, the same + one this branch would otherwise have built. *) + build ~subject:Colitur_kernel.Subject.Bvm ~names:bvm_saturday_names ~season:s ~slug + ~colour:Colour.White ~rank:Class4 ~week:week_n () + else let colour = (* The Pentecost octave weekdays are red, not Paschaltide's white. *) if days_between easter d >= 50 && days_between easter d <= 55 then Colour.Red @@ -817,11 +988,6 @@ let temporal d = else if days_between easter d = -3 then Colour.White else season_colour s in - let week_n = week d in - let slug = - Printf.sprintf "ef-%s-%d-%s" (season_slug_word s) - (Option.value week_n ~default:0) (weekday_word d) - in (* [triduum_names]'s own citation above: identity only, for the three days of the Sacred Triduum -- every other ferial day here stays unnamed, subject diff --git a/test/test_temporal_ef.ml b/test/test_temporal_ef.ml index 5394173..ff3cc0b 100644 --- a/test/test_temporal_ef.ml +++ b/test/test_temporal_ef.ml @@ -296,13 +296,31 @@ let test_holy_name_sunday_shape () = compared against)" None (Colitur_kernel.Names.find (office (d 2026 1 4)).Cel.names en); (* Negative controls: every OTHER day in the 2-5 January window that year - stays [subject Temporal] -- the override is scoped to exactly the one - Sunday [T.holy_name_sunday] names, not the whole window. *) + is NOT Lord -- RG 17(a)'s own override is scoped to exactly the one + Sunday [T.holy_name_sunday] names, not the whole window. 2 and 5 January + (Friday, Monday) stay plain [Temporal] ferias, as before. 3 January is a + SATURDAY -- an unrelated rubric (RG 78, "De sancta Maria in sabbato", + {!bvm_saturday_names}'s own citation in temporal_ef.ml) legitimately + retags it [Bvm], not [Temporal]: it is an otherwise-unoccupied IV-class + Saturday (Christmastide's "ef-christmas-1-*" ferial branch, [ferial_rank]'s + unconditional Class4 there), so RG 78 fires regardless of RG 17(a) being + in play the same week -- the two rubrics are independent and this is not + a collision. This is deliberately NOT folded into the [Temporal] check + above: asserting "stays Temporal" for 3 January would be WRONG once RG + 78 is built, not merely incomplete. *) List.iter (fun dd -> Alcotest.(check bool) (Printf.sprintf "2026-01-%02d: NOT Lord (not the Sunday)" dd) true - (subject_of (d 2026 1 dd) = Sub.Temporal)) + (subject_of (d 2026 1 dd) <> Sub.Lord)) [ 2; 3; 5 ]; + Alcotest.(check bool) "2026-01-02: plain Temporal feria (not a Saturday)" true + (subject_of (d 2026 1 2) = Sub.Temporal); + Alcotest.(check bool) "2026-01-05: plain Temporal feria (not a Saturday)" true + (subject_of (d 2026 1 5) = Sub.Temporal); + Alcotest.(check bool) "2026-01-03: a Saturday -- RG 78's BVM Saturday office fires here \ + independently of RG 17(a)" + true + (subject_of (d 2026 1 3) = Sub.Bvm); (* 2027: 3 January is the Sunday (`date -d 2027-01-03 +%u` = 7) -- the oracle window's own second instance of the Sunday shape. missalemeum's 2027-01-03 row independently corroborates: rank 2, white, title "Holy @@ -489,7 +507,20 @@ let test_colours () = (6 Jan) is a Tuesday, so the actual first-Sunday-after-Epiphany origin is 11 Jan -- exercising all four sub-stretches of the fix. *) let test_christmastide_feria_slugs () = + (* 26 Dec 2026 and 10 Jan 2026 are both SATURDAYS -- ef-bvm-saturday task + (RG 78, "De sancta Maria in sabbato"): every Christmastide feria + [christmastide_feria_slug] builds is unconditionally Class4 + ([ferial_rank]'s own catch-all outside Advent/Lent/Passiontide), so on a + Saturday {!Rite_ef.Temporal_ef.bvm_saturday_names}'s own override fires + here too -- but per that citation's own "Slug" paragraph, the SLUG is + deliberately left UNCHANGED (reused from this same "-0-"/"-2-" naming, + not replaced): only colour/subject/name change. So the slug assertions + below are unaffected by the fix; what is NEW is the colour/subject + override on these two specific dates, asserted alongside them. *) Alcotest.(check string) "26 Dec (Sat)" "ef-christmas-0-saturday" (slug_of (d 2026 12 26)); + Alcotest.(check string) "26 Dec (Sat): the BVM Saturday office overrides the season colour (white, RG 120(b))" + "white" (colour_of (d 2026 12 26)); + Alcotest.(check bool) "26 Dec (Sat): subject Bvm" true (subject_of (d 2026 12 26) = Sub.Bvm); Alcotest.(check string) "28 Dec (Mon)" "ef-christmas-0-monday" (slug_of (d 2026 12 28)); Alcotest.(check string) "2 Jan (Fri)" "ef-christmas-1-friday" (slug_of (d 2026 1 2)); Alcotest.(check string) "5 Jan (Mon)" "ef-christmas-1-monday" (slug_of (d 2026 1 5)); @@ -497,6 +528,7 @@ let test_christmastide_feria_slugs () = lectio's "week 1" key, precisely to avoid colliding with 12-13 Jan below. *) Alcotest.(check string) "7 Jan (Wed, before the origin)" "ef-christmas-2-wednesday" (slug_of (d 2026 1 7)); Alcotest.(check string) "10 Jan (Sat, before the origin)" "ef-christmas-2-saturday" (slug_of (d 2026 1 10)); + Alcotest.(check bool) "10 Jan (Sat): subject Bvm" true (subject_of (d 2026 1 10) = Sub.Bvm); (* 12-13 Jan are on/after the origin: genuinely week 1, lectio's key. *) Alcotest.(check string) "12 Jan (Mon, on/after the origin)" "ef-time-after-epiphany-1-monday" (slug_of (d 2026 1 12)); @@ -813,6 +845,98 @@ let test_sacred_triduum_identity () = Alcotest.(check bool) "1666-04-22 Holy Thursday: subject Lord" true (subject_of (d 1666 4 22) = Sub.Lord) +(* RG 91 entry 27 / RG 78-79 (Caput IX, "De sancta Maria in sabbato") -- + {!Rite_ef.Temporal_ef.bvm_saturday_names}'s own citation has the full + primary-source argument (both photographic scans and the electronic + transcription for RG 78/79 themselves; both photographic scans for RG + 120(b)'s colour rule and the Missal's own "Missae de sancta Maria in + sabbato" heading). This test proves it holds across every season family + [ferial_rank] can give Class4 outside a privileged run -- Christmastide, + Septuagesima, Time after Epiphany, Time after Pentecost and ordinary + Paschaltide -- and that it does NOT fire where RG 78's own protasis is + false (Advent/Lent/Passiontide Saturdays, already II/III class; Ember + Saturdays, II/I class; a non-Saturday day in the very same week). Every + date below was independently checked against `colitur day <year>`'s own + real output (data/ef/sanctoral.sexp + adjustments.sexp) before being + pinned here, exactly like test_golden.ml's own discipline -- not merely + asserted against [T.temporal]'s own predicted shape a second time. *) +let test_bvm_saturday () = + (* Septuagesima, clean (no competing sanctoral candidate that year): + 19 February 2028, Septuagesima I Saturday. Colour is the clearest + possible witness here -- Septuagesima's own season colour is violet + (RG 128(b)), so a white result can only come from RG 120(b)'s override, + never from [season_colour] agreeing by coincidence the way + Christmastide/Paschaltide do below. *) + Alcotest.(check string) "2028-02-19 (Septuagesima I Saturday): slug stays the ordinary ferial key" + "ef-septuagesima-1-saturday" (slug_of (d 2028 2 19)); + Alcotest.(check string) "2028-02-19: class-4, unconditional (RG 91's own IV-class table position)" + "class-4" (rank_of (d 2028 2 19)); + Alcotest.(check string) "2028-02-19: white overrides Septuagesima's own violet (RG 120(b), not RG 128(b))" + "white" (colour_of (d 2028 2 19)); + Alcotest.(check bool) "2028-02-19: subject Bvm" true (subject_of (d 2028 2 19) = Sub.Bvm); + Alcotest.(check (option string)) "2028-02-19: Latin name, both photographic scans and the transcription, \ + word for word" + (Some "Officium sanctae Mariae in sabbato") (name_la_of (d 2028 2 19)); + (* Time after Epiphany, clean: 16 February 2030. Season colour there is + green (RG 127), like Time after Pentecost below -- a second, + independent witness that the override is season-blind, not merely + "true for Septuagesima's violet and Time after Pentecost's green + happen to share a fix". *) + Alcotest.(check string) "2030-02-16 (Time after Epiphany V Saturday): slug stays the ordinary ferial key" + "ef-time-after-epiphany-5-saturday" (slug_of (d 2030 2 16)); + Alcotest.(check string) "2030-02-16: white overrides Time after Epiphany's own green (RG 127)" "white" + (colour_of (d 2030 2 16)); + Alcotest.(check bool) "2030-02-16: subject Bvm" true (subject_of (d 2030 2 16) = Sub.Bvm); + (* Time after Pentecost, clean: 27 June 2026. *) + Alcotest.(check string) "2026-06-27 (Time after Pentecost IV Saturday): slug stays the ordinary ferial key" + "ef-time-after-pentecost-4-saturday" (slug_of (d 2026 6 27)); + Alcotest.(check string) "2026-06-27: white overrides Time after Pentecost's own green (RG 127)" "white" + (colour_of (d 2026 6 27)); + Alcotest.(check bool) "2026-06-27: subject Bvm" true (subject_of (d 2026 6 27) = Sub.Bvm); + (* Ordinary Paschaltide, clean, outside the privileged Easter octave: 18 + April 2026. Season colour there is ALREADY white (RG 119) -- colour + alone cannot distinguish the override firing from it simply not being + needed, so subject/name are the load-bearing assertions on this one, + not colour (the SAME reasoning [test_holy_family]'s own "Christmastide + already white" gap does not arise for -- this is a genuine, deliberate + exception recorded here, not an oversight). *) + Alcotest.(check string) "2026-04-18 (Paschaltide II Saturday): slug stays the ordinary ferial key" + "ef-easter-2-saturday" (slug_of (d 2026 4 18)); + Alcotest.(check string) "2026-04-18: white (coincides with Paschaltide's own RG 119 white -- not a \ + distinguishing witness on its own)" + "white" (colour_of (d 2026 4 18)); + Alcotest.(check bool) "2026-04-18: subject Bvm (the real witness this date proves, since colour alone \ + cannot)" + true (subject_of (d 2026 4 18) = Sub.Bvm); + Alcotest.(check (option string)) "2026-04-18: Latin name present too" (Some "Officium sanctae Mariae in sabbato") + (name_la_of (d 2026 4 18)); + (* Negative controls: RG 78's own protasis ("in quibus occurrit Officium + de feria IV classis") is false for these -- each is already II or III + class, never reaching Class4 at all, so none of them is overridden. *) + Alcotest.(check string) "2026-03-14 (an ordinary Lent Saturday): stays III class, violet, Temporal" + "class-3" (rank_of (d 2026 3 14)); + Alcotest.(check string) "2026-03-14: violet, NOT overridden (RG 78 never applies -- already III class)" + "violet" (colour_of (d 2026 3 14)); + Alcotest.(check bool) "2026-03-14: subject stays Temporal" true (subject_of (d 2026 3 14) = Sub.Temporal); + Alcotest.(check string) "2026-12-12 (an ordinary Advent Saturday, before 17 Dec): stays III class" + "class-3" (rank_of (d 2026 12 12)); + Alcotest.(check bool) "2026-12-12: subject stays Temporal (not overridden)" true + (subject_of (d 2026 12 12) = Sub.Temporal); + Alcotest.(check string) "2026-02-28 (Lent Ember Saturday): stays II class, NOT overridden" "class-2" + (rank_of (d 2026 2 28)); + Alcotest.(check bool) "2026-02-28: subject stays Temporal" true (subject_of (d 2026 2 28) = Sub.Temporal); + Alcotest.(check string) "2026-09-26 (September Ember Saturday): stays II class, NOT overridden" "class-2" + (rank_of (d 2026 9 26)); + (* A non-Saturday day in the SAME week as a clean BVM Saturday stays an + ordinary ferial -- the override is exactly one weekday wide, not the + whole week. 26 June 2026 is the Friday immediately before the 27 June + Saturday pinned above. *) + Alcotest.(check string) "2026-06-26 (Friday, day before a BVM Saturday): plain ferial, not overridden" + "ef-time-after-pentecost-4-friday" (slug_of (d 2026 6 26)); + Alcotest.(check string) "2026-06-26: green, the season's own colour, unaffected" "green" + (colour_of (d 2026 6 26)); + Alcotest.(check bool) "2026-06-26: subject stays Temporal" true (subject_of (d 2026 6 26) = Sub.Temporal) + let test_totality () = (* Every day of 2026 yields an office without raising. Not a slug re-validation -- Slug.t is a private string validated on construction, @@ -848,6 +972,7 @@ let suite_extra = Alcotest.test_case "colours" `Quick test_colours; Alcotest.test_case "sacred triduum identity (RG 91 entry 2, Gap 1)" `Quick test_sacred_triduum_identity; + Alcotest.test_case "BVM Saturday office (RG 91 entry 27, RG 78-79)" `Quick test_bvm_saturday; Alcotest.test_case "christmastide feria slugs" `Quick test_christmastide_feria_slugs; Alcotest.test_case "named days carry their week" `Quick test_named_days_carry_their_week; Alcotest.test_case "totality" `Quick test_totality; |
