diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-24 16:29:23 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-24 16:29:23 +0200 |
| commit | 8a5da8756cf6b57aa36c01b71ce893f7967d3a29 (patch) | |
| tree | 10873a692400fa25ce54c67ac9fc34d46af86272 | |
| parent | 4f87cbde4ee79ac96aa7ebfed105b3a5ec02be43 (diff) | |
| parent | 73b15551804bb63ee0081005e2869d36afb54be2 (diff) | |
| download | colitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.tar.gz colitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.zip | |
merge: celebrant Mass rubrics, and four rubrical corrections
colitur now prints what a real ordo prints for the Mass: which formulary is
said and how it was reached, the Gloria, the Creed, the preface, and the
commemorations with their Low-Mass/sung distinction. colitur rubrics joins
day and readings.
Four defects were found and fixed on the way, each by an external witness
rather than by inspection: the Creed said at Requiem Masses (RG 476(f)),
the missing bissextile shift of St Matthias and St Gabriel (2 041 leap
years), Rogation Monday and Tuesday coloured violet in Paschaltide (RG
119(b)), and the ferias after the Ascension resuming the wrong Sunday's
Mass rather than the Ascension's.
Validation gained a sixth layer and then some: the preface is checked
against three independent publishers over seven witness-years (FIUV, three
LMS editions, three extraordinaryform.org editions), none of which shares
the Divinum Officium -> missalemeum -> lectio lineage the older layers all
descend from.
73 files changed, 17549 insertions, 135 deletions
@@ -100,7 +100,7 @@ overlays**. - **Data format**: **S-expressions** (`sexplib`/`ppx_sexp_conv`) — the OCaml type *is* the format, parse/print auto-derived, no hand-written parser. -## Validation (the "sure bet" pillar — 5 layers) +## Validation (the "sure bet" pillar — 6 layers) 1. **Types** — illegal states unrepresentable (closed variants for ranks/colours/ seasons; dates validated at construction; resolution total). @@ -113,11 +113,30 @@ overlays**. citations). 4. **Oracle cross-check** — vs missalemeum (EF) / litcal (OF) in lectio's `sources/`. 5. **Golden regression** — landmark + known-tricky years pinned. +6. **LMS Ordo cross-check** (`test_lms_ordo.ml`, added `celebrant-rubrics-phase1`) — + the Creed (RG 475–476), the RG 78/309(a) Saturday votive Mass's own seasonal + selection, and the reading-formulary override, each compared against a printed + Latin Mass Society Ordo for England & Wales (Peter Day-Milne, v2.21) over one + liturgical year, 2024-11-27–2025-12-31 (400 days). Genuinely a FOURTH lineage, + not a re-count of layer 4 — see the very next bullet, which this layer + supersedes for the "no independent witness" half of its own claim. -**Status: all five layers are built and green.** Layer 2 is exhaustively clean over +**Status: all six layers are built and green.** Layer 2 is exhaustively clean over all 8 417 years (`COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force`, ~50 s; the default suite samples). Layer 3 compares 16 801 days against lectio; layer 4, 730 days -against missalemeum; layer 5 pins ~30 dates. +against missalemeum; layer 5 pins ~30 dates; layer 6 compares 400 days against the +LMS Ordo, full 1:1 on the Creed axis, and found a real colitur defect on its first +run (RG 476(f), closed — see the register). + +**Layer 6's own blind spots, stated plainly rather than left implied**: it covers +ONE civil year, not the whole 2005–2050 differential window; the formulary- +override axis compares only 3 of {!Mass_formulary.source}'s 5 constructors +(`Own_slug` is excluded — a real, evidenced data-representation ambiguity in +colitur's own citations, not a gap in the Ordo, and `Votive` is covered by a +separate, dedicated seasonal-numeral check instead); and it is an England & Wales +DIOCESAN Ordo — universal-calendar days are compared, the diocesan variant on 156 +of its 400 days is not. `docs/research/ordo/PROVENANCE-lms.md` has the full +source citation, SHA-256 and characterisation record. **Know what each layer cannot see** — this is load-bearing, not a caveat: - **LAYERS 3 AND 4 ARE ONE LINEAGE, not two** (register §6.20, 2026-08-18 — @@ -132,9 +151,18 @@ against missalemeum; layer 5 pins ~30 dates. The genuinely independent witness found is the **published Ordo** (clergy- compiled, not software): it confirmed seven colitur positions including three hand-authored entries missing from the entire DO tree (Major - Litanies, the RG 110 Peter companion, St Barbara). Not wired in as a layer — - its PDF columns shift between pages and extraction is unreliable; a - structured Ordo would be the only way to add a fourth *lineage*. + Litanies, the RG 110 Peter companion, St Barbara). + *(CORRECTED, `celebrant-rubrics-phase1`, 2026-08-22: this paragraph + previously ended "Not wired in as a layer — its PDF columns shift between + pages and extraction is unreliable; a structured Ordo would be the only + way to add a fourth lineage." That is still true of THIS SPECIFIC Ordo + (the one that confirmed the three entries above) — it remains unwired, + for that exact reason. But its own closing prediction has since been + fulfilled by a DIFFERENT, later-acquired published Ordo: the Latin Mass + Society's, structurally parseable (`tools/extract_lms_ordo.ml`), now + wired in as layer 6 — see the validation section above. Two distinct + printed Ordos, not one: this file's own historical entries about the + first should not be read as describing the second.)* - **THE CHAIN IS NOW BROKEN AT ONE LINK, AND LAYER 4 IS THE OUTLIER** (2026-08-18). lectio has ADOPTED eight corrections colitur argued from the Missal — `ubaldus`/`didacus` promoted to III-class feasts, both August @@ -354,7 +382,7 @@ Litanies, Barbara and Rogation Wednesday. `Overlay.merge` is last-writer-wins, so a local calendar can still override a universal entry by naming its slug. Refused on `easter`/`temporal` (they read no sanctoral data) rather than silently ignored. **An overlay is applied, not validated** -— the five layers assert things about the SHIPPED data and cannot vouch for +— the six layers assert things about the SHIPPED data and cannot vouch for a user file; a directive matching nothing warns on stderr and continues, a file that fails to load is fatal. Worked example, both a fixed and a movable local feast: `test/fixtures/overlay-example-diocesan.sexp`. @@ -145,7 +145,7 @@ v0.9.0, EF only. **569 tests**, of which the property suite runs against every year in 1583-9999 rather than a sample — that is how confidence extends past the ~2050 horizon of any reference to check against. -Five validation layers, each blind to something the others catch: +Six validation layers, each blind to something the others catch: | | | |---|---| @@ -153,12 +153,18 @@ Five validation layers, each blind to something the others catch: | properties | invariants over all 8 417 years (QCheck) | | differential | 16 801 days compared against the sibling `lectio` engine | | oracle | three captured years compared against missalemeum | +| ordo | one liturgical year compared against a printed Latin Mass Society Ordo | | golden | 11 pinned template outputs | Knowing what each layer *cannot* see is load-bearing here: the differential and -the oracle share one data lineage (Divinum Officium → missalemeum → lectio → -colitur), so an error inherited by both is invisible to either. That is written -up in full in `docs/` rather than left implied. +the missalemeum oracle share one data lineage (Divinum Officium → missalemeum +→ lectio → colitur), so an error inherited by both is invisible to either. The +Ordo layer is a genuinely separate lineage — a clergy-compiled book, never +passed through that chain — but has its own blind spots: it covers one civil +year, only three of the reading-formulary's five sources (a documented +data-representation ambiguity excludes the rest), and England & Wales +diocesan propers are excluded from every comparison, universal-calendar days +only. That is written up in full in `docs/` rather than left implied. **Chants are deliberately absent.** Psalm, Tract, Alleluia and Sequence have no source and no oracle, so `Validate` rejects any citation part outside diff --git a/bin/main.ml b/bin/main.ml index 18fd2f5..b5d8d98 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -362,6 +362,91 @@ let readings_line ~lang ~sigla (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.r (part_ref Colitur_kernel.Citation.Gospel) name_suffix +(* Task 4 (celebrant-rubrics-phase1): the day's own Mass formulary -- which + slug's Mass is actually said, and how that was decided + ({!Colitur_kernel.Mass_formulary.source}: proper/own/preceding-sunday/ + common/votive). + + A SEPARATE command from `day` and `readings`, for the identical mechanical + reason CLAUDE.md already records for `readings`: a formulary NAME (not + built yet, but the reason this row is shaped the way it is) contains + spaces ("Mass of the 9th Sunday after Pentecost"), and `day`'s own row is + fixed-width space-separated with a variable-length "+slug" tail, so + appending anything with its own internal whitespace there would leave the + row unsplittable by field number. + + TAB-separated rather than reusing [readings_line]'s " | " -- deliberately + a THIRD delimiter, not a second use of the existing one -- because a + later column on this row (the resolved formulary name, once one exists) + can itself contain a literal "|" inside punctuation a citation never + does, and because TAB is what stays unambiguous once a field may carry + both spaces and arbitrary punctuation. This is also why `rubrics` does + not (yet) take --lang/--raw/--sigla-*: there is no display name or + citation on this row for any of them to resolve. + + [d.formulary] is documented as [Some] on every day of every year for EF, + asserted by {!Colitur_kernel.Validate}'s own ["formulary"] check -- but + the type itself permits [None] (a rite with no lectionary), so this + prints "-" rather than pattern-matching partially and crashing on a + guarantee that belongs to DATA, not to the type. + + Task 5 (celebrant-rubrics-phase1): a fourth column, whether the Creed is + said (EF: RG 475-476, {!Rite_ef.Rubrics_ef.creed}) -- "true"/"false" + ([string_of_bool], not "yes"/"no" or "1"/"0": this row has no other + boolean column to be consistent with, so OCaml's own literal is the + least surprising choice for a machine-readable field). Unlike + [formulary], [d.creed] is a plain [bool] with no [option] to guard: a + rite that has not implemented the rule answers [false] outright, so + there is no third "unknown" state this column could ever need to print. + + Whole-branch review fix round: {!Colitur_kernel.Mass_formulary.t.said} + itself gained an [option] (its own citation has the full account -- + [None] exactly for [Votive], where the shipped data genuinely names no + slug for the Mass actually said). This column's own OUTPUT does not + change for that reason: when [said] is [None] it falls back to + [d.observed]'s own slug -- the SAME value this column always printed + for a [Votive] day before [said] became honest, and it is a value this + function already has in scope regardless of [via]. So this is not + "print a placeholder for the missing case", it is "the value was + already available from a different field, and still is". + + Task (celebrant-rubrics-phase1, Phase 2): a FIFTH column, whether the + Gloria in excelsis is said (EF: RG 431-432, {!Rite_ef.Rubrics_ef.gloria}) + -- same [string_of_bool] convention as [creed], same plain [bool] with + no [option] to guard, same reasoning throughout. + + Task (celebrant-rubrics-phase1, Phase 3): a SIXTH column, which preface + is said (EF: RG 482-499, {!Rite_ef.Rubrics_ef.preface}) -- + {!Colitur_kernel.Preface.to_string} (e.g. "common", "holy-cross"), or + "-" when [d.preface] is [None]. UNLIKE [creed]/[gloria], [preface] is a + genuine [option]: "-" here can mean either of two things ("this rite + has not implemented the rule" or "this specific day has no Mass to + preface", {!Colitur_kernel.Rite.t.preface}'s own citation) and this + column does not distinguish them, the same "-" convention [formulary]'s + own [None] case already uses two columns to the left, for the identical + reason. *) +let rubrics_line (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) + = + let said, via = + match d.Colitur_kernel.Liturgical_day.formulary with + | Some f -> + ( Colitur_kernel.Slug.to_string + (match f.Colitur_kernel.Mass_formulary.said with + | Some s -> s + | None -> d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug), + Colitur_kernel.Mass_formulary.source_to_string f.Colitur_kernel.Mass_formulary.via ) + | None -> ("-", "-") + in + let preface = + match d.Colitur_kernel.Liturgical_day.preface with + | Some p -> Colitur_kernel.Preface.to_string p + | None -> "-" + in + Printf.printf "%s\t%s\t%s\t%s\t%s\t%s\n" (D.to_iso8601 d.Colitur_kernel.Liturgical_day.date) said via + (string_of_bool d.Colitur_kernel.Liturgical_day.creed) + (string_of_bool d.Colitur_kernel.Liturgical_day.gloria) + preface + (* One civil year, Jan 1 - Dec 31, matching [temporal_report]'s own scan -- NOT one liturgical year: [Colitur_kernel.Calendar.year] resolves a single Advent-anchored liturgical year, which straddles two civil years, so a @@ -456,6 +541,7 @@ let resolved_year_report ~line ~overlays y = let day_report ~lang ~overlays y = resolved_year_report ~line:(day_line ~lang) ~overlays y let readings_report ~lang ~sigla ~overlays y = resolved_year_report ~line:(readings_line ~lang ~sigla) ~overlays y +let rubrics_report ~overlays y = resolved_year_report ~line:rubrics_line ~overlays y (* Task 8: `colitur emit` -- the five template-family emitters built in Tasks 5-7, wired to a year RANGE rather than a single year, because a @@ -1182,7 +1268,9 @@ usage: colitur temporal <year> the temporal cycle, one line per day colitur day <year> the resolved day identity, one line per day colitur readings <year> the Mass reading citations, one line per day + colitur rubrics <year> the Mass formulary said, one line per day colitur day|readings <year> [--overlay FILE ...] [--lang CODE|FILE] [--raw] + colitur rubrics <year> [--overlay FILE ...] colitur emit --format csv|json|sexp|xml|ics --from Y --to Y [--overlay FILE ...] [--dtstamp S] [--lang CODE|FILE] [--raw] render a resolved year range through one of five emitters @@ -1216,6 +1304,8 @@ output formats: 2026-04-05 sunday paschaltide 1 ef-easter-sunday class-1 white readings date slug | Epistle | Gospel [| name] 2026-12-25 ef-nativity | Heb 1:1-12 | John 1:1-14 + rubrics date, formulary slug, source, creed, gloria, preface -- TAB-separated + 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity A citation contains spaces, so readings uses " | " between its fields while day stays space-separated; that is why they are separate commands rather @@ -1228,6 +1318,25 @@ output formats: for that particular day, the trailing field is simply absent, which is what makes --raw byte-identical to this program's pre-naming output. + rubrics prints which Mass is actually said and how that was decided + (source: proper/own/preceding-sunday/common/votive) -- not always the + day's own: a weekday with no proper resumes the preceding Sunday's, a + saint with no proper says his assigned Common -- followed by whether the + Creed is said (RG 475-476), whether the Gloria in excelsis is said + (RG 431-432, deferring to the Breviary's own Te Deum rule, nn. 237-238, + for RG 431(a)), and which preface is said (RG 482-499) -- Creed/Gloria + both "true"/"false", OCaml's own literal, not "yes"/"no" or "1"/"0"; + preface one of nativity/epiphany/lent/holy-cross/easter/ascension/ + sacred-heart/christ-the-king/holy-spirit/trinity/bvm/st-joseph/apostles/ + common/requiem, or "-" when this engine resolves no Mass at all that day + (Good Friday). TAB-separated rather than space or " | ": a resolved + formulary NAME is a column a later version may add, and it can carry + both spaces and punctuation a citation never does, which rules out + either alternative already in use above. --overlay is accepted (the + observed celebration it changes decides the formulary, the Creed, the + Gloria and the preface); --lang/--raw/--sigla-* are refused -- this row + resolves no display name and no citation for any of them to affect. + emit one schema (season, week, slug, rank, colour, subject, names, citations, commemorations), rendered five ways: csv (RFC 4180, one header for the whole run), json, sexp, xml (schema/colitur- @@ -1240,9 +1349,10 @@ overlays: the shipped universal one, never instead of it, so local feasts add to it rather than replacing it. Later files win over earlier ones, and over the universal calendar, when they name the same - slug. Accepted on `day`, `readings`, `emit`, `table`, `render` and - `publish` -- `easter` and `temporal` read no sanctoral data, so - the flag is refused there rather than silently ignored. + slug. Accepted on `day`, `readings`, `rubrics`, `emit`, `table`, + `render` and `publish` -- `easter` and `temporal` read no + sanctoral data, so the flag is refused there rather than + silently ignored. An overlay is applied, NOT validated: colitur's test layers assert things about the shipped calendar and cannot vouch for a file you @@ -1435,10 +1545,10 @@ let print_help () = let usage () = prerr_endline "colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur \ - readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template \ - FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | \ - colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | \ - colitur new-overlay (try: colitur --help)"; + readings <year> | colitur rubrics <year> | colitur emit --format FMT --from Y --to Y | colitur \ + table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish \ + --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show \ + | colitur check FILE | colitur new-overlay (try: colitur --help)"; exit 2 let with_year ys f = @@ -2269,6 +2379,19 @@ let () = ~sigla_tradition_flag:sigla_tradition ~config in with_year ys (readings_report ~lang:lang_t ~sigla ~overlays:effective_overlays) + | [ "rubrics"; ys ] -> + (* --overlay accepted, same reasoning as `readings`: an overlay can + change which celebration is observed, hence which Mass formulary + is said. --lang/--raw/--sigla-* are refused, unlike `readings` + -- this row resolves no display name and no citation for any of + them to affect. *) + reject_emit "rubrics"; + reject_table "rubrics"; + reject_publish "rubrics"; + reject_lang "rubrics"; + reject_lang_sub "rubrics"; + reject_sigla "rubrics"; + with_year ys (rubrics_report ~overlays:effective_overlays) | [ "emit" ] -> ( reject_table "emit"; reject_publish "emit"; diff --git a/data/ef/expected-divergences-efdotorg.sexp b/data/ef/expected-divergences-efdotorg.sexp new file mode 100644 index 0000000..addecfe --- /dev/null +++ b/data/ef/expected-divergences-efdotorg.sexp @@ -0,0 +1,207 @@ +; data/ef/expected-divergences-efdotorg.sexp -- efdotorg-preface task +; (2026-08-24-colitur-celebrant-rubrics-phase1)'s cited allow-list for the +; extraordinaryform.org Ordo preface comparison (test/test_efdotorg_ordo.ml), +; three editions (2024-2025, 2025-2026, 2026-2027), 1091 day-rows total. +; +; A SEPARATE file from data/ef/expected-divergences.sexp (lectio), +; data/ef/expected-divergences-missalemeum.sexp (missalemeum/Divinum- +; Officium lineage), data/ef/expected-divergences-lms.sexp (Latin Mass +; Society, England & Wales, Peter Day-Milne) and +; data/ef/expected-divergences-fiuv.sexp (FIUV, universal, Joseph Shaw): +; this is a FIFTH lineage, a third distinct publisher/compiler. +; +; Two things resolved BEFORE any divergence below was adjudicated, per the +; task's own "characterise first" discipline -- neither is an allow-list +; entry, because neither is a disagreement: +; - "Advent" is not a static mapping (RG 494(b) grants Trinity on every +; Advent SUNDAY, RG 498 the residual Common on every Advent FERIA) -- +; see tools/extract_efdotorg_ordo.py's own header, finding 3, and +; test_efdotorg_ordo.ml's own [classify_praef]. Zero mismatches. +; - The "Christ the King" classifier gap in parse_ordo.py's own hardcoded +; PREFACES set is RECOVERED in the fixture generator (finding 2), not +; allow-listed. +; +; Of 1088 comparable rows (1091 minus Good Friday x3 minus the one source +; gap, 2027-03-03), 11 diverge, all found ONLY after building +; tools/extract_efdotorg_ordo.py's own Rule A (finding 6: "Saturday of Our +; Lady", whenever listed, IS the office, checked exhaustively across all +; 38 instances in the corpus) -- without Rule A the apparent divergence +; count was far higher (dominated by the BVM-Saturday-Office population), +; which is why Rule A belongs in the generator, not the allow-list: it is +; a general, well-evidenced STRUCTURAL rule, not a per-date adjudication. +; +; The 11 residual rows resolve to exactly SEVEN root causes, E1-E7 below. + +; E1 -- colitur correct. "Our Lady of Mt. Carmel" (16 July) is +; `Commemoration_only` status in data/ef/sanctoral.sexp (confirmed +; directly: `grep our-lady-of-mt-carmel data/ef/sanctoral.sexp`, and +; already cited elsewhere in this codebase -- +; lib/rites/rite_ef/precedence_ef.ml's own `marian_slugs`/RG112(d) +; citation names it explicitly), so it can NEVER be the day's own +; OBSERVED office in colitur's model -- only ever a commemoration. This +; source nonetheless lists it as a standalone Mass option (the same +; "priest's menu, not office order" convention +; .superpowers/ordo-class-report.md already established for the votive +; Requiem population), with the day's real office (an ordinary feria/ +; resumed Sunday) listed alongside, its own `comms` field naming Mt +; Carmel as what IT commemorates -- exactly matching colitur's own +; `+our-lady-of-mt-carmel` commemoration on all three dates. Fires once +; per edition, unchanged: 2025-07-16, 2026-07-16, 2027-07-16. +((id E1) (citation "RG91 table (Commemoration_only has no table row); data/ef/sanctoral.sexp") + (verdict colitur) + (note "Our Lady of Mt Carmel (16 July) is Commemoration_only-status data, never the observed office; the corpus lists it as an optional votive Mass regardless. Fires 2025-07-16, 2026-07-16, 2027-07-16 (one row per edition).") + (expected_rows 1)) + + ; E2 -- colitur correct, the SAME shape as E1. "Our Lady of Ransom" (24 + ; September) is also `Commemoration_only` status + ; (data/ef/sanctoral.sexp), and CLAUDE.md's own record already notes it + ; "forces the September Ember Saturday every time, by construction" -- + ; confirmed live here: the true office on every instance checked (2025, + ; 2027) is the September Ember day itself (Ember Wednesday/Friday), with + ; Ransom correctly reduced to ITS OWN commemoration -- matching colitur + ; exactly and producing NO divergence those two years. Only 2026-09-24 + ; diverges, because that entry happens to be listed first in the + ; option list with an empty comms field of its own while the true + ; office (the Ember Saturday) is a separate, later entry -- the same + ; "named votive Mass listed ahead of the real office" shape as E1, just + ; without a Saturday-of-Our-Lady-style structural marker to catch it + ; generically. + ((id E2) (citation "RG91 table (Commemoration_only has no table row); data/ef/sanctoral.sexp; September Ember Saturday, RG26") + (verdict colitur) + (note "Our Lady of Ransom (24 September) is Commemoration_only-status data; the September Ember Saturday always wins the day outright. Fires once, 2026-09-24 (2025 and 2027's own 24 September already match colitur without needing this entry -- the Ember day is listed first there).") + (expected_rows 1)) + + + ; CORRECTED 2026-08-24 (coordinator): this entry reasoned correctly and + ; then recommended the opposite. It concludes, rightly, that the feast was + ; "never added to the GENERAL calendar" -- and then proposes it as a + ; candidate for CLAUDE.md's list of sanctoral entries MISSING from + ; colitur's universal data. Those cannot both be true, and acting on the + ; recommendation would be a REGRESSION: adding a particular-calendar feast + ; to the universal core is precisely what binding decision 2 forbids + ; ("any community's proper is an overlay, never core"). + ; + ; The Missal settles it from the primary source rather than from general + ; knowledge of the 1830 apparition. BOTH feasts named in E3 and E4 appear + ; in the Missal under its own heading "Missae pro aliquibus locis" -- + ; Masses FOR SOME PLACES: + ; docs/research/scan1.txt:52019, 52077, 52129 + ; "Missae pro aliquibus locis (B. M. V. Immaculatae a sacro Numismate)" + ; docs/research/scan1.txt:48793 + ; "Missae pro aliquibus locis (S. Ioannis Ap. et Ev. ante Portam Latinam)" + ; This is the Missal's OWN classification, and it is the same structural + ; test the register already relies on for universality: the calendarium + ; carries no "pro aliquibus locis" marker in its own lines, while the + ; wider Missal carries the marker elsewhere for exactly this class of + ; feast. + ; + ; So E3 and E4 are NOT sanctoral gaps and are NOT candidates for any + ; missing-entry list. They are particular-calendar feasts that colitur + ; correctly excludes from the universal core, and that belong in an + ; overlay -- the shape data/ef/examples/poland.ini and benedictine.ini + ; already demonstrate. The ordos carry them because those ordos serve + ; communities that keep them. Verdict [colitur] is unchanged and now rests + ; on the Missal's own words. + + ; E3 -- colitur correct (a genuine sanctoral DATA GAP, not a rule bug). + ; "Our Lady of the Miraculous Medal" (27 November) does not appear + ; anywhere in data/ef/sanctoral.sexp (`grep -i medal` / `grep -i + ; miraculous`: zero hits) -- CROSS-CONFIRMED independently by BOTH + ; already-validated witnesses on the identical civil date: the FIUV + ; Ordo (test/fixtures/fiuv-ordo-2025-2026.sexp, 2025-11-27: plain + ; "IV cl." feria, "comm.") and the LMS Ordo (both the 2023-2024 and + ; 2024-2025 editions, 2024-11-27/2025-11-27: "Mass of 24th & Last + ; Sunday After Pentecost", "Common Pr") show no such feast at all. Not a + ; feast of the UNIVERSAL 1962 General Roman Calendar (the Miraculous + ; Medal apparition, 1830, is a devotional/particular-calendar + ; commemoration in some places, never added to the GENERAL calendar) -- + ; worth flagging alongside CLAUDE.md's own existing list of missing + ; sanctoral entries (Agnes secundo, Boniface 14 May, Evaristus, + ; Theodore) as a FIFTH candidate, but NOT fixed here: out of this task's + ; own scope (preface-comparison wiring, not sanctoral completeness), and + ; unlike those four, this one is independently corroborated as + ; genuinely absent from the UNIVERSAL calendar, not merely missing from + ; colitur's own bootstrap. Fires 2025-11-27, 2026-11-27 (one row per + ; edition where it recurs; 2027-11-27 does not reach this entry at all). + ((id E3) (citation "data/ef/sanctoral.sexp (no entry); cross-confirmed absent in both the FIUV and LMS Ordos on the same civil date") + (verdict colitur) + (note "Our Lady of the Miraculous Medal (27 November) is genuinely absent from the universal 1962 calendar colitur models -- not merely a colitur bootstrap gap. Fires 2025-11-27, 2026-11-27.") + (expected_rows 1)) + + ; E4 -- colitur correct (a second genuine sanctoral DATA GAP). "St. John + ; before the Latin Gate" (6 May) is likewise absent from + ; data/ef/sanctoral.sexp entirely -- CROSS-CONFIRMED by the LMS Ordo on + ; the identical civil date in TWO separate editions + ; (test/fixtures/lms-ordo-2023-2024.sexp, 2024-05-06, and + ; lms-ordo-2024-2025.sexp, 2025-05-06): both show only "Mass of Nth + ; Sunday after Easter", "Pr of Easter" -- matching colitur's own answer + ; exactly, with no trace of this feast. A genuine SIXTH candidate for + ; CLAUDE.md's known-missing-sanctoral-entries list, not fixed here for + ; the same out-of-scope reason as E3. Fires 2025-05-06, 2026-05-06; + ; 2027-05-06 does not diverge (that date is a Saturday, and Rule A's own + ; "Saturday of Our Lady" preference resolves it correctly without ever + ; needing to know this feast is missing). + ((id E4) (citation "data/ef/sanctoral.sexp (no entry); cross-confirmed absent in the LMS Ordo (2024-05-06 and 2025-05-06) on the same civil date") + (verdict colitur) + (note "St John before the Latin Gate (6 May) is genuinely absent from the universal 1962 calendar colitur models. Fires 2025-05-06, 2026-05-06 (2027-05-06 is a Saturday and is resolved by Rule A instead).") + (expected_rows 1)) + + ; E5 -- colitur correct, extraordinaryform.org is the OUTLIER. St + ; Michael's Dedication (29 September) has no dedicated preface among RG + ; 484-497's fourteen, so RG 482's chain falls through to RG 498's Common + ; -- and this is DOUBLY corroborated already, in + ; lib/rites/rite_ef/rubrics_ef.ml's own [preface] header: the FIUV Ordo + ; reads "comm. vel de Angelis" and the LMS Ordo reads "Pr of the Angels + ; or Common Pr" for this exact feast ("of the Angels" being one of the + ; several non-RG-482 "extra" preface names both those sources are + ; already documented to carry, alongside the genuine Common answer). + ; extraordinaryform.org's bare "Holy Trinity" is a single, uncorroborated + ; reading against two independent, already-validated witnesses that both + ; agree with colitur. Fires once, 2025-09-29 (the only occurrence in + ; this corpus where 29 September is NOT itself a Sunday reaching RG + ; 494(b) by a different route -- see E6 for that shape). + ((id E5) (citation "RG482/RG498; lib/rites/rite_ef/rubrics_ef.ml's own [preface], corroborated by both the FIUV and LMS Ordos on this exact feast") + (verdict colitur) + (note "St Michael's Dedication (29 September 2025) has no dedicated preface; colitur's Common answer is independently confirmed by both the FIUV and LMS Ordos (\"... or Common Pr\"/\"comm. vel ...\"). extraordinaryform.org's bare \"Holy Trinity\" is single-witnessed and outvoted.") + (expected_rows 1)) + + ; E6 -- colitur correct, extraordinaryform.org is the OUTLIER, the SAME + ; shape as E5 but for RG 494(b)'s own Sunday grant rather than RG 498. + ; All Saints falls on a Sunday in 2026 (confirmed: the corpus's own + ; entry carries `comms: ["Twenty-third Sunday after Pentecost"]`, + ; matching colitur's own `+ef-time-after-pentecost-sunday-23`), so RG + ; 494(b) ("in omnibus dominicis II classis... praefatio de Ss.ma + ; Trinitate") grants the TRINITY preface -- independently confirmed by + ; the FIUV Ordo on the SAME civil date (test/fixtures/fiuv-ordo-2025- + ; 2026.sexp, 2026-11-01: "Trinit. vel de Omnibus Sanctis et Patronis.", + ; Trinity again being the genuine RG-482 answer and "of All Saints and + ; Patrons" the same kind of non-RG-482 extra E5 already documents). + ; extraordinaryform.org's bare "Common" is single-witnessed here too. + ; Fires once, 2026-11-01 (the only Sunday occurrence of All Saints this + ; corpus's own window covers). + ((id E6) (citation "RG494(b); test/fixtures/fiuv-ordo-2025-2026.sexp, 2026-11-01 (\"Trinit. vel de Omnibus Sanctis...\")") + (verdict colitur) + (note "All Saints falls on a Sunday in 2026, so RG494(b) grants the Trinity preface -- independently confirmed by the FIUV Ordo on the same date. extraordinaryform.org's bare \"Common\" is single-witnessed and outvoted.") + (expected_rows 1)) + + ; E7 -- a single-row SOURCE DATA INCONSISTENCY, not a rule question. + ; 2025-11-29 is a "Saturday of Our Lady" day like the other 37 in this + ; corpus (Rule A correctly selects it as the office, matching colitur's + ; own BVM answer on office IDENTITY), but this ONE row's own `preface` + ; field reads "Common" where every other "Saturday of Our Lady" entry + ; in the whole corpus reads "BVM" (checked directly: 37 of 38 read + ; "BVM", this is the sole exception) -- an isolated compiler slip in the + ; source, not a pattern. + ((id E7) (citation "internal corpus consistency check: 37 of 38 \"Saturday of Our Lady\" entries read \"BVM\"; this is the sole exception") + (verdict colitur) + (note "2025-11-29's own \"Saturday of Our Lady\" entry reads \"Common\" where every other instance in the corpus (37 of 38) reads \"BVM\" -- an isolated source labelling slip, not a rule disagreement.") + (expected_rows 1)) + +; Per-edition agreement, reported separately, never merged (each row count +; is 364 total minus that edition's own no-praef coverage bucket -- Good +; Friday plus, for 2026-2027 only, the known 2027-03-03 source gap): +; 2024-2025: 358/363 (E1 x1, E3 x1, E4 x1, E5 x1, E7 x1) +; 2025-2026: 358/363 (E1 x1, E2 x1, E3 x1, E4 x1, E6 x1) +; 2026-2027: 361/362 (E1 x1) +; Full account: .superpowers/sdd/2026-08-21-colitur-celebrant-rubrics- +; phase1/efdotorg-preface-report.md. diff --git a/data/ef/expected-divergences-fiuv.sexp b/data/ef/expected-divergences-fiuv.sexp new file mode 100644 index 0000000..c8f1e21 --- /dev/null +++ b/data/ef/expected-divergences-fiuv.sexp @@ -0,0 +1,226 @@ +; data/ef/expected-divergences-fiuv.sexp -- Witnesses task +; (2026-08-22-colitur-celebrant-rubrics-phase1)'s cited allow-list for the +; FIUV Ordo comparison (test/test_fiuv_ordo.ml), fixture window +; 2025-11-27..2026-12-31. +; +; A SEPARATE file from data/ef/expected-divergences-lms.sexp (the LMS +; allow-list, also third-party but England & Wales diocesan and single- +; compiler across its three editions), data/ef/expected-divergences.sexp +; (the lectio allow-list) and data/ef/expected-divergences-missalemeum.sexp +; (the missalemeum/Divinum-Officium-lineage allow-list): the FIUV Ordo is +; a FOURTH, independent lineage -- universal, not diocesan, compiled by a +; different person (Joseph Shaw) than the LMS editions (Peter Day-Milne). +; +; [verdict] names which side this task's own primary-source research +; backs, the SAME convention every other allow-list file in this project +; uses: not always "colitur". +; +; The Creed comparison (Task 6/Witnesses task) found no unexplained +; divergence anywhere in the 400-day window (399 comparable days, Holy +; Saturday excluded per test_creed_coverage -- see that test's own +; citation) and still does not. Phase 2 (celebrant-rubrics-phase1, +; 2026-08-22) extended this file to two more axes, Gloria and Te Deum -- +; F1 below (Gloria) and F3 (Te Deum). Both prose-only, the same L2/L5/L6 +; convention data/ef/expected-divergences-lms.sexp's own header explains: +; the real enforcement is test_fiuv_ordo.ml's own predicates and count +; assertions, not a machine-loaded [id] record. +; +; F2 and F4 (Te Deum: every vigil; the three September Ember days) were +; found, then CLOSED within the same task: tools/extract_fiuv_ordo.ml's +; own Te Deum parser recognised only ONE of the source's two negative +; phrasings ("non dicitur Te Deum"), so "sine Te Deum" -- how the source +; actually negates a Sunday's/vigil's/Ember-day's own Te Deum -- fell +; through to a bare "Te Deum" substring match and was wrongly read +; [true]. Fixed in the extractor (its own citation has the full account); +; the fixture was re-extracted from the SAME pdftotext dump; 24 of 400 +; rows flipped true->false, and colitur's own answer already matched the +; corrected value on every one of them -- no code change needed for F2/ +; F4 specifically. See test/fixtures/fiuv-ordo-2025-2026.sexp's own +; "RE-EXTRACTED" note and lib/rites/rite_ef/rubrics_ef.ml's own [te_deum] +; header (237(a)'s comment) for the fuller account, including a real, +; separate regression this same fix round found and reverted (a first +; attempt at "every Sunday says Te Deum" wrongly excluded Christ the +; King, caught by the LMS Ordo's own Gloria axis, 2024-10-27). +; +; F3 was ALSO found to be the same GENUS of extractor bug -- a different +; PARSER shape (not a negation word, an unbounded scan reading a second, +; "-VEL-"-separated printed office instead of the primary one) -- and is +; likewise now CLOSED (l5-f3-readjudication task, 2026-08-22). See F3's +; own rewritten entry below for the full account, including why the +; original finding was misadjudicated as "colitur's own gap" rather than +; recognised as an extraction defect from the start. + +; F1 -- OPEN, adjudicated FOR colitur. Fired once: 2026-04-03, Good +; Friday. +; +; The raw source (docs/research/ordo/fiuv-ordo-2025-2026.pdf, page 46, +; verified directly against the PDF, not merely the extracted fixture): +; "3. Nig in Actione liturgica usque ad 4am partem, Viol. in S. +; Communione. FERIA VI IN PASSIONE ET MORTE DOMINI, De ea, I cl. ... +; Missa pr., (omittuntur ps. Iudica me et Gloria Patri), Gloria, sine +; Credo, praef. comm." -- read LITERALLY, this states the Gloria IS said +; on Good Friday. colitur says [false] (RG 432(d)'s own {!Colour.Black} +; proxy this Mass shares with the Requiem population, {!Rite_ef.Rubrics_ +; ef.gloria}'s own header). +; +; ADJUDICATED FOR COLITUR: Good Friday's own liturgical action has no +; Mass at all in the 1955-restored Holy Week (RG 28's own "non sit dies +; liturgicus" framing for the Paschal Vigil is the closest parallel this +; project already cites, {!Rite_ef.Rubrics_ef.creed}'s own RG 28-34 +; comment) -- no Consecration, no Communion under both species by the +; celebrant, only Communion from the reserved Sacrament. That the Gloria +; is NOT said on Good Friday is among the most widely and consistently +; attested facts in the whole of 1962-rite literature (O'Connell, +; Fortescue, every published Ordo this project has touched, and this +; author's own independent knowledge of the rite) -- essentially +; undisputed. The printed "Missa pr., ..., Gloria, ..." block, structured +; identically to a REAL Mass's own rubric line elsewhere in this same +; Ordo (compare Easter Day's "Missa pr., Gloria, sequentia, Credo, praef. +; Pasch."), most plausibly describes the liturgical action's own +; STRUCTURE using the book's standard notation for bookkeeping +; consistency, or is a genuine single-word compiler error -- neither +; resolvable without contacting the compiler, out of this task's own +; scope. NOT the same failure mode as the Te Deum extractor bug above +; (F2/F4): this is the RAW pdftotext TEXT itself making the claim, not a +; downstream parsing artefact of test_fiuv_ordo.ml's own extraction -- +; re-run directly against a fresh -layout dump for this task, not merely +; trusted from the fixture. The PDF's own page IMAGE was not separately +; inspected (out of this task's own tool access), so a pdftotext-layer +; misread (a stray line from an adjacent block folded into this one) is +; not fully ruled out either -- named as a real possibility, not +; silently excluded. +; +; RESOLVED 2026-08-22 (coordinator): the page IMAGE was rendered and read +; (pdftoppm -f 48, the PDF page bearing printed folio 46). TWO findings. +; FIRST, the pdftotext layer is FAITHFUL -- the printed book really does +; carry "Missa pr., (omittuntur ps. Iudica me et Gloria Patri), Gloria, +; sine Credo, praef. comm." under FERIA VI IN PASSIONE ET MORTE DOMINI, so +; the adjacent-block-misread possibility named above is RULED OUT, not +; merely unlikely. +; SECOND, and this is what settles the adjudication rather than resting it +; on external attestation: the SAME PAGE proves the compiler knew the +; distinction and lost it here specifically. Its next entry, "4. Viol ... +; SABBATUM SANCTUM", carries NO "Missa pr." line at all -- correctly, Holy +; Saturday's own Mass being the Vigil's. The entry after it, "5. Alb DOM. +; RESURRECTIONIS", carries a full one. So on one page the book omits the +; Mass line where there is no Mass, and supplies one where there is; Good +; Friday, which likewise has none, wrongly receives one. Its own Vespers +; rubric on the same entry calls the day's rite "Actioni liturgicae +; vespertinae" -- an Action, not a Mass -- contradicting the Mass line four +; lines above it. +; The line is also WORD-FOR-WORD identical to Holy Thursday's own on the +; preceding page ("(omittuntur ps. Iudica me et Gloria Patri), Gloria, sine +; Credo"), where every word of it is correct. A copied line, not a +; considered statement. +; Verdict unchanged (colitur), now on internal evidence from the source +; itself rather than on "every other authority disagrees" -- which is the +; stronger footing, and the one this project's own standard asks for. + +; F3 -- CLOSED, MISADJUDICATED, NOW FIXED AT THE SOURCE +; (l5-f3-readjudication task, 2026-08-22). This entry previously read +; "OPEN, single-witnessed, colitur's own possible gap" -- WRONG, and not +; a Te Deum question at all: it was tools/extract_fiuv_ordo.ml's own +; [extract_te_deum] reading the WRONG PRINTED OFFICE on these six dates. +; +; THE ORIGINAL, SUPERSEDED FINDING -- preserved below verbatim, the same +; "retain the wrong reading and say why it was wrong" convention this +; file's own F1 history and data/ef/expected-divergences-lms.sexp's own +; L3/L5 already establish, NOT deleted: fires 6 times, every one of the +; six dates data/ef/expected-divergences-lms.sexp's own L5 already found +; for Gloria: 2026-03-06/07/09/12/21/24, a privileged Lenten or +; Passiontide feria (Class3, RG25) whose own office is impeded and +; carries exactly one commemoration of a Class3 saint. colitur's +; [te_deum] reads [false] (a plain ferial office by every branch +; {!Rite_ef.Rubrics_ef.te_deum} checks); FIUV reads [true] in all six -- +; confirmed directly against the raw pdftotext dump, not merely the +; fixture: e.g. 12 March, "Ll. 1a et 2a (= 2a+3a) de Scr. occ., 3a de +; festo, Te Deum." -- a genuine, unnegated "Te Deum" (neither of the two +; negative phrasings the extractor now checks for), so this is NOT the +; same failure mode F2/F4 were. (This description of what the raw text +; SAYS is still accurate -- the error was reading it from the wrong +; PLACE in the block, below, not misreading the words themselves.) +; +; CITATION [SUPERSEDED, see THE CORRECTION below]: the same +; n.302(b)/RG431(b) text L5 already cites (LT.txt -- a MISSAL rubric, not +; a Breviary one, so its literal text governs the MASS's own Gloria, not +; Matins' Te Deum) does not directly license this finding at all -- +; 237/238 (the BREVIARY rubric {!Rite_ef.Rubrics_ef.te_deum} actually +; implements) has no clause naming a commemoration as grounds for Te +; Deum. What this finding suggested, not established: the DIVINE OFFICE +; may treat a commemorated day more generously than the MASS does for +; exactly this shape (a commemorated saint's own lessons are read at +; Matins even on an impeded day, which could plausibly extend to Te Deum +; by an unwritten or unlocated convention) -- genuinely speculative, +; offered as a research lead for a follow-on task, not a citation this +; entry treated as settled. (There was no such convention: see below.) +; +; WHY NOT FIXED HERE [SUPERSEDED]: SINGLE-WITNESSED (the LMS fixtures +; never captured Te Deum at all, so there is no second Ordo to +; corroborate this shape the way the Sacred-Triduum/BVM-Saturday/vigil +; findings elsewhere in this task were cross-checked). Fixing it would +; need the SAME kernel signature widening L5 already declines for the +; identical reason (`~commemorations` on {!Colitur_kernel.Rite.t.gloria}, +; and by extension a parallel widening of [te_deum] if the two were ever +; to diverge in their own inputs) -- out of a task briefed to follow +; creed's existing seam exactly. Left OPEN for the same follow-on task L5 +; recommends. (No kernel change was ever needed -- the bug was entirely +; inside the EXTRACTOR, tools/, never inside lib/.) +; +; THE CORRECTION, in full (l5-f3-readjudication task, 2026-08-22): FIUV +; prints a "-VEL-" ("or") separator on these exact six dates, dividing +; each day's block into a PRIMARY, strict-1962 office (the feria wins, +; "sine Gloria", the saint commemorated, no "Ad Mat." lessons mentioned +; at all -- an ordinary privileged feria's Matins needs no special note) +; and a SECOND, complete alternative office under the 2020 decree Cum +; Sanctissima (the saint kept outright, "Off. ordinarium", with its OWN +; "Ad Mat. ... Te Deum" lessons). tools/extract_fiuv_ordo.ml's own +; [extract_te_deum] scanned the WHOLE block for "Ad Mat." unbounded, so +; on these six days it silently read the SECOND office's own Te Deum +; instead of the PRIMARY's -- manufacturing a same-day contradiction with +; colitur that this entry first recorded as "colitur's own possible +; gap". There was never a genuine Office-vs-Mass question, and no +; DIVINE-OFFICE convention naming a commemoration as grounds for Te +; Deum: the "unnegated Te Deum" the original finding quoted was real +; text, just read from the wrong printed office. +; +; Fixed in tools/extract_fiuv_ordo.ml's own [split_at_alt_office] (see +; its own citation, module header point 5): every field extractor now +; reads the PRIMARY office only, cut at the "-VEL-" token before any +; field extraction runs. [te_deum] now reads [None] (unresolved) on +; these six dates -- the primary office states no "Ad Mat." of its own, +; so there is nothing to positively confirm either direction from, the +; same meaning [None] already carries elsewhere in this fixture. The +; alternative office's own Te Deum is captured, not discarded, in a new +; [alt_te_deum] field (still [true] on all six -- the extraction was +; never wrong about what the SECOND office says, only about which +; office [te_deum] itself should report). +; +; VERIFIED, not merely argued: re-extracted from the SAME pdftotext dump +; (SHA-256 of the source PDF unchanged, fixture header above). Exactly 6 +; of 400 rows changed, every one Te Deum true->unresolved, on precisely +; these six dates and no others (a hard characterisation probe in +; tools/extract_fiuv_ordo.ml now asserts this population is EXACTLY +; these six, not merely observed once). Gloria, Credo, class_, title and +; praef are UNCHANGED on all 400 rows, confirmed by a direct diff of the +; fixture before and after -- those fields were already correctly +; bounded to the primary office (a Vespers-line token always intervened +; before "-VEL-" on all six real instances), so this was never a +; Gloria-axis bug, consistent with F1 and with L5's own six-date subset +; agreeing with colitur throughout. +; +; VERDICT: colitur correct; the LMS Ordo (L5) and the FIUV Ordo's own +; "-VEL-" alternative both, correctly, describe the SAME Cum-Sanctissima +; calendar colitur excludes by binding design (CLAUDE.md decision 2). +; See L5's own rewritten entry (data/ef/expected-divergences-lms.sexp) +; for the full account, including the "-VEL-" dual printing quoted there +; as the decisive evidence for BOTH entries. NOT an active +; machine-checked [id] entry, matching this file's own F1/F2/F4 +; precedent -- the real enforcement was test_fiuv_ordo.ml's own +; [is_f3_lenten_commemoration] predicate and [f3_count] assertion, BOTH +; REMOVED (same task): with the extractor fixed, this shape produces no +; mismatch at all any more (matched by the general [None]-skips- +; comparison branch every other unresolved-Te-Deum row already uses), +; so a dedicated predicate/count pin would be dead code -- the same "an +; entry that stops firing is a real change, not silently absorbed" +; discipline data/ef/expected-divergences-lms.sexp's own L1/L3 closures, +; and this file's own F2/F4 closure, already establish. diff --git a/data/ef/expected-divergences-lms.sexp b/data/ef/expected-divergences-lms.sexp new file mode 100644 index 0000000..d91028a --- /dev/null +++ b/data/ef/expected-divergences-lms.sexp @@ -0,0 +1,446 @@ +; data/ef/expected-divergences-lms.sexp -- Task 6 (2026-08-21-colitur- +; celebrant-rubrics-phase1)'s cited allow-list for the LMS Ordo comparison +; (test/test_lms_ordo.ml). Extended by the Witnesses task (2026-08-22, +; same phase) from the single 2024-2025 window (2024-11-27..2025-12-31) +; to three: 2023-2024 (2023-12-01..2024-12-31) and 2025-2026 +; (2025-11-28..2026-12-31) joined it. L3/L4 below fired only in the +; 2023-2024 window -- neither recurs in the other two, a fact worth +; keeping visible rather than merging away (see [expected_rows] on each). +; L5/L6 (Phase 2, 2026-08-22) extended the comparison to a second axis, +; Gloria (RG431-432) -- both fire in more than one window, at DIFFERENT +; counts per window, so both are prose-only (L2's own precedent), not +; machine-checked [id] records; see each for the real enforcement site. +; L5 was MISADJUDICATED as "colitur's own gap" and CORRECTED +; (l5-f3-readjudication task, 2026-08-22): see L5's own entry for the +; full account -- it is an OCCURRENCE difference (the LMS Ordo follows +; the 2020 decree Cum Sanctissima, colitur excludes it by binding +; design), not a Gloria defect. +; +; A SEPARATE file from data/ef/expected-divergences.sexp (the lectio +; allow-list) and data/ef/expected-divergences-missalemeum.sexp (the +; missalemeum/Divinum-Officium-lineage allow-list): this Ordo is a THIRD, +; independent lineage (a printed England & Wales diocesan book, ISBN +; 9781739209636, compiled directly from the 1962 Missal/1960 rubrics -- +; never passed through Divinum Officium, missalemeum or lectio), so its +; own divergences are kept apart rather than tangled into either existing +; file's own provenance. +; +; [verdict] names which side this task's own primary-source research +; backs, the SAME convention the missalemeum file's own header states: +; not always "colitur". +; +; L1 -- CLOSED, FIXED (whole-branch review finding 1, 2026-08-22): was +; 2025-11-03 (All Souls' Day, transferred from 2 November, a Sunday that +; year). colitur used to say the Creed IS said (true) on rank alone +; (475(b), Class1) where the Ordo, correctly, says it is not: "Mon 3 ALL +; SOULS' DAY I Cl B / No Gl Sequence No Cr Pr of the Dead No Blessing". +; +; This entry's own PREVIOUS text argued the divergence could not be fixed +; without a signature change, because [creed]'s inputs (temporal/observed/ +; date) have no notion of "this Mass is a Requiem". That argument was +; wrong: {!Colour.Black} is used by exactly TWO celebrations in the whole +; engine (verified by grepping every [colour Black]/[Colour.Black] site in +; lib/ and data/) -- [commemoration-of-all-souls] (data/ef/sanctoral.sexp) +; and Good Friday (temporal_ef.ml, already [false] via the RG 23(b) feria +; exclusion regardless of colour, and has no Mass at all in the +; 1955-restored Holy Week) -- so on every day this engine can construct, +; [colour = Black] if and only if the Mass is a Requiem: a citable +; implication (RG 117 assigns black to Masses of the dead) on THIS DATA, +; not a heuristic guess. [Rite_ef.Rubrics_ef.creed] now reads +; [observed.colour] as RG 476(f)'s own guard, positioned ahead of 475(b)'s +; rank branch; see rubrics_ef.ml's own header and the guard's own comment +; for the full account, and test_rubrics_ef.ml's +; [test_colour_black_population_is_exactly_two] for the test that fails +; loudly the day a third [Colour.Black] celebration is ever added, so this +; proxy cannot silently rot. +; +; BLAST RADIUS, measured (full 1583-9999 sweep of {!Colitur_kernel. +; Calendar.year}, grouped by [observed]'s own slug): 8 416 days changed +; from [true] to [false], every one [commemoration-of-all-souls] (missing +; from exactly 1 of the 8 417 domain years -- a boundary-year transfer +; effect at 1583/9999, not a third population member: see the "know what +; each layer cannot see"-style caveats elsewhere in this project for other +; instances of the same edge). A further 8 416 [Colour.Black] days are +; Good Friday ([ef-passiontide-2-friday]), unchanged by this fix (already +; [false] before it, via the earlier feria exclusion) -- confirmed +; [creed_true_among_black = 0] after the fix, over the WHOLE domain, not +; merely the fixture's own 2024-2025 window. +; +; `colitur day`/`colitur readings` are unaffected (neither prints [creed]); +; `colitur rubrics` output changes on exactly the 8 416 days above. + +; L2 -- OPEN, colitur's own gap, found while building L1's fix (whole- +; branch review finding 2, 2026-08-22). NOT an active entry in this +; file's own machine-checked sense (no code loads or cross-checks an +; "L2" id anywhere -- this file's own [allow_entry] machinery is scoped +; to the CREED axis, {!test_lms_ordo.test_creed_matches_or_is_explained} +; alone; a second, unrelated axis reusing the same id-lookup mechanism +; would let one test's "declared but never fired" check spuriously trip +; on the other axis's own entry). Recorded here as prose only, the same +; discipline this file's own closed L1 note above and +; expected-divergences.sexp's own closed C-entries already use for a +; citation worth preserving without a live parser hook -- the REAL +; enforcement is test_lms_ordo.ml's own [test_formulary_override_matches], +; which asserts this population is exactly 3 days directly. +; +; Strengthening test_lms_ordo.ml's formulary-override check from PRESENCE +; to the actual STRING (this same finding 2) surfaced a real, separate +; defect in step 3 of the reading chain ({!Rite_ef.Lectionary_ef. +; readings}), independent of the Creed axis above. Three real days in the +; fixture window -- 2025-05-30 (Friday), 2025-06-02 (Monday), 2025-06-03 +; (Tuesday), all between Ascension Thursday and the following Sunday -- +; have no proper of their own and fall to {!Colitur_kernel. +; Mass_formulary.Preceding_sunday}. colitur resumes the nearest CALENDAR +; Sunday (the "5th"/"6th Sunday after Easter", Paschaltide's own week +; 6/7), but the Missal, and the Ordo, keep saying ASCENSION'S OWN Mass +; through this stretch instead: "Mass of the Ascension" on all three +; days, never a numbered-Sunday title. Step 3 has no notion of "inside +; Ascension's own after-feast period" -- it always resumes the nearest +; preceding Sunday, numbered or not. +; +; STRUCTURAL, not a fixture artefact: the Ascension is a fixed Easter+39 +; (a Thursday inside Paschaltide week 6), so every feria whose own +; Preceding_sunday fallback would otherwise resolve to week 6 or 7 falls +; in this same stretch, every year -- this is not a coincidence of +; 2024-2025 alone, though only this fixture's own window has been checked +; against a real Ordo. +; +; NOT FIXED in this task: fixing it means teaching step 3, or the +; lectionary data, about Ascension's own after-feast period -- the same +; shape as the Christmastide "infra octavam Nativitatis" entries +; data/ef/lectionary.sexp already carries directly rather than resolving +; through this fallback -- a lectionary-data change out of a fix round's +; own scope. test/test_lms_ordo.ml's own [is_after_ascension] excludes +; this population from the general mapping (bounded ABOVE by Pentecost, +; not merely "later than Ascension" -- see its own citation, corrected +; during the Witnesses task after a first version manufactured 8 false +; failures by matching any later date in the same civil year), and +; [test_formulary_override_matches] asserts its exact size per window. +; +; CORRECTED (Witnesses task, 2026-08-22): this note previously said "exactly +; 3 real days" as though that were a universal count. Extending the +; comparison to 2023-2024 and 2025-2026 showed it is not -- the population +; depends on which OTHER days that particular year's Ascension-adjacent +; week happen to have their own competing propers (a saint, a vigil), so +; it varies year to year: 3 in 2024-2025, 1 in 2023-2024 (only 30 May 2024 +; -- Rogation Monday, 6 May 2024, is BEFORE Ascension and correctly resumes +; the ordinary "5th Sunday after Easter" instead, once the exclusion's own +; date comparison was corrected to test "after Ascension AND before +; Pentecost" rather than "week 6 or 7"), 2 in 2025-2026. All three counts +; measured directly, all showing "Mass of the Ascension", none unexplained. +; +; Domain-wide count: unmeasured -- "which feria is inside Ascension's own +; after-feast period" is not a distinct predicate anywhere in this +; codebase to sweep on. Structurally recurs every year, though the exact +; per-year count is now known to vary (1-3 in the three years measured), +; not a flat "3 days/year". + +; L3 -- CLOSED, FIXED (bissextile-shift task, 2026-08-22; NOT an active +; sexp record any more, same convention L1 above established -- removed +; from [test_allow_list_ids_are_exactly_l3_l4]'s own expected set, which +; now names L4 alone). Was OPEN, colitur's OWN genuine gap, found +; extending this suite to the 2023-2024 window (Witnesses task, +; 2026-08-22), firing once: 2024-02-24. +; +; Citation, preserved verbatim: the Missale Romanum's own CALENDARIUM +; table, February, footnote (docs/research/LT.txt:5011-5013, scan- +; corroborated docs/research/scan2.txt:3050-3058, OCR-damaged to +; "bi&sextili"/"Matthue"/"Cabrielis" but unmistakable against the +; undamaged transcription): "In anno bissextili mensis februarius est +; dierum 29, et festum S. Matthiae celebratur die 25 februarii, ac festum +; S. Gabrielis a Virgine perdolente 28 februarii, et bis dicitur sexto +; calendas, id est die 24 et die 25" -- in a leap year February has 29 +; days, St Matthias is kept on 25 February (not 24), St Gabriel of Our +; Lady of Sorrows on 28 February (not 27), and the sixth kalends of March +; is said twice. Not RG-numbered -- a calendarium footnote, not a +; Rubricae Generales paragraph. +; +; FIXED: {!Rite_ef.Temporal_ef.bissextile_fixed_key}, threaded through +; {!Colitur_kernel.Rite.t}'s new [fixed_key] field (read only by +; {!Colitur_kernel.Layer.on_date}'s FIXED half, so the kernel stays +; rite-agnostic -- a rite that supplies nothing behaves exactly as +; before). Implemented as the rubric's own MECHANISM (every fixed entry +; from 24 through 28 February shifts one civil day later in a leap year, +; 24 February itself carrying no fixed entry that year), not as "move +; these two named saints": the two are indistinguishable on shipped data +; (nothing else is fixed in that window) and diverge only for a future +; [--overlay] entry in the same range, which the mechanism reading covers +; and a two-saints special case would not. +; +; 2024-02-24/25 now MATCH the Ordo: colitur's Creed follows the same +; Matthias-vacates-24/loses-outright-on-the-Sunday-25th path the note +; below already inferred from the Ordo's own titles, and the LMS +; 2023-2024 suite's Creed and formulary-override checks are both green +; (the formulary bucket's own [expected_proper] constant dropped 182->181 +; for this window: 24 February is now the Ember Saturday's own Own_slug- +; sourced proper, not Matthias's Proper-sourced one, leaving the counted +; population rather than changing which slug's proper it is). +; +; BLAST RADIUS, MEASURED (full 1583-9999 sweep, {!Colitur_kernel.Calendar. +; year} run twice per civil year -- once with the real [fixed_key], once +; with it forced to the identity default -- every changed liturgical day +; diffed on observed slug/rank/colour/subject/commemorations; throwaway +; probe, tools/probe_bissextile.ml, run for this task and not committed, +; same precedent as tools/probe_matthias.ml above): +; +; - ALL 2 041 leap years in the domain show at least one visible +; Matthias-related change, and separately all 2 041 show at least one +; Gabriel-related change -- every leap year in 1583-9999 is touched. +; - 6 983 individual liturgical days change domain-wide, ZERO +; unclassified: exactly four shapes, all the same mechanism -- +; Matthias vacates 24 February (1 803 years) and newly appears on 25 +; February (1 811 years); Gabriel vacates 27 February (1 699 years) +; and newly appears on 28 February (1 670 years). "Vacates"/"appears" +; covers BOTH observed-outright and commemorated-only presence, not +; observed alone -- RG 111's admission cap can relegate the shifted +; saint to a bare commemoration rather than the day's own office, and +; a classifier that only watched [observed] undercounted by roughly a +; tenth on a first pass (found and corrected before this note was +; written: the OBSERVED-outright figures alone, tracked separately +; for direct comparison against this entry's own prior estimate +; below, are 1 677 for Matthias and 571 for Gabriel). +; - THIS ENTRY'S OWN PRIOR ESTIMATE, checked: "of 2 041 leap years, +; colitur observes matthias on 24 February in 1 650 of them" is +; confirmed close but not exact against the real, precisely-measured +; figure on the SAME (observed-outright-only) definition -- 1 677, a +; 2% difference consistent with the prior probe's own "roughly +; measured" caveat, not a sign either probe was wrong in kind. The +; prior estimate's own further caveat -- "some of those years may see +; identical final output either way" -- is also confirmed real but +; small: 1 677 (narrow, observed-only) vs 1 803 (broad, observed-or- +; commemorated) for the SAME 24-February-vacated population shows the +; narrow definition undercounts genuine visible impact rather than +; overcounting it, because a saint who only lost outright pre-fix +; (never observed, never commemorated, invisible either way) is +; absent from BOTH counts and was never the source of the gap between +; them. +; - Gabriel's own sibling shift, unwitnessed by this fixture's own +; 2023-2024 window (no divergence fired on either 27 or 28 February +; 2024 -- 2024's own competing office there does not expose it), is +; the identical mechanism and closes with the same fix; its own +; measured figures are recorded above for the first time, this entry +; having previously had no estimate for it at all. +; +; The differential (lectio, layer 3) gained a new cited entry for its own +; 2005-2050 window, data/ef/expected-divergences.sexp's C40 -- lectio +; implements no such shift either (confirmed directly against the +; fixture: Matthias/Gabriel sit at their PRE-shift dates in every one of +; the 11 leap years that window covers), so every leap year in it now +; diverges on the two shifted days, 21 rows total. See C40's own note for +; the row-by-row account. + +; L4 -- OPEN, adjudicated FOR colitur (a defensible primary-source reading, +; not a fix confirmed against the Ordo -- the Ordo's own contrary reading is +; also textually arguable, see below). Fired once: 2023-12-24. +((id L4) + (citation "RG 30(a) (Caput V, De Vigiliis, docs/research/LT.txt:959-961): \"vigilia Nativitatis Domini quae, IN OCCURRENTIA, locum tenet dominicae IV Adventus, de qua, proinde, NULLA FIT COMMEMORATIO\" -- the Vigil of the Nativity, when it occurs [on a Sunday], TAKES THE PLACE of the 4th Sunday of Advent, of which, accordingly, no commemoration is made -- the identical \"locum tenet ... nulla fit commemoratio\" shape RG16(a) uses for a Feast of the Lord occurring on a II-class Sunday, which colitur already implements and which RG475(a) explicitly extends the Creed to (\"in qualibet dominica, etsi eius Officium alicui festo locum cedat\").") + (verdict open) + (note "2023-12-24 (the 4th Sunday of Advent AND Christmas Eve, a genuinely rare coincidence -- roughly 1 year in 7 -- absent from both the 2024-2025 and 2025-2026 windows, where Christmas Eve falls on a Tuesday and a Wednesday respectively). colitur says the Creed IS said (true), reading [temporal]'s own weekday (Sunday) per RG475(a)'s clause, positioned ahead of the vigil-exclusion check in {!Rite_ef.Rubrics_ef.creed} -- unconditionally, the same way it already does for RG16(a)'s Feast-of-the-Lord case. The Ordo says \"No Gl No Cr\" for this date. ADJUDICATED FOR COLITUR, not merely left open by default: RG30(a)'s own \"locum tenet ... nulla fit commemoratio\" language is textually closer to RG16(a) (which colitur already treats as Creed-preserving) than to an ordinary vigil superseding a Sunday -- the Vigil does not merely WIN THE DAY, it takes the SUNDAY'S OWN IDENTITY, the same shape RG475(a) was written to reach. The COUNTER-reading is real and not dismissed here: RG475(a)'s own text says \"locum cedat ... festo\" (gives way to a FEAST), and RG35 (Caput VI) classifies feria/vigilia/festum as three distinct liturgical-day categories -- a strict textual reading could confine 475(a)'s override to FEAST-displacement only, leaving a VIGIL-displaced Sunday to fall through to the general vigil exclusion (476, via RG33's own \"a vigil is a distinct category\" reasoning already coded elsewhere in {!Rite_ef.Rubrics_ef.creed}). Left OPEN rather than closed on this task's own authority: adjudicating scripture-grade primary-source questions is out of scope for a witness-wiring task, and the two readings are both defensible. Not fixable inside this task's own no-lib-changes constraint regardless of which reading eventually wins.") + (expected_rows 1)) + +; L5 -- MISADJUDICATED, NOW CORRECTED (l5-f3-readjudication task, +; 2026-08-22). This entry previously read "OPEN, colitur's own gap" -- +; WRONG, on two independent grounds (below). It is NOT a Gloria defect +; of colitur's. It is NOT a rubric dispute at all: it is an OCCURRENCE +; difference, because the LMS Ordo is compiled to the 2020 decree Cum +; Sanctissima (its own introduction says so, docs/research/ordo/ +; PROVENANCE-lms.md) and colitur excludes that decree from its 1962 core +; by BINDING DESIGN (CLAUDE.md decision 2: "Every addition [2020 Quo +; Magis/Cum Sanctissima, any community's proper] is an overlay, never +; core"). On these 16 dates colitur and the LMS Ordo each correctly +; describe a DIFFERENT, both genuine, calendar -- they were never +; disagreeing about the same one. VERDICT: colitur correct. NOT an +; active machine-checked [id] entry -- same reasoning L2 above gives: +; the count varies window to window (5 in 2023-2024, 5 in 2024-2025, 6 +; in 2025-2026), so a single static [expected_rows] cannot check it. The +; REAL enforcement is test_lms_ordo.ml's own [is_l5_lenten_commemoration] +; predicate plus [make_suite]'s own ~expected_gloria_l5 parameter, +; asserted per window directly -- KEPT, unlike a bug-driven divergence +; that stops firing once fixed (data/ef/expected-divergences-fiuv.sexp's +; own F3, closed by this same task, is that other shape): this one is +; EXPECTED TO RECUR IN EVERY FUTURE WINDOW, because the exclusion it +; reflects is a standing design decision, not a defect to remove. +; +; THE ORIGINAL, SUPERSEDED HYPOTHESIS -- preserved below verbatim, the +; same "retain the wrong reading and say why it was wrong" convention +; L3's and F1's own history in this file already establish, NOT deleted: +; +; SHAPE, identical in all 16 instances found (5+5+6, zero exceptions): +; a privileged Lenten or Passiontide feria (Class3, violet -- RG25, +; {!Rite_ef.Temporal_ef.ferial_rank}) whose own office is impeded and +; carries EXACTLY ONE commemoration, of a Class3 saint colitur's own +; precedence engine (independently validated, layers 3-5) correctly +; reduces to a mere commemoration. colitur's [gloria] reads [false] (the +; day is a plain ferial office by every test [Rite_ef.Rubrics_ef.te_deum] +; runs -- no Sunday, no vigil, no octave, [named] = [None], [subject] = +; [Temporal]); the Ordo reads [true] in every one of the 16 instances. +; (This description of the SHAPE is still accurate -- what was wrong is +; the CONCLUSION drawn from it, below.) +; +; CITATION (docs/research/LT.txt:2359-2361, "V - De Missis festivis", +; quoted in rubrics_ef.ml's own [gloria] header in full): "302. Sensu +; autem latiore, dicuntur quoque Missae de festo: ... b) Missa de +; commemoratione in Officio diei occurrente" -- in the WIDER sense, a Mass +; "of a commemoration occurring in the day's own Office" is ALSO called a +; "Missa festiva" -- and RG431(b): "Hymnus Gloria in excelsis dicitur ... +; in Missis festivis de quibus n. 302" -- such a Mass says the Gloria. +; Textually, this appears to be EXACTLY the shape found: the day's own +; ferial Office, carrying a commemoration, is elevated to "festive" status +; for the Gloria specifically. +; +; WHY NOT FIXED HERE (the original text, which already quoted the very +; clause that defeats its own hypothesis, below, but did not follow it +; to its conclusion): n.303(b), the very next paragraph (LT.txt:2359-2367, +; same quote in rubrics_ef.ml), qualifies n.302(b)'s own Masses: "dici +; potest tantum si occurrit dies liturgicus IV classis" -- CAN ONLY BE +; SAID if the liturgical day occurring is IV class. Every instance found +; here is a Class3 PRIVILEGED FERIA (RG25), not IV class, which reads as a +; textual CONTRADICTION of the empirical finding rather than a +; confirmation of it -- unresolved without n.304 onward (not in this +; project's sources), which may clarify that 301-303 govern which Mass a +; priest may freely CHOOSE among several options in one church on one day +; (a dimension colitur does not model -- see [gloria]'s own SCOPE NOTE), +; a different question from "does THE Mass actually said, once +; determined, say the Gloria" (431(b)'s own question). Implementing this +; also has a real architectural cost this task's own instructions +; explicitly avoided: [Rite_ef.Rubrics_ef.gloria] would need a FOURTH +; parameter, the day's own {!Colitur_kernel.Liturgical_day.t.commemorations} +; -- a kernel [Rite.t.gloria] signature change, the same shape RG16(a)'s +; own [admit] fix needed a [~temporal] parameter for, and squarely out of +; a task briefed to "follow exactly how creed was wired -- same seam". +; Left OPEN, not guessed into a possibly-wrong rule. Recommended for a +; follow-on task, ideally alongside Phase 3's Preface work (RG483 governs +; a DIFFERENT, but textually adjacent, commemoration-vs-Mass-part +; question, so the two may share the same kernel signature widening). +; +; UPDATE (same original task, after wiring the FIUV Ordo's own Gloria and +; Te Deum axes, test_fiuv_ordo.ml): this paragraph previously said FIUV's +; own [gloria] axis was not compared at all. It now is, and the result +; WEAKENS this entry's own case rather than strengthening it: FIUV's own +; [gloria] is [false] on all six of these exact dates in its window -- +; AGREEING WITH COLITUR, DIRECTLY CONTRADICTING the LMS Ordo's [true] +; above. So this is not "colitur has a corroborated gap", it is "two +; independent Ordos disagree with EACH OTHER on Gloria for this shape, +; and colitur happens to agree with the universal one, not the diocesan +; one". What FIUV's OWN Te Deum axis DOES show for the identical six +; dates: [true] -- Te Deum, unlike Gloria, genuinely IS said at Matins on +; these days (data/ef/expected-divergences-fiuv.sexp's own F3), a real, +; single-witness finding that this entry's own n.302(b)/431(b) citation +; may in fact belong to the DIVINE OFFICE, not the MASS -- which would +; mean L5 itself is answering the wrong question, not merely open. +; Genuinely uncertain which of the two Mass-Gloria witnesses (LMS or +; FIUV) is right for this shape; left OPEN, not adjudicated either way, +; for a follow-on task with more primary-source access than this one had. +; (CORRECTED, l5-f3-readjudication task: F3's own "single-witness +; finding" was never a Te Deum finding at all -- it was +; tools/extract_fiuv_ordo.ml reading the WRONG PRINTED OFFICE, see below. +; There was no Office-vs-Mass question to be uncertain about.) +; +; THE CORRECTION, in full (l5-f3-readjudication task, 2026-08-22): +; +; 1. RG303(b) ALREADY DEFEATS the n.302(b)/431(b) hypothesis on its own +; terms -- the original text above quoted it but stopped short of the +; conclusion. Quoted again, in full, because it is the load-bearing +; sentence: "dici potest tantum si occurrit dies liturgicus IV +; classis" -- [a Mass "of a commemoration occurring in the day's own +; Office"] MAY BE SAID ONLY IF the liturgical day occurring is FOURTH +; class. A privileged Lenten or Passiontide feria is THIRD class +; (RG25) -- every one of these 16 instances. So n.302(b) is +; PROHIBITED, not merely inapplicable, on precisely the days this +; entry covers, and 431(b)'s own Gloria elevation, which depends on +; 302(b), can never reach them. Not "unresolved without n.304" as the +; original text guessed: 303(b) alone already closes the question, +; the wrong way for the original hypothesis. +; +; 2. THE FIUV ORDO PRINTS BOTH OPTIONS, and this is decisive on its own, +; independent of (1). All 16 LMS dates are Lenten/Passiontide +; privileged ferias; six of them fall inside the FIUV fixture's own +; 2025-2026 window (2026-03-06/07/09/12/21/24 -- the same six F3 +; named). For every one of the six, the raw FIUV source (verified +; directly against a fresh pdftotext -layout dump, not merely the +; fixture) prints TWO complete readings for the SAME civil date, +; separated by a literal "-VEL-" ("or") token. 24 March 2026, in +; full: +; +; 24. Viol Feria III post Dom. I Passionis, De ea, III cl. - Off. feriale temp. Passionis. +; Ad LAUDES ... comm. S Gabrielis Archangeli. +; Missa pr., (omittuntur ps. Iudica me et Gloria Patri), sine Gloria, comm. S +; Gabrielis Archangeli, sine Credo, praef. de Sancta Cruce or. super populum. +; I VESPERAE de seq., comm. huius diei. - Compl. de dom. +; -VEL- +; Feria III. S Gabrielis Archangeli, III cl. (Priv.) - Off. ordinarium. - Ad Mat. +; Ll. 1a et 2a (= 2a + 3a) de Scr. occ., 3a de festo, Te Deum. - Ad LAUDES comm. +; Feriae. +; Missa pr., Gloria, comm. Feriae, tractus, sine Credo, praef. de Sancta Cruce vel +; de Angelis. +; +; The FIRST option is strict 1962: the feria wins, "sine Gloria", no +; Te Deum stated, the saint merely commemorated -- EXACTLY colitur's +; own answer, field for field. The SECOND, after "-VEL-", is the +; Cum-Sanctissima-elevated option: the saint's own feast, "Off. +; ordinarium", Gloria, Te Deum, the feria commemorated instead -- +; EXACTLY the LMS Ordo's own answer. The FIUV Ordo's own title page +; states the convention this book uses throughout for exactly this +; distinction (N.B., page 1, verified directly against the PDF): +; "days of the third class to which the norms of the decree Cum +; santissima [sic] apply are marked 'III cl.' ... but days ... to +; which these norms do not apply are marked 'III cl. (Priv.)'." One +; document, compiled by a THIRD party independent of both colitur's +; own lineage and the LMS, prints BOTH engines' own answers side by +; side as two legitimate readings of two different calendars. There +; is no dispute left to adjudicate. +; +; So the Gloria and Te Deum RULES were never in dispute at all: each +; engine's answer follows correctly from its own occurrence result, on +; its own calendar. What this entry originally described as "colitur's +; own gap" is colitur correctly implementing the 1962 core it was built +; to implement, diverging from a printed book that, by its own +; introduction, deliberately implements something else. +; +; NOTE ALSO (so a reader arriving here from +; data/ef/expected-divergences-fiuv.sexp's own F3 does not draw the +; wrong conclusion from that entry's own closure): F3 did NOT +; "corroborate" or "contradict" L5 at any point in this history. Both +; were the same underlying fact read two different ways, and F3's own +; apparent Te Deum-true reading was never a real second data point in +; the first place -- it was tools/extract_fiuv_ordo.ml's own +; [extract_te_deum] silently reading the SECOND ("-VEL-") office's own +; Te Deum instead of the primary's, on exactly these six dates, closed +; by fixing the extractor (tools/extract_fiuv_ordo.ml's own +; [split_at_alt_office]), not by resolving any Office-vs-Mass question. +; See F3's own entry for the full account. + +; L6 -- OPEN, root-caused to a DIFFERENT, PRE-EXISTING bug this Gloria +; comparison merely surfaced, not a Gloria defect itself. Fired once, +; 2023-2024 only (2024-05-06, Rogation Monday) -- absent from the other +; two windows because Rogation Monday/Tuesday is impeded by a real +; sanctoral feast in both of them, so the office's own colour never +; reaches [observed] there. Same non-machine-checked-count reasoning as L5 +; above (count 1/0/0); enforced by test_lms_ordo.ml's own +; [is_l6_rogation_colour] predicate and [make_suite]'s own +; ~expected_gloria_l6 parameter. +; +; {!Rite_ef.Temporal_ef.temporal}'s own Rogation Monday/Tuesday branch +; hardcodes [~colour:Colour.Violet] with NO RG citation at all (verified +; by reading the branch directly, temporal_ef.ml, the Rogation comment +; block). The Ordo shows 2024-05-06 as \"FERIA IV Cl W †\" (white), +; borrowing \"Mass of 5th Sunday after Easter\" (matching colitur's own +; [Mass_formulary.Preceding_sunday] resolution for the identical date) -- +; consistent with RG88 (Caput X, \"De Litaniis maioribus et minoribus\"): +; \"De Litaniis minoribus nihil fit in Officio, sed tantum in Missa\" -- +; nothing changes in the OFFICE for the Minor Litanies, only the Mass +; TEXT is proper, which reads as the Office's own colour (Paschaltide, +; white) staying unchanged, the violet belonging only to the PROCESSION +; that precedes the Mass -- the same PER-ACTION colour nuance this +; project already documents as unmodelled for Palm Sunday's palm +; procession and Good Friday's Communion rite (temporal_ef.ml's own RG126/ +; RG128 citations), not a new kind of gap. +; +; NOT FIXED HERE: out of this task's own scope (Gloria/Te Deum, not the +; temporal cycle's colour assignment), and a real fix needs its own +; measured blast radius across 1583-9999 (every Rogation Monday/Tuesday +; not impeded by a stronger feast) plus a re-check against the +; differential/oracle layers, which already treat Rogation days as +; correctly violet on whatever data they compare against -- a +; cross-layer question, not a one-line patch. Recommended as a follow-on +; task's own first item.") diff --git a/data/ef/expected-divergences-missalemeum.sexp b/data/ef/expected-divergences-missalemeum.sexp index dfee36c..d1995e2 100644 --- a/data/ef/expected-divergences-missalemeum.sexp +++ b/data/ef/expected-divergences-missalemeum.sexp @@ -257,8 +257,10 @@ REVISED, ef-bvm-saturday task: 395 of the 730 days in this window used to carry REVISED AGAIN, Task 9 (branch ef-lectionary, layer-4 oracle): 352, down by 42 from 394. NOT a change to this entry's own guard (still, and only, [diffs = [ Observed_identity_unresolved ]] exactly) -- this task compared reading citations for the first time, and 42 of the former 394 rows now ALSO carry a real [First_mismatch]/[Gospel_mismatch] alongside the pre-existing observed-identity gap, so they escape this entry's own EXACT-match guard and move to the FIVE new entries below (M23 2, M24 4, M25 4, M26 30, M27 2 -- 2+4+4+30+2=42, exactly accounting for the drop, verified against the comparator's own failure output, not assumed from the arithmetic alone -- CORRECTED, fix round 1, coordinator review: this note previously miscounted them as \"six\"). -CORRECTED, fix round 1 (coordinator review): the remaining 352 were previously described as every day whose citation \"ALREADY agreed with missalemeum before this task and still does\" -- imprecise for 18 of them. Before this task the citation axis did not exist at all, so NO row's citation was ever actually checked; \"already agreed\" wrongly implies the pre-task VALUE was correct on all 352, when for 18 it was not -- it only became correct, and therefore only started agreeing, because of this task's own three fixes (Holy Name Sunday's own two dates, 2026-01-04/2027-01-03; 12 more January-window ferias across the three RG-17(a)/Holy-Family-propers-rubric families that now resolve at step 2 instead of the walkback, one full list: 2026-01-02/05/07/08/09/12, 2027-01-04/05/07/08/11/12; and Corpus Christi/Sacred Heart in both years, 2026-06-04/06-12, 2027-05-27/06-04 -- 2+12+4=18, independently re-derived against the real resolver, not merely arithmetic). The other 334 were genuinely unaffected by this task, matching both before and after (or, more precisely, would have matched on the day this axis existed either way). WIDENED 352 -> 355 (movable-date-specs follow-up, 2026-08-17): the three Trinity-week ferias that M26 shape 2(a) used to cover now agree with the oracle on their citations and differ only on observed-identity, which is this entry own generic shape -- a temporal-origin day for which colitur sets no English name. Not a new divergence: the same three days, one of their two causes removed. WIDENED 355 -> 376 (BVM Saturday Mass, 2026-08-17): the BVM Saturday days M26 shape 1 used to cover now agree with the oracle on their citations and differ only on observed identity, which is this entry's own generic shape -- the office is temporal-origin and deliberately carries no English name. Not new divergences: the same days, their citation cause removed. CORRECTED, ef-sanctoral-status: 376 -> 373. Three rows left this entry for M30 when `ubaldus` and `didacus` were promoted to Feast on the Missal's own calendarium. They were unresolved here precisely because the observed office was TEMPORAL-origin (a feria) and carries no English name; now the observed office is the SAINT, which is sanctoral-origin and does resolve, so the comparator can state a real identity mismatch instead of declining to compare. The entry shrinks because its shape stopped occurring on those days, not because the days stopped diverging.") - (expected_rows 373)) +CORRECTED, fix round 1 (coordinator review): the remaining 352 were previously described as every day whose citation \"ALREADY agreed with missalemeum before this task and still does\" -- imprecise for 18 of them. Before this task the citation axis did not exist at all, so NO row's citation was ever actually checked; \"already agreed\" wrongly implies the pre-task VALUE was correct on all 352, when for 18 it was not -- it only became correct, and therefore only started agreeing, because of this task's own three fixes (Holy Name Sunday's own two dates, 2026-01-04/2027-01-03; 12 more January-window ferias across the three RG-17(a)/Holy-Family-propers-rubric families that now resolve at step 2 instead of the walkback, one full list: 2026-01-02/05/07/08/09/12, 2027-01-04/05/07/08/11/12; and Corpus Christi/Sacred Heart in both years, 2026-06-04/06-12, 2027-05-27/06-04 -- 2+12+4=18, independently re-derived against the real resolver, not merely arithmetic). The other 334 were genuinely unaffected by this task, matching both before and after (or, more precisely, would have matched on the day this axis existed either way). WIDENED 352 -> 355 (movable-date-specs follow-up, 2026-08-17): the three Trinity-week ferias that M26 shape 2(a) used to cover now agree with the oracle on their citations and differ only on observed-identity, which is this entry own generic shape -- a temporal-origin day for which colitur sets no English name. Not a new divergence: the same three days, one of their two causes removed. WIDENED 355 -> 376 (BVM Saturday Mass, 2026-08-17): the BVM Saturday days M26 shape 1 used to cover now agree with the oracle on their citations and differ only on observed identity, which is this entry's own generic shape -- the office is temporal-origin and deliberately carries no English name. Not new divergences: the same days, their citation cause removed. CORRECTED, ef-sanctoral-status: 376 -> 373. Three rows left this entry for M30 when `ubaldus` and `didacus` were promoted to Feast on the Missal's own calendarium. They were unresolved here precisely because the observed office was TEMPORAL-origin (a feria) and carries no English name; now the observed office is the SAINT, which is sanctoral-origin and does resolve, so the comparator can state a real identity mismatch instead of declining to compare. The entry shrinks because its shape stopped occurring on those days, not because the days stopped diverging. + +NARROWED, celebrant-rubrics-phase1 Bug 2 (2026-08-22): 373 -> 370. The three Ascension-week days (2026-05-21, 2026-05-22, 2027-05-14) move to the new M31: before this fix colitur's own citation on these three days was ALSO wrong (the same Preceding_sunday walkback missalemeum still uses), so it happened to already agree with missalemeum's, leaving [Observed_identity_unresolved] as the ONLY diff -- this entry's own shape. The fix corrected colitur's side, so these three now ALSO carry a real citation mismatch and escape this entry's exact-match guard, the identical mechanism M23-M27 above already used when the citation axis was first built. See M31's own note for the full account.") + (expected_rows 370)) ((id M19) (citation "RG 110's OTHER direction: \"In Officio et Missa S. Petri semper fit commemoratio S. Pauli, ET VICISSIM\" -- the SAME rule M12 used to cite, applied here to Paul's own office commemorating Peter, not Peter's own office commemorating Paul; confirmed a third time by the calendarium's own June table, both photographic scans, word for word: \"In Commemoratione S. Pauli Ap., III classis. / Commemoratio S. Petri Ap.\"") (verdict colitur) @@ -308,3 +310,8 @@ CORRECTED, fix round 1 (coordinator review): the remaining 352 were previously d (verdict colitur) (note "ef-sanctoral-status branch. As with M29, the oracle here is not an independent witness against colitur but colitur's own discarded ancestor: colitur was bootstrapped from lectio, lectio's ini is generated from missalemeum, and missalemeum uses Divinum Officium's data files, so all three carried the same wrong status. Found by auditing ALL 290 fixed-date sanctoral entries against the calendarium; these two were the only status defects in the file. 3 rows in this window: 2026-05-16, 2026-11-13, 2027-11-13. Where colitur now observes the saint the oracle still observes the feria, so rank, observed identity and both citations differ together and the commemoration colitur used to emit is gone. Colour differs only on 13 November, the ferial green giving way to the confessor's white; 16 May is in Paschaltide and already white. Gated on the exact dates and on a subset of that named field list, so a divergence of any other shape on these days would still surface unexplained. Three rows also leave M18 (376 to 373): they were unresolved there only because the observed office was a temporal-origin feria with no English name, and the observed office is now sanctoral and resolves.") (expected_rows 3)) + ((id M31) + (citation "The Missale Romanum's own Proprium de Tempore carries an explicit marginal rubric immediately after the Ascension's own Mass propers, before \"Dominica post Ascensionem\" begins (scan1.txt:20749-20754, both scans corroborate): \"Diebus a feria VI post Ascensionem usque ad feriam VI ante vigiliam Pentecostes inclusive, dicitur Missa de festo Ascensionis\" -- on the days from the Friday after the Ascension until the Friday before the Vigil of Pentecost inclusive, the Mass OF THE FEAST OF THE ASCENSION is said. Corroborated by RG 490(b), which assigns the Ascension preface as de Tempore across the identical window. Full account in C41, data/ef/expected-divergences.sexp. Implemented in data/ef/lectionary.sexp's [ascension_week_entries] (tools/bootstrap_lectionary.ml), celebrant-rubrics-phase1 Bug 2, 2026-08-22.") + (verdict colitur) + (note "As with M29/M30, the oracle here is colitur's own discarded ancestor, not an independent witness: missalemeum -- Divinum Officium's lineage -- still walks these ferias back to the preceding Sunday's Mass, the SAME wrong answer colitur itself gave before this fix. 3 rows in this window: 2026-05-21, 2026-05-22, 2027-05-14. Of the twelve candidate civil dates the six slugs reach across 2026 and 2027 (six per year), the other nine are occupied by real sanctoral feasts both engines already agree on: 2026-05-15/18/19/20 (John Baptist de la Salle, Venantius, Peter Celestine, Bernardine of Siena) and 2027-05-07/10/11/12/13 (Stanislaus, Antoninus, Sts Philip & James, Sts Nereus/Achilleus/Domitilla/Pancras, Robert Bellarmine) -- checked directly against `colitur day`, not assumed. [Observed_identity_unresolved] fires alongside on all three: none is a sanctoral-origin day, M18's own pre-existing limit, unrelated to this cause. Gated on the exact dates and on a subset of [Observed_identity_unresolved; First_mismatch; Gospel_mismatch] (2027-05-14 also carries a real, AGREEING commemoration -- St Boniface -- on both sides, so Comm_count/Comm_presence never differ there and stay outside this diff set). Three rows leave M18 (373 to 370): they used to carry [Observed_identity_unresolved] alone (colitur's own pre-fix citation happened to already match missalemeum's, both walking back the same wrong way) and now also carry the citation mismatch this fix corrected colitur's own side of.") + (expected_rows 3)) diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index 19ff2ef..ca0d6a3 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -116,13 +116,45 @@ WHAT THIS ENTRY ALSO RESTS ON. Two things, neither of them a day-level witness. Gated on lectio's own slug being one of the three vigils this clause can reach and colitur's not being a vigil -- identity on both sides, not a diff-set shape. The Assumption's and the Ascension's vigils are absent from that list because their I-class feasts always keep their own day: 0 occurrences across the whole domain, measured rather than assumed.") (expected_rows 10)) - ; C8 -- CLOSED, REMOVED (2026-08-18): 0 of 16801 rows, was 26. lectio builds - ; Rogation Monday and Tuesday now (RG 87, Easter+36/+37, violet under - ; RG 128(d)). The Wednesday is NOT built there and deliberately so: Easter+38 - ; is the Ascension's Vigil, which wins the day, and the rubric asks for a - ; commemoration -- a channel lectio's one-office-per-day temporal function - ; does not have. That is the same reason this entry never covered the - ; Wednesday either. Citation preserved in the register. + ((id C40) + (citation "The Missale Romanum's own CALENDARIUM table, February, footnote (docs/research/LT.txt:5011-5014, scan-corroborated docs/research/scan2.txt:3050-3058): \"In anno bissextili mensis februarius est dierum 29, et festum S. Matthiae celebratur die 25 februarii, ac festum S. Gabrielis a Virgine perdolente 28 februarii, et bis dicitur sexto calendas, id est die 24 et die 25\" -- in a leap year February has 29 days, St Matthias is kept on 25 February (not 24), St Gabriel of Our Lady of Sorrows on 28 February (not 27), and the sixth kalends of March is said twice. Implemented in Rite_ef.Temporal_ef.bissextile_fixed_key, threaded through Colitur_kernel.Rite.t's new [fixed_key] field (bissextile-shift task, 2026-08-22). Not RG-numbered -- a calendarium footnote, not a Rubricae Generales paragraph.") + (verdict colitur) + (note "lectio builds no such shift at all: checked directly against the fixture, Matthias sits at 24 February and Gabriel of Our Lady of Sorrows at 27 February in EVERY ONE of the 11 leap years the 2005-2050 window covers (2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048), never moved. colitur now moves both, per the calendarium's own footnote, so every leap year in this window diverges on the two shifted civil days: colitur vacates 24/27 February (the saint moves away) and occupies 25/28 February instead (the saint newly appears there), while lectio keeps the pre-shift assignment throughout. + +19 Matthias rows + 2 Gabriel rows = 21, not the naive 11-years x 2-sides x 2-feasts = 44 ceiling: this comparator, BY DESIGN (see this file's own header), never compares commemorations -- only observed slug/rank/colour/citations -- so a side where the shifted saint has ZERO comparator-visible footprint, on both engines, whether pre- or post-shift, produces no row even though a real change happened underneath (the full-domain probe below, which DOES track commemorations, still counts it). + +MATTHIAS fires on both sides (24 vacated AND 25 occupied) in 8 of the 11 years; in the remaining 3 (2008, 2024, 2036) exactly one side is missing, and in every one of the three the missing side is a SUNDAY -- 2008-02-24 and 2036-02-24 (Matthias already loses outright to that Sunday whichever engine or shift-state is asked, so the vacated side shows no change); 2024-02-25 (the occupied side: colitur's post-shift Matthias loses outright to the 2nd Sunday of Lent, I class, with no commemoration surviving RG111's own tight cap -- Matthias's footprint there is genuinely zero, not merely uncompared). A Sunday's own observed slug is unaffected by this shift either way, so whichever side coincides with one contributes nothing comparator-visible; only the other, non-Sunday side shows the real new divergence. 2024-02-24 is L3's own original date (data/ef/expected-divergences-lms.sexp), now confirmed independently by a second, larger fixture. + +GABRIEL (Class3, weaker than Matthias's Class2/Apostle rank) fires in only 2 of the 11 years (2028 occupied, 2044 vacated) because in the other 9 his position is already dominated by a Class3-or-stronger competing office both before and after the shift, so his own presence is commemoration-only throughout -- invisible to this comparator on either side. He surfaces only where the position happens to be a plain, unprivileged Class4 feria weak enough for his own Class3 to win outright: 2028-02-28 (colitur: gabriel-of-our-lady-of-sorrows, Class3, White, beating ef-septuagesima-3-monday, Class4) and 2044-02-27 (lectio still shows gabriel there unmoved, Class3, White; colitur's post-shift 27th falls to RG78's own votive BVM-Saturday office instead, also White, hence the colour match but slug/rank/citation mismatch in that row). Every one of the 21 rows was read directly off the comparator's own failure output, not apportioned by hand. + +Diff shapes: most rows carry [Slug_f; Rank; Colour_f; First_f; Gospel_f] (the temporal office on one side and the saint's own Class2/3 proper on the other differ in rank too); a handful carry only [Slug_f; Colour_f; First_f; Gospel_f] where the competing temporal office happens to share Matthias's own Class2 (the privileged Lenten Ember Friday/Saturday, 2024 and 2040) or Gabriel's own White (a BVM Saturday, 2044-02-27's own vacated row). Season never differs on any of the 21 -- both sides stay in whichever season that Sunday-relative week already put them in, regardless of which fixed entry, if any, sits on the day. + +BLAST RADIUS, MEASURED, full 1583-9999 domain (not merely this fixture's 2005-2050 window): 6 983 liturgical days change, zero unclassified, across all 2 041 leap years in the domain -- see data/ef/expected-divergences-lms.sexp's own now-closed L3 entry for the full figures (this entry's own 21-row 2005-2050 population is the expected subset of that domain-wide count landing inside the fixture's own window: 11 leap years x up to 2 new rows each, minus the three already-explained overlaps above).") + (expected_rows 21)) + ((id C41) + (citation "The Missale Romanum's own Proprium de Tempore carries an explicit marginal rubric immediately after the Ascension's own Mass propers, before \"Dominica post Ascensionem\" begins (scan1.txt:20749-20754, both scans corroborate): \"Diebus a feria VI post Ascensionem usque ad feriam VI ante vigiliam Pentecostes inclusive, dicitur Missa de festo Ascensionis, cum Gloria et praefatione de Ascensione, sine Credo et Communicantes proprio\" -- on the days from the Friday after the Ascension until the Friday before the Vigil of Pentecost inclusive, the Mass OF THE FEAST OF THE ASCENSION is said. Corroborated by RG 490(b) (LT.txt:3981-3985), which assigns the Ascension preface \"tamquam de Tempore\" to every Mass in that same window lacking a proper preface -- consistent only if the Mass repeated is the Ascension's own, not a numbered Sunday's. Witnessed directly: the LMS Ordo prints \"Mass of the Ascension\" literally across all three fixture windows (data/ef/expected-divergences-lms.sexp's own L2, closed by this entry) on every affected day of BOTH weeks, and the FIUV Ordo's own [praef] field independently reads \"Ascensionis\" on the two analogous 2025-2026 dates its title labels by week rather than by formulary. Implemented in data/ef/lectionary.sexp's [ascension_week_entries] (tools/bootstrap_lectionary.ml), celebrant-rubrics-phase1 Bug 2, 2026-08-22.") + (verdict colitur) + (note "lectio has no equivalent rubric: it walks the six affected ferias back to the nearest preceding Sunday's Mass (5th Sunday after Easter for [ef-easter-6-friday], Dominica post Ascensionem for the five [ef-easter-7-*] weekdays), the SAME wrong answer colitur used to give before this fix. Both sides agree on slug, season (Layer A normalises colitur's [paschaltide] and lectio's [easter] as the same vocabulary), rank and colour throughout -- only the citation text differs, so every row carries [First_f; Gospel_f] alone. + +MEASURED (test_differential.ml's own [classify], 2005-2050 fixture, run directly): 95 rows, all six slugs represented, zero unclassified. Population varies year to year (0-3 of the six slugs fire per year) because most years have a real sanctoral feast occupying one or more of the six candidate civil dates -- the same reason data/ef/expected-divergences-lms.sexp's own L2 found only 1-3 affected days per its own one-year fixture windows, now confirmed at scale across the full 46-year differential window. + +The window's two Saturdays (Easter+41, Easter+48) never reach this entry: Easter+48 is the Vigil of Pentecost, a named day with its own Mass, outside the rubric's own upper bound; Easter+41 is an ordinary Class4 Saturday, so RG 78's votive Office of Our Lady on Saturday intercepts it before the lectionary lookup this entry's own fix touches is ever reached (readings' own step ordering) -- confirmed directly: no row in the 95 carries [ef-easter-6-saturday] or [ef-easter-7-saturday]. + +BLAST RADIUS, MEASURED (full 1583-9999 sweep, in-process against {!Colitur_kernel.Calendar.year}, throwaway probe, not committed): 16 350 days total, split ef-easter-6-friday 2 562, ef-easter-7-monday 2 618, ef-easter-7-tuesday 2 744, ef-easter-7-wednesday 2 776, ef-easter-7-thursday 2 781, ef-easter-7-friday 2 869 -- every one resolved via step 2's Own_slug, zero anomalies, and the window's two Saturdays confirmed to contribute zero Own_slug hits via this cause across the whole domain (RG 78's votive Office of Our Lady always intercepts first), corroborating the code-level reasoning above by direct sweep rather than inspection alone.") + (expected_rows 95)) + ((id C8) + (citation "RG 119 (Caput XVIII, \"De Colore Paramentorum\"): white is used \"in Officio et Missa de Tempore ... a Missa Vigiliae paschalis usque ad Missam vigiliae Pentecostes exclusive\" -- the de-Tempore Office and Mass are white from the Paschal Vigil Mass until the Pentecost Vigil Mass exclusive, and Rogation Monday/Tuesday (Easter+36/+37) sit inside that window. RG 128's own exhaustive four-case list for violet (Advent I-Christmas Eve; Septuagesima-Paschal Vigil; the September Ember ferias; vigils of II/III class OUTSIDE Paschaltide) never names Rogation days. RG 88 (\"de Litaniis minoribus nihil fit in Officio, sed tantum in Missa\"): the violet belongs to the Rogation MASS/procession, a distinct votive text this engine does not model, not to the day's own Office. Fixed in Rite_ef.Temporal_ef.temporal's Rogation branch, celebrant-rubrics-phase1 Bug 1, 2026-08-22 -- see that branch's own citation and data/ef/expected-divergences-lms.sexp's now-closed L6 entry, which is what surfaced it (LMS Ordo 2023-2024, 2024-05-06, \"FERIA IV Cl W\").") + (verdict colitur) + (note "REOPENED (2026-08-22, celebrant-rubrics-phase1, Bug 1 fix). Previously CLOSED, REMOVED (2026-08-18): 0 of 16801 rows, was 26, with this note, PRESERVED VERBATIM because it contains a misattribution now corrected rather than silently dropped: \"lectio builds Rogation Monday and Tuesday now (RG 87, Easter+36/+37, violet under RG 128(d)). The Wednesday is NOT built there and deliberately so: Easter+38 is the Ascension's Vigil, which wins the day, and the rubric asks for a commemoration -- a channel lectio's one-office-per-day temporal function does not have. That is the same reason this entry never covered the Wednesday either. Citation preserved in the register.\" + +THE MISATTRIBUTION: \"violet under RG 128(d)\" is wrong. RG 128(d) governs vigils of II/III class OUTSIDE Paschaltide; Rogation Monday/Tuesday are neither vigils nor outside Paschaltide. Checked against docs/research/rules-register.md (gitignored, local) while researching Bug 1: no claim of an RG 128(d) basis for Rogation colour exists there -- the misattribution was confined to this file's own closure note. It traces to Rite_ef.Temporal_ef.temporal's own Rogation branch, which hardcoded [Colour.Violet] with NO citation at all before this fix; whoever wrote this entry's closure note in 2026-08-18 apparently backfilled a plausible-looking but wrong citation for behaviour that was never actually cited in the code it described. + +WHY THIS REOPENS RATHER THAN STAYS CLOSED: the entry closed in 2026-08-18 because lectio, independently, ALSO computes these two days violet -- not because either engine's violet was ever verified against the Missal. Both engines shared the same uncited assumption, so the comparator saw agreement and the entry went to zero. Bug 1 corrected COLITUR's side to white (RG 119); lectio's own violet is unchanged (a sibling project, out of this repo, not modified here). The comparator now disagrees again, on the same 26 rows, for the OPPOSITE reason: previously colitur was wrong and lectio was wrong the same way; now colitur is right and lectio still carries the old, uncited assumption forward -- consistent with CLAUDE.md's own \"colitur vs missalemeum\" base-rate note for a different lineage, applied here to lectio directly: a fresh divergence is not presumptively colitur's fault once colitur has just been corrected FROM the shared error. + +MEASURED (test_differential.ml's own [classify], 2005-2050 fixture, DEBUGC8 probe run and reverted): exactly 26 rows, all with diffs=[Colour_f] alone -- season and slug already agree (lectio's own [easter]/colitur's [paschaltide] season labels are Layer A vocabulary synonyms, not a diff), and on every row lectio=violet, colitur=white. Dates: 2005-05-03, 2006-05-22/23, 2007-05-14, 2011-05-30, 2012-05-14, 2013-05-06, 2016-05-03, 2017-05-22/23, 2018-05-08, 2022-05-23/24, 2024-05-06, 2027-05-03, 2028-05-22/23, 2029-05-08, 2032-05-03, 2033-05-23/24, 2040-05-08, 2044-05-23/24, 2047-05-21, 2049-05-24. Fewer than the 2-per-year x 23-year x ~2 ceiling because a competing sanctoral feast impedes the Rogation office outright in some years on one or both of the two days (unchanged by this fix, gated on colitur's own [rogation-monday]/[rogation-tuesday] slug in [layer_c_reason] the same as before). The Wednesday remains absent from this entry for the same reason the pre-2026-08-18 and post-2026-08-18 notes both already gave: Easter+38 is the Ascension Vigil (RG 91 entry 21), which outranks the Rogation Wednesday commemoration outright on colitur's side, and lectio has no Rogation-Wednesday concept at all to compare against regardless. + +Gated on [(String.equal c.slug \"ef-rogation-monday\" || String.equal c.slug \"ef-rogation-tuesday\") && subset diffs [ Season; Slug_f; Colour_f ]] in [layer_c_reason] -- unchanged code, present since before this entry's 2026-08-18 closure and never removed; only the sexp record was removed when the count hit zero, per this file's own \"closed = 0 rows, not code deleted\" convention.") + (expected_rows 26)) ; C14 -- CLOSED, REMOVED (2026-08-18): 0 of 16801 rows, was 3. lectio has ; adopted RG 96(a)/97/98. Its transferIfImpededEF resolved each impeded ; I-class feast independently, so in 2008, 2035 and 2046 St Joseph and the diff --git a/data/ef/lectionary.sexp b/data/ef/lectionary.sexp index a83e12e..e34622d 100644 --- a/data/ef/lectionary.sexp +++ b/data/ef/lectionary.sexp @@ -10,7 +10,7 @@ ; ; Source: ../lectio/internal/caldata/tridentine-lectionary.ini ; SHA-256: ccd6640e8c2ae4d260e62c55cfe2b3ea14ab996e8e5a82cc1b9a37bc65ac8591 -; 153 entries (119 ini sections translated/widened into colitur's own +; 159 entries (119 ini sections translated/widened into colitur's own ; Temporal_ef vocabulary via [colitur_keys]; 1 hand-authored from a ; second source file [vigil_entries]; 6 hand-authored directly from ; the Missal [holy_week_entries]; 1 hand-authored directly from the @@ -134,9 +134,27 @@ (ef-easter-5-saturday (((part First) (reference "Ecclus 24:14-16")) ((part Gospel) (reference "John 19:25-27")))) + (ef-easter-6-friday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) (ef-easter-6-saturday (((part First) (reference "Ecclus 24:14-16")) ((part Gospel) (reference "John 19:25-27")))) + (ef-easter-7-friday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) + (ef-easter-7-monday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) + (ef-easter-7-thursday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) + (ef-easter-7-tuesday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) + (ef-easter-7-wednesday + (((part First) (reference "Acts 1:1-11")) + ((part Gospel) (reference "Mark 16:14-20")))) (ef-easter-8-monday (((part First) (reference "Acts 10:34, 42-48")) ((part Gospel) (reference "John 3:16-21")))) diff --git a/lib/kernel/calendar.ml b/lib/kernel/calendar.ml index 98e9032..a1309f9 100644 --- a/lib/kernel/calendar.ml +++ b/lib/kernel/calendar.ml @@ -79,7 +79,7 @@ let resolve_with_injected ?(suppressed = no_suppression) (rite : ('s, 'r) Rite.t { Precedence.cel = temporal.Temporal.office; origin = Precedence.Temporal } in let natural = - Layer.on_date idx date + Layer.on_date ~fixed_key:rite.Rite.fixed_key idx date |> List.map (fun (e : 'r Layer.entry) -> { Precedence.cel = e.Layer.cel; origin = Precedence.Sanctoral }) in @@ -339,7 +339,7 @@ let rg33_suppressed (rite : ('s, 'r) Rite.t) (idx : 'r Layer.index) Array.iter (fun date -> let candidates = - Layer.on_date idx date + Layer.on_date ~fixed_key:rite.Rite.fixed_key idx date |> List.map (fun (e : 'r Layer.entry) -> { Precedence.cel = e.Layer.cel; origin = Precedence.Sanctoral }) in @@ -529,7 +529,8 @@ let build_day (rite : ('s, 'r) Rite.t) (idx : 'r Layer.index) | None -> [] | Some slugs -> let on_date = - Layer.on_date idx date |> List.map (fun (e : 'r Layer.entry) -> e.Layer.cel) + Layer.on_date ~fixed_key:rite.Rite.fixed_key idx date + |> List.map (fun (e : 'r Layer.entry) -> e.Layer.cel) in let temporal_office = temporal.Temporal.office in (temporal_office :: (on_date @ List.map (fun c -> c.Precedence.cel) arrived)) @@ -543,6 +544,19 @@ let build_day (rite : ('s, 'r) Rite.t) (idx : 'r Layer.index) |> List.map (fun c -> (c.Precedence.cel, reason_for c))) @ rg33_omitted in + let formulary, citations = + rite.Rite.readings ~observed:resolution.Precedence.observed.Precedence.cel ~temporal ~date + ~temporal_at:rite.Rite.temporal + in + let creed = + rite.Rite.creed ~temporal ~observed:resolution.Precedence.observed.Precedence.cel ~date + in + let gloria = + rite.Rite.gloria ~temporal ~observed:resolution.Precedence.observed.Precedence.cel ~date + in + let preface = + rite.Rite.preface ~temporal ~observed:resolution.Precedence.observed.Precedence.cel ~date + in { Liturgical_day.date; rite = rite.Rite.id; @@ -553,9 +567,11 @@ let build_day (rite : ('s, 'r) Rite.t) (idx : 'r Layer.index) transferred_in; transferred_out; omitted; - citations = - rite.Rite.readings ~observed:resolution.Precedence.observed.Precedence.cel ~temporal ~date - ~temporal_at:rite.Rite.temporal; + citations; + formulary; + creed; + gloria; + preface; } let year (rite : ('s, 'r) Rite.t) (layer : 'r Layer.t) (y : int) : diff --git a/lib/kernel/date.mli b/lib/kernel/date.mli index 2f632c8..0e86d54 100644 --- a/lib/kernel/date.mli +++ b/lib/kernel/date.mli @@ -14,6 +14,13 @@ val month : t -> int val day : t -> int val weekday : t -> weekday +(** Proleptic Gregorian leap-year test: divisible by 4, except a century year + not divisible by 400. The same rule {!make}/{!days_in_month} already use + internally to admit 29 February -- exposed so a rite can key its own + calendar-reckoning rules (e.g. a kalends-doubling convention) off the + identical, single-sourced definition rather than re-deriving it. *) +val is_leap : int -> bool + (** [to_rata]/[of_rata] expose the underlying day-count (days since 1970-01-01); [of_rata] and [add_days] are unbounded total arithmetic (they may denote a year outside 1583..9999 — only [make] enforces the domain). *) diff --git a/lib/kernel/layer.ml b/lib/kernel/layer.ml index f069546..2a072f0 100644 --- a/lib/kernel/layer.ml +++ b/lib/kernel/layer.ml @@ -73,8 +73,12 @@ let index t ~easter ~years = Hashtbl.iter (fun k v -> Hashtbl.replace movable k (canonical v)) movable; { fixed; movable } -let on_date idx date = - let f = try Hashtbl.find idx.fixed (Date.month date, Date.day date) with Not_found -> [] in +let on_date ?(fixed_key = fun d -> Some (Date.month d, Date.day d)) idx date = + let f = + match fixed_key date with + | None -> [] + | Some k -> ( try Hashtbl.find idx.fixed k with Not_found -> []) + in let m = try Hashtbl.find idx.movable (Date.to_rata date) with Not_found -> [] in match m with [] -> f | _ -> canonical (f @ m) diff --git a/lib/kernel/layer.mli b/lib/kernel/layer.mli index ab6e56b..a71e113 100644 --- a/lib/kernel/layer.mli +++ b/lib/kernel/layer.mli @@ -36,8 +36,17 @@ type 'r index val index : 'r t -> easter:(int -> Date.t) -> years:int list -> 'r index (** Entries falling on [date], fixed and movable together, in the layer's - canonical slug order. *) -val on_date : 'r index -> Date.t -> 'r entry list + canonical slug order. + + [fixed_key] answers "which (month, day) does the FIXED half look up for + this civil date", defaulting to the identity [Some (Date.month date, + Date.day date)] -- exactly today's behaviour, for a caller that supplies + nothing. A rite's own kalends-reckoning convention (see {!Rite.t}'s + [fixed_key] field) is threaded through here rather than applied to + [date] itself, so it touches ONLY the fixed table: the MOVABLE half + (keyed by rata die, via {!Date_spec.Easter_offset}/{!Date_spec. + Nth_weekday}) always uses [date] unchanged. *) +val on_date : ?fixed_key:(Date.t -> (int * int) option) -> 'r index -> Date.t -> 'r entry list (** Loads a layer from a sexp file. Parse and validation failures come back as [Error], never as an exception. *) diff --git a/lib/kernel/liturgical_day.ml b/lib/kernel/liturgical_day.ml index bbb52b8..c3ecb37 100644 --- a/lib/kernel/liturgical_day.ml +++ b/lib/kernel/liturgical_day.ml @@ -23,5 +23,11 @@ type ('s, 'r) t = { (** with the reason, never silent -- Task 12's no-celebration-lost invariant reads this *) citations : Citation.t list; (** always empty until Plan 4 *) + formulary : Mass_formulary.t option; + (** which Mass the day says, and how that was decided; [None] only for + a rite with no lectionary -- see {!Mass_formulary} *) + creed : bool; (** whether the Creed is said at this day's Mass; see {!Rite.t.creed} *) + gloria : bool; (** whether the Gloria in excelsis is said; see {!Rite.t.gloria} *) + preface : Preface.t option; (** which preface is said; see {!Rite.t.preface} *) } [@@deriving sexp] diff --git a/lib/kernel/liturgical_day.mli b/lib/kernel/liturgical_day.mli index f0ea3d9..643097b 100644 --- a/lib/kernel/liturgical_day.mli +++ b/lib/kernel/liturgical_day.mli @@ -8,6 +8,16 @@ type ('s, 'r) t = { places for them to disagree *) observed : 'r Celebration.t; commemorations : ('r Celebration.t * Precedence.privilege) list; + (** The LOW MASS admitted set (RG 111(b)/(c)/(d) -- {!Precedence.rules.admit}'s + own wider caps). Not named [low_mass_commemorations]: this field + predates the sung/low distinction and every existing reader + ([emit], the differential/oracle layers, {!Record}) already reads + it under this name, so renaming it would be a needless breaking + change for a doc clarification alone. The SUNG-Mass equivalent + (RG 111(a): at most one commemoration, and it must be privileged) + is {!Precedence.sung_mass_commemorations}, a pure derivation over + this same list -- see its own citation for why it is a function, + not a second stored field. *) transferred_in : 'r Celebration.t option; (** arrived here from an impeded day *) transferred_out : ('r Celebration.t * Date.t) list; @@ -28,5 +38,25 @@ type ('s, 'r) t = { ["citations"] / ["citations-unresolved"] checks. (This said "always empty until Plan 4" until Task 10; the lectionary landed before Plan 4 did, and the comment outlived its truth.) *) + formulary : Mass_formulary.t option; + (** Which Mass this day says, and how that was decided -- see + {!Mass_formulary}. [None] only for a rite with no lectionary; for + EF it is [Some] on every day of every year 1583..9999, asserted by + {!Validate}. *) + creed : bool; + (** Whether the Creed is said at this day's Mass -- {!Rite.t.creed}, + EF: RG 475-476. A decision, not an [option]: [false] for a rite + that has not implemented the rule, same as [creed] itself. *) + gloria : bool; + (** Whether the Gloria in excelsis is said at this day's Mass -- + {!Rite.t.gloria}, EF: RG 431-432. Same seam as [creed] in every + respect. *) + preface : Preface.t option; + (** Which preface is said at this day's Mass -- {!Rite.t.preface}, + EF: RG 482-499. Same seam as [creed]/[gloria], but [option], not + a bare {!Preface.t}: see {!Rite.t.preface}'s own citation for why + -- [None] both for a rite that has not implemented the rule and + for a real day this engine resolves that has no Mass at all + (Good Friday). *) } [@@deriving sexp] diff --git a/lib/kernel/mass_formulary.ml b/lib/kernel/mass_formulary.ml new file mode 100644 index 0000000..60f9f1c --- /dev/null +++ b/lib/kernel/mass_formulary.ml @@ -0,0 +1,11 @@ +open Sexplib0.Sexp_conv + +type source = Proper | Own_slug | Preceding_sunday | Common | Votive [@@deriving sexp] +type t = { said : Slug.t option; via : source } [@@deriving sexp] + +let source_to_string = function + | Proper -> "proper" + | Own_slug -> "own" + | Preceding_sunday -> "preceding-sunday" + | Common -> "common" + | Votive -> "votive" diff --git a/lib/kernel/mass_formulary.mli b/lib/kernel/mass_formulary.mli new file mode 100644 index 0000000..b990e69 --- /dev/null +++ b/lib/kernel/mass_formulary.mli @@ -0,0 +1,57 @@ +(** Which Mass a day actually says, and how that was decided. + + A day does not always say its own Mass. A weekday with no proper of its own + resumes the preceding Sunday's; a saint with no proper says a Common. The + resolution already happens inside a rite's {!Rite.readings} -- this type is + what makes the answer visible instead of discarding it once the citations + have been extracted. An ordo prints it as "Mass of the 9th Sunday after + Pentecost". + + Rite-agnostic by construction: it names a slug and a provenance, and + carries no rank, season or rubric vocabulary of any rite. *) + +type source = + | Proper (** the observed celebration's own citations *) + | Own_slug (** the lectionary's entry for the day's own slug *) + | Preceding_sunday (** a weekday with no proper resumes the preceding Sunday *) + | Common (** a saint's assigned Common *) + | Votive + (** a Mass said IN PLACE of the day's own office's Mass, the office + itself being kept unchanged -- RG 309(a): "in Ecclesia universa, + Missae quae pro sancta Maria in sabbato, iuxta temporum + diversitatem, in Missali assignantur", corroborated by RG 431(e)'s + own classification of that Mass as "Missa votiva IV classis ... + de B. Maria Virg." The office/Mass split this constructor exists + to name is general (any rite may say a votive Mass on a day whose + OFFICE is not itself votive), even though EF's only witness today + is the RG 78/309(a) Saturday Mass of Our Lady. *) +[@@deriving sexp] + +type t = { said : Slug.t option; via : source } [@@deriving sexp] + +(** The slug whose CITATIONS were actually used to build the day's + readings, when the shipped data can name one. + + [Some] for four of the five sources: {!Proper} and {!Own_slug} each + carry the day's own slug; {!Preceding_sunday} carries that Sunday's + TEMPORAL slug; {!Common} carries the Common's own id. + + [None] for {!Votive}, and ONLY for {!Votive} (whole-branch review fix + round, celebrant-rubrics-phase1): RG 309(a)'s five seasonal "Missae de + sancta Maria in sabbato" carry no slug of their own anywhere in the + shipped data -- their citations come from a season-keyed function + ({!Rite_ef.Lectionary_ef.bvm_saturday_citations}), never from a + [Lectionary.find] against any slug, so there is genuinely no slug this + field could honestly report. An earlier version of this type set + [said] to the day's own OFFICE slug for {!Votive} too (RG 78's Office + of Our Lady, kept unchanged under the votive Mass) -- readable at the + call site as "this is the slug whose Mass is said", which is false for + exactly this one case: that slug's own [Lectionary] entry, if it has + one at all, is NOT what the day's citations came from. [None] says so + directly instead of silently mis-naming a Mass. The day's own OFFICE + is not lost by this change -- it is still on the very same + {!Liturgical_day.t} this formulary lives on, via [observed.slug], + which every caller already has in scope regardless of [via]; this + field does not need to duplicate it. *) + +val source_to_string : source -> string diff --git a/lib/kernel/precedence.ml b/lib/kernel/precedence.ml index c207117..7138b6a 100644 --- a/lib/kernel/precedence.ml +++ b/lib/kernel/precedence.ml @@ -91,3 +91,17 @@ let resolve rules ctx ~temporal ~sanctoral = List.rev omitted @ List.map (fun (c, _) -> (c, "omitted: admission limit reached")) dropped; } + +(* RG 111(a): at most one commemoration, and it must be privileged -- see + the .mli for the full citation and why this is a derivation over the + admitted Low-Mass list rather than a second admission rule. [List.find_opt] + keeps input order, which is already precedence order (RG 113), so "the + first privileged entry, if any" is "the highest-precedence privileged + entry, if any" -- the correct single survivor if more than one privileged + commemoration were ever admitted together (not known to occur on any + shipped rite's data, but not assumed impossible either: this reads the + list rather than asserting its length). *) +let sung_mass_commemorations low_mass_set = + match List.find_opt (fun (_, p) -> p = Privileged) low_mass_set with + | Some c -> [ c ] + | None -> [] diff --git a/lib/kernel/precedence.mli b/lib/kernel/precedence.mli index a0b4b1a..05022c5 100644 --- a/lib/kernel/precedence.mli +++ b/lib/kernel/precedence.mli @@ -145,3 +145,47 @@ type 'r resolution = { val resolve : ('s, 'r) rules -> 's context -> temporal:'r candidate -> sanctoral:'r candidate list -> 'r resolution + +(** RG 111(a) (EF; docs/research/rules-register.md; LT.txt, grep "Ratio + admittendi commemorationes"): {i "in diebus liturgicis I classis et in + Missis in cantu non conventualibus, nulla admittitur commemoratio, + praeter unam privilegiatam"} -- on a liturgical day of the first class, + AND at any non-conventual SUNG Mass regardless of the day's own class, + at most ONE commemoration is admitted, and only if it is privileged. + (b)/(c)/(d), immediately following in the same rubric, give the wider + caps -- two ordinary/privileged commemorations depending on class -- + that apply everywhere else; {!rules.admit} already computes exactly + that wider set, which is why this function's own INPUT is the admitted + LOW-MASS list, not a fresh resolution: (a) is not a distinct admission + RULE with its own candidate-ranking logic, it is a narrower CAP applied + afterwards to the identical admitted, precedence-ordered list -- "at + most one, and it must be privileged" is exactly "keep the first + admitted entry, if any, that is privileged", nothing else in the list + can ever outrank it (RG 113: admission order already follows the + rite's own table of precedence, {!rules.admit}'s own citation). + + Deliberately a pure post-hoc DERIVATION over + {!Liturgical_day.t.commemorations}, not a second stored field: the + input list is already validated (privilege-tagged, admission-capped); + this function adds no new information and can regress in no way the + input list itself could not already regress, so a second field would + only create a second place for the same fact to drift out of sync with + the first -- the identical reasoning {!Liturgical_day.t.temporal}'s own + "embedded, not flattened" comment gives for a different field. Exposed + here, at the kernel level, rather than left for an output layer to + reimplement: the filter is small but the RULE it encodes (RG 111(a)) + is not obvious from the type alone, and a caller (the [rubrics] CLI + column, a future template, a differential test) should name the + rubric, not re-derive "privileged commemorations, capped at one" for + itself. + + SCOPE: "non conventualibus" is read literally -- this models the + ordinary (non-conventual) sung Mass only. RG 111(a)'s own text implies + a CONVENTUAL sung Mass keeps the wider (b)/(c)/(d) caps even when sung + (a choir-obligation distinction), but this engine has no concept of + "conventual" at all (no community/choir dimension anywhere in + {!Celebration.t} or {!Liturgical_day.t}), so this function's result + should be read as "what a normal parish/private Low OR sung Mass + admits", never "what every sung Mass, everywhere, admits" -- a + documented scope limit, not an oversight. *) +val sung_mass_commemorations : ('a * privilege) list -> ('a * privilege) list diff --git a/lib/kernel/preface.ml b/lib/kernel/preface.ml new file mode 100644 index 0000000..08d00b4 --- /dev/null +++ b/lib/kernel/preface.ml @@ -0,0 +1,59 @@ +(* RG 482-499 -- see the .mli for the rubric quoted in full and the + placement rationale. Argument-less variants only, so no + [Sexplib0.Sexp_conv] open is needed -- see CLAUDE.md's own gotcha note. *) +type t = + | Nativity + | Epiphany + | Lent + | Holy_cross + | Easter + | Ascension + | Sacred_heart + | Christ_the_king + | Holy_spirit + | Trinity + | Bvm + | St_joseph + | Apostles + | Common + | Requiem +[@@deriving sexp] + +let all = + [ Nativity; Epiphany; Lent; Holy_cross; Easter; Ascension; Sacred_heart; Christ_the_king; + Holy_spirit; Trinity; Bvm; St_joseph; Apostles; Common; Requiem ] + +let to_string = function + | Nativity -> "nativity" + | Epiphany -> "epiphany" + | Lent -> "lent" + | Holy_cross -> "holy-cross" + | Easter -> "easter" + | Ascension -> "ascension" + | Sacred_heart -> "sacred-heart" + | Christ_the_king -> "christ-the-king" + | Holy_spirit -> "holy-spirit" + | Trinity -> "trinity" + | Bvm -> "bvm" + | St_joseph -> "st-joseph" + | Apostles -> "apostles" + | Common -> "common" + | Requiem -> "requiem" + +let of_string = function + | "nativity" -> Some Nativity + | "epiphany" -> Some Epiphany + | "lent" -> Some Lent + | "holy-cross" -> Some Holy_cross + | "easter" -> Some Easter + | "ascension" -> Some Ascension + | "sacred-heart" -> Some Sacred_heart + | "christ-the-king" -> Some Christ_the_king + | "holy-spirit" -> Some Holy_spirit + | "trinity" -> Some Trinity + | "bvm" -> Some Bvm + | "st-joseph" -> Some St_joseph + | "apostles" -> Some Apostles + | "common" -> Some Common + | "requiem" -> Some Requiem + | _ -> None diff --git a/lib/kernel/preface.mli b/lib/kernel/preface.mli new file mode 100644 index 0000000..b43890e --- /dev/null +++ b/lib/kernel/preface.mli @@ -0,0 +1,50 @@ +(** The Mass preface (Missale Romanum, Rubricae Generales, Caput XVII("De + Ritibus servandis in celebratione Missae"), "H) De praefatione", RG + 482-499; docs/research/LT.txt, grep "praefatione dicitur quae cuique"). + + RG 482 gives the resolution chain in full: {i "Praefatio dicitur quae + cuique Missae propria est; qua deficiente, dicitur praefatio de + Tempore, secus communis"} -- the Mass's own PROPER preface; failing + that, the SEASONAL ("de Tempore") one; failing that, the COMMON. RG + 483: {i "Nulla commemoratio, in Missa occurrens, praefationem propriam + inducit"} -- a commemoration never induces its own proper preface, + which is why {!Rite_ef.Rubrics_ef.preface} (the one rite that + implements this so far) reads only the day's OBSERVED celebration, + never its commemorations, the identical discipline {!Rite.t.creed}'s + own RG 476(e) already established. + + RG 484-497 enumerate the fourteen named propers -- Nativity, Epiphany, + Lent, Holy Cross, [the Chrism Mass, out of scope: see the .ml's own + N/A note], Easter, Ascension, the Sacred Heart, Christ the King, the + Holy Spirit, the Trinity, the Blessed Virgin Mary, St Joseph, the + Apostles. RG 498 is the residual Common; RG 499 the Requiem. + + A KERNEL type, not a rite-specific one (the same placement as + {!Colour}, {!Subject}, {!Mass_formulary}): {!Liturgical_day.t} is + parameterised only over a rite's season/rank, so any field it carries + generically must live here, even though only the EF rite constructs a + value of it today -- CLAUDE.md's own "generalise when forced, not + speculatively" stance, already the precedent {!Mass_formulary} + follows. *) + +type t = + | Nativity (** RG 484 *) + | Epiphany (** RG 485 *) + | Lent (** RG 486, "de Quadragesima" *) + | Holy_cross (** RG 487, "de sancta Cruce" *) + | Easter (** RG 489, "paschalis" *) + | Ascension (** RG 490 *) + | Sacred_heart (** RG 491, "de Ss.mo Corde Iesu" *) + | Christ_the_king (** RG 492, "de D. N. Iesu Christo Rege" *) + | Holy_spirit (** RG 493, "de Spiritu Sancto" *) + | Trinity (** RG 494, "de Ss.ma Trinitate" *) + | Bvm (** RG 495, "de beata Maria Virgine" *) + | St_joseph (** RG 496, "de S. Ioseph" *) + | Apostles (** RG 497, "de Apostolis" *) + | Common (** RG 498, "communis" -- the residual when nothing else applies *) + | Requiem (** RG 499, "defunctorum" *) +[@@deriving sexp] + +val all : t list +val to_string : t -> string +val of_string : string -> t option diff --git a/lib/kernel/rite.ml b/lib/kernel/rite.ml index 600a691..e44c2c6 100644 --- a/lib/kernel/rite.ml +++ b/lib/kernel/rite.ml @@ -8,6 +8,7 @@ type ('s, 'r) t = { temporal : Date.t -> ('s, 'r) Temporal.t; anchors : int -> (string * Date.t) list; easter : int -> Date.t; + fixed_key : Date.t -> (int * int) option; rules : ('s, 'r) Precedence.rules; season_runs : 's list; transfer_target : @@ -17,5 +18,8 @@ type ('s, 'r) t = { temporal:('s, 'r) Temporal.t -> date:Date.t -> temporal_at:(Date.t -> ('s, 'r) Temporal.t) -> - Citation.t list; + Mass_formulary.t option * Citation.t list; + creed : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> bool; + gloria : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> bool; + preface : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> Preface.t option; } diff --git a/lib/kernel/rite.mli b/lib/kernel/rite.mli index 0324bf2..d53e4e6 100644 --- a/lib/kernel/rite.mli +++ b/lib/kernel/rite.mli @@ -17,6 +17,33 @@ type ('s, 'r) t = { into rite-agnostic code and be silently wrong for a Julian-reckoning rite. Read by {!Layer.index} to resolve {!Date_spec.Easter_offset}. *) + fixed_key : Date.t -> (int * int) option; + (** The (month, day) under which a FIXED sanctoral entry ({!Layer.on_date}) + is looked up for this civil date. [Some (month, day)] identity for + every rite with no reason to differ -- a Byzantine or other + non-Roman rite supplies nothing beyond that, and its output is + therefore byte-identical to a rite that predates this field + entirely. [None] means no fixed entry can ever be found for this + date, regardless of what {!Layer.index} holds. + + Exists for the Roman calendarium's own bissextile (leap-year) + footnote (February, docs/research/LT.txt:5011-5014): the + intercalary day is inserted by DOUBLING the sixth kalends of March + (civil 24 February in a common year), not by appending a 29th day + at the month's end, so every fixed feast dated at or after that + kalends position is kept one civil day later than usual, and 24 + February itself carries no fixed entry that year. This is a fact + about the ROMAN rite's own kalends reckoning, not a universal + computus rule -- a rite with no such convention (or none at all, + the default above) must not have it hardcoded into rite-agnostic + code, the same reason {!easter} above is rite-supplied rather than + chosen here. See rite_ef/temporal_ef.ml's [bissextile_fixed_key] + for the concrete Roman implementation and its full citation. + + Deliberately untouched: the MOVABLE half of {!Layer.on_date}'s + lookup ({!Date_spec.Easter_offset}, {!Date_spec.Nth_weekday}) -- + this field's contract is fixed-date reckoning only, and nothing in + the calendarium footnote concerns Easter-relative dates. *) rules : ('s, 'r) Precedence.rules; season_runs : 's list; (** the expected run-length-compressed season sequence over one liturgical @@ -71,13 +98,63 @@ type ('s, 'r) t = { temporal:('s, 'r) Temporal.t -> date:Date.t -> temporal_at:(Date.t -> ('s, 'r) Temporal.t) -> - Citation.t list; - (** The day's Epistle and Gospel citations, or []. Rite-supplied for the - same reason [transfer_target] is: what a day with no proper of its - own falls back to is a rubric of a particular rite, not a universal. + Mass_formulary.t option * Citation.t list; + (** The Mass actually said -- which formulary, and how that was decided + -- paired with its Epistle and Gospel citations. Rite-supplied for + the same reason [transfer_target] is: what a day with no proper of + its own falls back to is a rubric of a particular rite, not a + universal. + + The [Mass_formulary.t option] is [None] exactly when the rite's + lectionary is not built at all (the citation list is then also + []): a rite that HAS a lectionary is expected to resolve [Some] on + every day it covers, the same total-coverage discipline + {!Validate}'s own ["formulary"] check holds it to. [None] is never + a per-day "no Mass today" answer for a rite that otherwise + resolves readings -- that shape is coverage FAILURE, not a + legitimate outcome, which is exactly what makes the [Validate] + check meaningful. [temporal_at] is a callback so the rite can reach another date's temporal identity (the preceding Sunday's, for the ferial rule) without re-implementing the temporal cycle -- the same shape [transfer_target]'s own [occupant] callback established. *) + creed : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> bool; + (** Whether the Creed is said, post-Gospel/homily, at this day's Mass + (EF: RG 475-476). A [bool], not an [option]: this is a decision, + and a rite that has not implemented the rule returns [false] + explicitly rather than leaving the question unanswered. + + [temporal] and [observed] are supplied for the same reason + [readings] gets both: a rubric like this one can turn on either + the day's TEMPORAL-cycle identity (e.g. "is this a Sunday, even + one a feast has displaced") or on the celebration actually + observed, and only the rite knows which. [date] is supplied for + the same reason [readings] gets it too -- a rubric keyed to an + Easter-relative window (e.g. "within the octave of Easter") needs + the civil date and the rite's own Easter to test it, and neither + [temporal] nor [observed] alone carries that arithmetic. *) + gloria : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> bool; + (** Whether the Gloria in excelsis is said at this day's Mass (EF: RG + 431-432). Same seam as {!creed} in every respect: same three + parameters and the same reasons for each, a [bool] not an + [option], and [false] is the answer a rite that has not + implemented the rule returns explicitly. *) + preface : temporal:('s, 'r) Temporal.t -> observed:'r Celebration.t -> date:Date.t -> Preface.t option; + (** Which preface is said at this day's Mass (EF: RG 482-499). Same + seam and same three parameters as {!creed}/{!gloria}, for the + same reasons -- {!Preface}'s own citation has the rubric in full. + [Preface.t option], not a bare [Preface.t]: unlike [creed]/ + [gloria], where "not said" is itself a legitimate answer a + [bool] can carry, a preface is said only at a MASS, and this + engine constructs at least one day (Good Friday, the + 1955-restored Holy Week) that resolves an [observed] celebration + but has no Mass at all -- [None] is the honest answer there, not + a manufactured preface. [None] is also the value a rite that has + not implemented this rule returns, the same "the type's own + neutral value" contract {!creed}/{!gloria} give for [false] -- + the two meanings ("this rite does not model the question" and + "this specific day has no Mass to preface") collapse onto the + same representation deliberately: a caller with no rite-specific + context to distinguish them should not need one. *) } diff --git a/lib/kernel/validate.ml b/lib/kernel/validate.ml index c9d4263..f523b39 100644 --- a/lib/kernel/validate.ml +++ b/lib/kernel/validate.ml @@ -239,7 +239,7 @@ let run (rite : ('s, 'r) Rite.t) (layer : 'r Layer.t) ~year = let expected : (string, int) Hashtbl.t = Hashtbl.create 64 in List.iter (fun date -> - Layer.on_date idx date + Layer.on_date ~fixed_key:rite.Rite.fixed_key idx date |> List.iter (fun (e : 'r Layer.entry) -> bump expected (Slug.to_string e.Layer.cel.Celebration.slug))) days; @@ -453,5 +453,34 @@ let run (rite : ('s, 'r) Rite.t) (layer : 'r Layer.t) ~year = fail date "citations" (Printf.sprintf "expected exactly one First and one Gospel, got [%s]" (String.concat "," (List.map Citation.part_to_string sorted)))) + resolved; + (* ---- Formulary invariant (Task 3, celebrant-rubrics-phase1) ---- + + Same rite-agnostic gating as the citation checks immediately + above, and for the same reason: a rite whose lectionary is not + built returns [(None, [])] from {!Rite.readings} on every day, so + [year_has_formulary] is false and this check never fires for it. + A rite that resolves a formulary AT ALL is held to resolving one + on every day of the year -- a day that says no Mass at all is a + defect, not a gap, the same discipline the ["citations-unresolved"] + check above already holds for the citations themselves. One check + name, not two: unlike [citations], there is no separate + "well-formed but wrong" shape to distinguish -- [Mass_formulary.t + option] is either the day's answer or it is missing, so + [year_has_formulary] gates a single ["formulary"] label. *) + let year_has_formulary = + Array.exists + (fun (d : ('s, 'r) Liturgical_day.t) -> d.Liturgical_day.formulary <> None) + resolved + in + if year_has_formulary then + Array.iter + (fun (d : ('s, 'r) Liturgical_day.t) -> + match d.Liturgical_day.formulary with + | Some _ -> () + | None -> + fail d.Liturgical_day.date "formulary" + "no Mass formulary resolved for this day: the lectionary chain fell through \ + every step") resolved); List.rev !failures diff --git a/lib/rites/rite_ef/lectionary_ef.ml b/lib/rites/rite_ef/lectionary_ef.ml index d7b2497..b996412 100644 --- a/lib/rites/rite_ef/lectionary_ef.ml +++ b/lib/rites/rite_ef/lectionary_ef.ml @@ -51,9 +51,9 @@ module Commons = struct | None -> ( (* A formulary with no citations is indistinguishable at the call site from "this saint has no Common" -- [commons_for] would - return [Some []] and [readings] would emit [] either way. That - is exactly the silent hole this project does not allow, so it - is rejected here where it is still nameable. *) + return [Some (common, [])] and [readings] would emit [] either + way. That is exactly the silent hole this project does not + allow, so it is rejected here where it is still nameable. *) match List.find_opt (fun (_, cs) -> cs = []) commons with | Some (s, _) -> Error (Printf.sprintf "commons: common %S has no citations" (Slug.to_string s)) @@ -72,10 +72,19 @@ module Commons = struct (Slug.to_string saint) (Slug.to_string common)) | None -> Ok { commons; assigned }))) + (* Returns the Common's own id ALONGSIDE its citations, not the citations + alone: [readings]' step 4 needs the id to build the day's + {!Colitur_kernel.Mass_formulary.t} ("the Common's own id as its slug"), + and the id is only ever in scope here, at the point [common] is looked + up -- re-deriving it afterwards would mean a second [assoc_opt] search + over [t.assigned] for a value this function already held. *) let find t saint = match List.assoc_opt saint t.assigned with | None -> None - | Some common -> List.assoc_opt common t.commons + | Some common -> ( + match List.assoc_opt common t.commons with + | None -> None + | Some cs -> Some (common, cs)) (* Byte-for-byte the failure discipline of [Lectionary.load] (see its own comments for why each catch-all is placed where it is): every parse and @@ -250,7 +259,8 @@ let is_bvm_saturday_office (observed : Vocab_ef.rank Celebration.t) let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = match observed.Celebration.citations with - | _ :: _ as cs -> cs + | _ :: _ as cs -> + (Some { Mass_formulary.said = Some observed.Celebration.slug; via = Mass_formulary.Proper }, cs) | [] -> ( (* Step 4: a saint who is the day's observed office and has no proper says his assigned Common. The assignment is explicit, never @@ -346,7 +356,8 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = match if sanctoral_office then commons_for ~commons observed.Celebration.slug else None with - | Some cs -> cs + | Some (common_id, cs) -> + (Some { Mass_formulary.said = Some common_id; via = Mass_formulary.Common }, cs) | None -> ( (* The votive Mass of Our Lady on Saturday (RG 309(a)) runs HERE: after the proper (step 1) and the Common (step 4), which answer @@ -354,13 +365,73 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = lookup -- which is exactly what used to answer, with the feria's own Mass, on a day whose office is Our Lady's. Placing it later would be dead code; placing it earlier would let it outrank a - real saint's proper. *) + real saint's proper. + + FORMULARY PROVENANCE: [Votive], not [Own_slug] (CORRECTED, fix + round 1, coordinator review -- the first pass tagged this + [Own_slug] for lack of a better constructor and flagged it as a + judgement call; [Mass_formulary.source] has grown a [Votive] + case since, precisely for this branch). RG 431(e) + (docs/research/LT.txt, verbatim): "e) in Missis votivis IV + classis de Angelis, quocumque die, et de B. Maria Virg. quae in + sabbato celebrantur" -- votive Masses of the IV class, of the + Angels on any day, and of the BVM WHICH ARE CELEBRATED ON + SATURDAY: the Missal's own words classify this exact Mass as a + "Missa votiva", not as the day's own office's Mass, corroborated + by RG 309(a) (this branch's own header comment above, "iuxta + temporum diversitatem") naming the FIVE seasonal Masses RG 431(e) + is speaking of. Together: a votive Mass said IN PLACE of the + day's own office's Mass, the office (RG 78, Officium sanctae + Mariae in sabbato) being kept unchanged. + + CORRECTED, fix round 2 (coordinator review): fix round 1's own + comment here claimed the Latin Mass Society Ordo witnesses + [Votive] directly, printing "V Mass of BVM" with "V" read as an + abbreviation for "votive". That was the coordinator's + misreading, not this codebase's, and it was wrong: the Ordo's + "I"-"V" are ROMAN NUMERALS naming WHICH of the Missal's five + seasonal "Missae de sancta Maria in sabbato" (this branch's own + header comment; RG 309(a)'s "iuxta temporum diversitatem") is + said on a given Saturday -- not an abbreviation of anything, and + not a marker of the Mass's class or kind. All five numerals + occur through the Ordo (I x1, II x4, III x3, IV x3, V x8, + counted across the whole document); "V Mass of BVM" merely also + happens to be substring-matched by a naive search for "V Mass of + BVM" inside "IV Mass of BVM", which is what produced the + original false reading. [Votive] itself is UNAFFECTED by this + correction and stays right, on RG 431(e) alone -- only the + Ordo-witness claim is retracted, not softened, removed. A + genuinely useful consequence survives the mistake: because the + Ordo's own numeral names WHICH seasonal Mass is said, a future + comparison against it (Task 6 of this plan) can validate + [bvm_saturday_citations]'s own season-keyed SELECTION, not + merely that some BVM Mass was chosen. + + [said] used to be set HERE to the day's own temporal slug + (reasoning: [is_bvm_saturday_office] only ever fires when + [sanctoral_office] above is false, i.e. the observed + celebration already IS the day's own temporal office, which + deliberately reuses the ordinary ferial slug, [Temporal_ef]'s + own [bvm_saturday_names]). CORRECTED (whole-branch review fix + round): that value is the OFFICE's slug, not the slug whose + Mass is actually said -- the five seasonal Masses RG 309(a) + names have no slug of their own anywhere in the shipped data, + so [said] is [None] here, honestly, rather than silently + naming the wrong thing. See {!Colitur_kernel.Mass_formulary.t}'s + own [said] citation for the full account; the office itself is + not lost, it is still [observed.slug] on the very same + {!Colitur_kernel.Liturgical_day.t} this formulary lives on. *) if is_bvm_saturday_office observed temporal then - bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date) - ~day:(Date.day date) + ( Some { Mass_formulary.said = None; via = Mass_formulary.Votive }, + bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date) + ~day:(Date.day date) ) else match Lectionary.find lectionary temporal.Temporal.office.Celebration.slug with - | Some cs -> cs + | Some cs -> + ( Some + { Mass_formulary.said = Some temporal.Temporal.office.Celebration.slug; + via = Mass_formulary.Own_slug }, + cs ) | None -> ( (* Step 3: a feria with no proper of its own says the preceding Sunday's Mass. WARRANT is the same as step 2's -- lectio's own @@ -404,12 +475,14 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = season name), so deriving one from the other textually would be a latent bug the moment a season's naming convention differs. *) let offset = days_since_sunday temporal.Temporal.weekday in - if offset = 0 then [] + if offset = 0 then (None, []) else let sunday = Date.add_days date (-offset) in let sunday_temporal = temporal_at sunday in match Lectionary.find lectionary sunday_temporal.Temporal.office.Celebration.slug with - | Some cs -> cs - | None -> []))) + | Some cs -> + let said = sunday_temporal.Temporal.office.Celebration.slug in + (Some { Mass_formulary.said = Some said; via = Mass_formulary.Preceding_sunday }, cs) + | None -> (None, [])))) diff --git a/lib/rites/rite_ef/lectionary_ef.mli b/lib/rites/rite_ef/lectionary_ef.mli index caefc74..715e9c2 100644 --- a/lib/rites/rite_ef/lectionary_ef.mli +++ b/lib/rites/rite_ef/lectionary_ef.mli @@ -72,21 +72,28 @@ module Commons : sig val assignments : t -> (Slug.t * Slug.t) list end -(** The Common assigned to a saint who has no proper, if any. Exposed for the - golden pins, which must show WHICH Common fired, not merely that two - citations appeared. +(** The Common assigned to a saint who has no proper, if any -- its own id + ALONGSIDE its citations, not the citations alone: {!readings}' step 4 + needs the id to name which Common fired in the {!Colitur_kernel.Mass_formulary.t} + it builds. Exposed for the golden pins too, which must show WHICH Common + fired, not merely that two citations appeared. Takes the table explicitly for the same reason {!readings} takes [~lectionary]: the data is the caller's, not this module's. *) -val commons_for : commons:Commons.t -> Slug.t -> Citation.t list option +val commons_for : commons:Commons.t -> Slug.t -> (Slug.t * Citation.t list) option -(** The day's Epistle and Gospel citations, or []. +(** The Mass actually said -- which formulary, and how that was decided -- + paired with the day's Epistle and Gospel citations. [(None, [])] when + none of the four steps below answers. Four steps, in EXECUTION order 1, 4, 2, 3 (the numbers are the plan's and are kept as written, so that every "step 3" already recorded in a test - name, comment or report still means the same branch): + name, comment or report still means the same branch). Each step's own + {!Colitur_kernel.Mass_formulary.source} is built at the point the step + decides, not re-derived afterwards from the citations it returns: - {b Step 1} -- the observed celebration's own proper. + {!Colitur_kernel.Mass_formulary.Proper}, [said] the observed slug. - {b Step 4} -- a saint who is the day's observed office and has no proper says his assigned Common. Runs before the temporal fallbacks, not after them: this is the only step in the chain with a direct @@ -98,14 +105,42 @@ val commons_for : commons:Commons.t -> Slug.t -> Citation.t list option a feria, a Sunday, the Triduum and the RG 78 Saturday Office of the BVM (whose observed celebration is its own temporal office) are structurally excluded, not merely absent from the data. + {!Colitur_kernel.Mass_formulary.Common}, [said] the Common's own id. - {b Step 2} -- the day's own temporal slug in the lectionary. + {!Colitur_kernel.Mass_formulary.Own_slug}, [said] that slug. The RG + 309(a) Saturday votive Mass of Our Lady also answers here (structurally, + not as a fifth numbered step), but is tagged + {!Colitur_kernel.Mass_formulary.Votive} instead, not [Own_slug]: RG + 431(e) ("in Missis votivis IV classis ... de B. Maria Virg. quae in + sabbato celebrantur", docs/research/LT.txt) classifies it, in the + Missal's own words, as a "Missa votiva" said IN PLACE of the day's own + office's Mass, the office (RG 78) itself being kept, corroborated by RG + 309(a)'s own "iuxta temporum diversitatem" naming the five seasonal + Masses RG 431(e) speaks of. (CORRECTED, fix round 2: this previously + also cited the Latin Mass Society Ordo as witnessing the tag directly, + reading its "V Mass of BVM" as an abbreviation for "votive" -- the + coordinator's own misreading. The Ordo's "I"-"V" are ROMAN NUMERALS + naming which of the five seasonal Masses is said, not a marker of the + Mass's kind; see the implementation comment on this branch for the + full account and the validation use this correction still leaves + available for Task 6.) [said] is [None] here (whole-branch review fix + round, celebrant-rubrics-phase1): the five seasonal Masses RG 309(a) + names carry no slug of their own anywhere in the shipped data, so + there is no slug this field could honestly report -- see + {!Colitur_kernel.Mass_formulary.t}'s own [said] citation for the full + account. The day's own OFFICE (the guard that reaches this branch + only ever fires when the observed celebration already IS the day's + own temporal office) is unaffected and is still [observed.slug] on + the same {!Colitur_kernel.Liturgical_day.t}. - {b Step 3} -- for a weekday whose own slug has no entry, the preceding Sunday's temporal slug (never its observed one; a Sunday is guarded out because it has no PRECEDING Sunday to resume, not because consulting itself would loop -- [readings] is not recursive, see its own implementation comment). + {!Colitur_kernel.Mass_formulary.Preceding_sunday}, [said] that + Sunday's temporal slug. - A day matching none of the four gets []. *) + A day matching none of the four gets [(None, [])]. *) val readings : lectionary:Lectionary.t -> commons:Commons.t -> @@ -113,4 +148,4 @@ val readings : temporal:(Vocab_ef.season, Vocab_ef.rank) Temporal.t -> date:Date.t -> temporal_at:(Date.t -> (Vocab_ef.season, Vocab_ef.rank) Temporal.t) -> - Citation.t list + Mass_formulary.t option * Citation.t list diff --git a/lib/rites/rite_ef/precedence_ef.mli b/lib/rites/rite_ef/precedence_ef.mli index 4c2523a..0100d40 100644 --- a/lib/rites/rite_ef/precedence_ef.mli +++ b/lib/rites/rite_ef/precedence_ef.mli @@ -132,6 +132,22 @@ val sunday_marker : string recognising a live candidate again. *) val major_litanies_slug : string +(** RG 112(d)'s own closed, hand-verified list of sanctoral entries that are + themselves a feast/commemoration OF the Blessed Virgin Mary in her own + right -- see the .ml's own citation for the full derivation and the + entries considered and excluded. A celebration is "of the BVM" for + {!disposition}'s RG 112(d) branch when its [subject] is [Subject.Bvm] OR + its slug is on this list ({!Celebration.t}'s [subject] field is NOT + reliably [Bvm] for most Marian sanctoral entries -- bootstrapped from + lectio, most carry [Saint] instead, this list is the reliable signal). + + Exposed (task 5, the Creed, RG 475(c) "festis II classis... B. Mariae + Virg.") so a second rite-local consumer can test the identical + Marian-identity question without re-deriving its own list and risking + drift from this one -- the same reasoning {!vigil_feast_table} and + {!is_vigil} are already exposed for. *) +val marian_slugs : string list + (** [disposition ~winner ~loser]: RG 92-95, 33, 21-27, 94 (docs/research/ rules-register.md §4, "Occurrence", "Vigils" and "Caput IV, 'De feriis'"). What becomes of a losing candidate, decided by the LOSER's diff --git a/lib/rites/rite_ef/rite_ef.ml b/lib/rites/rite_ef/rite_ef.ml index ec6d2b9..808e017 100644 --- a/lib/rites/rite_ef/rite_ef.ml +++ b/lib/rites/rite_ef/rite_ef.ml @@ -8,6 +8,7 @@ module Vocab_ef = Vocab_ef module Temporal_ef = Temporal_ef module Precedence_ef = Precedence_ef module Lectionary_ef = Lectionary_ef +module Rubrics_ef = Rubrics_ef open Colitur_kernel @@ -38,6 +39,10 @@ let context ~lectionary ~commons : (Vocab_ef.season, Vocab_ef.rank) Rite.t = Julian-reckoning rite can supply {!Computus.julian_easter} instead. Read by [Layer.index] for [Date_spec.Easter_offset]. *) easter = Colitur_kernel.Computus.gregorian_easter; + (* The calendarium's own bissextile footnote (February, LT.txt:5011-5014): + see {!Temporal_ef.bissextile_fixed_key} for the full citation and + mechanism. Read by [Layer.on_date]'s fixed half only. *) + fixed_key = Temporal_ef.bissextile_fixed_key; rules = { Precedence.band = Precedence_ef.band; disposition = Precedence_ef.disposition; @@ -45,4 +50,7 @@ let context ~lectionary ~commons : (Vocab_ef.season, Vocab_ef.rank) Rite.t = vigil_feast = Precedence_ef.vigil_feast }; season_runs = Vocab_ef.seasons; transfer_target = Precedence_ef.transfer_target; - readings = Lectionary_ef.readings ~lectionary ~commons } + readings = Lectionary_ef.readings ~lectionary ~commons; + creed = Rubrics_ef.creed; + gloria = Rubrics_ef.gloria; + preface = Rubrics_ef.preface } diff --git a/lib/rites/rite_ef/rite_ef.mli b/lib/rites/rite_ef/rite_ef.mli index 2183799..2ed61de 100644 --- a/lib/rites/rite_ef/rite_ef.mli +++ b/lib/rites/rite_ef/rite_ef.mli @@ -10,6 +10,7 @@ module Vocab_ef = Vocab_ef module Temporal_ef = Temporal_ef module Precedence_ef = Precedence_ef module Lectionary_ef = Lectionary_ef +module Rubrics_ef = Rubrics_ef (** The EF rite, bundled (design spec's [RITE] signature, realised as a {!Colitur_kernel.Rite.t} value rather than a functor -- see rite.mli): @@ -32,6 +33,16 @@ module Lectionary_ef = Lectionary_ef slug, else (a weekday with no entry of its own) the preceding Sunday's temporal slug, in data/ef/lectionary.sexp. See {!Lectionary_ef.readings} for why the Common is consulted second rather than last. + - [creed]: {!Rubrics_ef.creed}, RG 475-476 -- whether the Creed is said. + The first rubric in this phase governing a part of Mass rather than + occurrence/precedence. + - [gloria]: {!Rubrics_ef.gloria}, RG 431-432 -- whether the Gloria in + excelsis is said. Reads {!Rubrics_ef.te_deum} (Breviary nn. 237-238) + for RG 431(a)/432(a)'s own deferral. + - [preface]: {!Rubrics_ef.preface}, RG 482-499 -- which preface is + said. Same seam as [creed]/[gloria]; [None] both for a day with no + Mass at all (Good Friday) and for a rite that has not implemented + the rule. Deliberately carries no [sanctoral]/[lectionary] fields the way the original design-doc sketch of [RITE] does: {!Colitur_kernel.Rite.t} (the diff --git a/lib/rites/rite_ef/rubrics_ef.ml b/lib/rites/rite_ef/rubrics_ef.ml new file mode 100644 index 0000000..ce2cfcc --- /dev/null +++ b/lib/rites/rite_ef/rubrics_ef.ml @@ -0,0 +1,1244 @@ +(* RG 475-476 (docs/research/LT.txt, grep "dicitur symbolum"; scan1.txt line + ~3872-3888), quoted here in full so every branch below can cite its own + letter without re-quoting the whole rubric: + + "475. Post Evangelium aut homiliam, dicitur symbolum: + a) in qualibet dominica, etsi eius Officium alicui festo locum + cedat, vel Missa votiva II classis celebretur; + b) in festis I classis et in Missis votivis I classis; + c) in festis II classis Domini et B. Mariae Virg.; + d) per octavas Nativitatis Domini, Paschatis et Pentecostes, etiam + in festis occurrentibus et in Missis votivis; + e) in festis nataliciis Apostolorum et Evangelistarum, necnon in + festis Cathedrae S. Petri et S. Barnabae Ap. + + 476. Non dicitur symbolum: + a) in Missis sive chrismatis sive in Cena Domini, feria V + Hebdomadae sanctae, et in Missa Vigiliae paschalis; + b) in festis II classis, iis exceptis quae supra, n. 475 c et e, + recensentur; + c) in Missis votivis II classis; + d) in Missis festivis et votivis III et IV classis; + e) ratione alicuius commemorationis in Missa occurrentis; + f) in Missis defunctorum." + + SCOPE NOTE, checked once here rather than at every clause below: this + engine resolves ONE observed office and ONE Mass per civil day (see + Rite.t.readings' own doc comment) -- it has no separate "which votive + Mass is said" dimension. So the "vel/et...votivis" halves of 475(a)/(b), + 476(c) entirely, and 476(d)'s "et votivis" half are genuinely + inapplicable to this implementation -- a documented scope limit, not a + defect. 476(e) needs no branch at all: [creed] below reads only + [observed], never a day's admitted commemorations, so a commemoration + can never change its answer by construction. + + 476(f) ("in Missis defunctorum") is DIFFERENT: this file used to carry + it in the same "not modelled" list above, on the reasoning that + [creed]'s inputs (temporal/observed/date) have no notion of "this Mass + is a Requiem". That reasoning was wrong, found by the LMS Ordo layer + (test_lms_ordo.ml, allow-list entry L1, now closed -- see + expected-divergences-lms.sexp) on 2025-11-03, All Souls' Day: colitur + said the Creed where the Ordo, correctly, does not. [observed] DOES + carry a usable signal -- RG 117 assigns black to Masses of the dead, + and {!Colour.Black} is used by exactly TWO celebrations in this whole + engine, verified by grepping every [colour Black]/[Colour.Black] site + in lib/ and data/: [commemoration-of-all-souls] in + data/ef/sanctoral.sexp, and Good Friday in temporal_ef.ml (which is a + Holy Week FERIA, RG 23(b), already excluded by the [n >= -6 && n <= + -1] branch below regardless of colour, and has no Mass at all in the + 1955-restored Holy Week). So on every day this engine can actually + construct, [colour = Black] if and only if the Mass is a Requiem -- + a citable implication ON THIS DATA, not a heuristic guess. [creed] + below uses it as 476(f)'s own guard. This is a PROXY, not a general + "is this a Requiem Mass" field, and it is only as good as that + two-member population: {!test_rubrics_ef}'s own + [test_colour_black_population_is_exactly_two] fails loudly the day a + third [Colour.Black] celebration is added anywhere, so the proxy + cannot silently rot into covering (or missing) a non-Requiem black + Mass. If that ever happens, this guard needs re-deriving, not merely + re-approving. *) + +open Colitur_kernel + +(* RG 475(e): "in festis nataliciis Apostolorum et Evangelistarum, necnon in + festis Cathedrae S. Petri et S. Barnabae Ap." NATALICIUM means the feast + of the saint's own death (dies natalis) -- not every feast that merely + names him. That is precisely why the clause has to name the Chair of St + Peter and St Barnabas EXPLICITLY: neither is a natalicium (Peter's own is + 29 June, shared with Paul; Barnabas's is his own day, 11 June, but the + clause names him anyway, redundantly with the natalicium reading, rather + than leave it to inference), so neither would be covered without the + explicit "necnon". + + DERIVED, not copied from any list supplied with this task: grepped + data/ef/sanctoral.sexp directly for every entry whose English or Polish + name mentions "Apostle"/"Evangelist"/"Aposto{l/ł}a", then each + candidate's own date, rank and status checked against the calendarium + and against whether it is that saint's own dies natalis. Every entry + below was cross-checked against the shipped data, not assumed: + + andrew (30 Nov, Class2) -- his natalicium. + barnabas (11 June, Class3) -- named explicitly; also his own natalicium. + bartholomew (24 Aug, Class2) -- his natalicium. + chair-of-st-peter (22 Feb, Class2) -- named explicitly ("Cathedrae S. + Petri"); NOT a natalicium (Peter's own is 29 June, shared with Paul) + -- exactly why the clause has to name it. + james-the-greater (25 July, Class2) -- his natalicium. + john-the-evangelist (27 Dec, Class2) -- his natalicium (the one Apostle + traditionally held to have died a natural death; "natalicium" still + names his own feast day, not only a martyr's). + luke-the-evangelist (18 Oct, Class2) -- his natalicium. + mark (25 April, Class2) -- the Evangelist ("Marka Ewangelisty" in the + data's own Polish name); NOT "mark-i" (7 Oct), a different saint (a + Pope), excluded. + matthew (21 Sep, Class2) -- Apostle and Evangelist, his natalicium. + matthias (24 Feb, Class2) -- his natalicium. + sts-peter-paul (29 June, Class1) -- the natalicium of both. + sts-philip-james (11 May, Class2) -- the natalicium of both (James the + Less; there is no separate "james-the-less" entry in the data). + sts-simon-jude (28 Oct, Class2) -- the natalicium of both. + thomas (21 Dec, Class2) -- his natalicium. + + Checked and DELIBERATELY EXCLUDED (the Trap this clause is built around): + conversion-of-st-paul (25 Jan, Class3) -- not a natalicium: it + commemorates an EVENT of his life, not his death. + in-commemoratione-sancti-pauli-apostoli (30 June, Class3, status + Feast, so it CAN be observed, unlike the two entries below) -- a + secondary commemoration of Paul, not his dies natalis (his own is 29 + June, with Peter); its own name says so ("In Commemoratione", not a + feast of his martyrdom). + "peter" (25 Jan) and "paul" (22 Feb) -- both status + [Commemoration_only] (RG 110's own Peter/Paul companions, on the + Conversion and Chair days respectively: {!Precedence_ef.disposition}'s + own citation), so neither can ever be [observed]; moot either way, + but neither is a natalicium regardless. + mark-i (7 Oct) -- a different saint (Pope St Mark), not the + Evangelist. *) +let creed_apostle_slugs = + [ "andrew"; "barnabas"; "bartholomew"; "chair-of-st-peter"; "james-the-greater"; + "john-the-evangelist"; "luke-the-evangelist"; "mark"; "matthew"; "matthias"; + "sts-peter-paul"; "sts-philip-james"; "sts-simon-jude"; "thomas" ] + +let creed ~(temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) + ~(observed : Vocab_ef.rank Celebration.t) ~(date : Date.t) : bool = + let easter = Computus.gregorian_easter (Date.year date) in + let n = Date.to_rata date - Date.to_rata easter in + let m = Date.month date and dd = Date.day date in + let slug = Slug.to_string observed.Celebration.slug in + if + (* RG 475(d): "per octavas Nativitatis Domini, Paschatis et + Pentecostes, etiam in festis occurrentibus et in Missis votivis" -- + an unconditional window override, checked first: EVEN a saint's + feast that wins the day within one of the three octaves (St Stephen, + 26 December, is the live witness -- RG 67's own "Com. octavae + Nativitatis" note, quoted in full in temporal_ef.ml's [named]) still + says the Creed. Pure date/Easter-offset arithmetic, not season or + rank: Ascension (Easter+39) and the Pentecost Vigil (Easter+48) are + both [Class1] and both fall inside the Paschaltide SEASON but + outside either 8-day OCTAVE, so a rank- or season-based test here + would wrongly include them -- checked and rejected for exactly this + reason. + + Nativity: 25-31 December (its own day plus 7) + 1 January (RG 91 + entry 5's own "Octave Day of the Nativity", the identical table + entry as 24 December's vigil -- temporal_ef.ml's [named]). Easter: + Easter Sunday (offset 0) through Low Sunday (offset 7) -- RG 11's + own "dominicae Paschatis et Pentecostes sunt pariter festa I classis + CUM OCTAVA". Pentecost: Pentecost (offset 49) through Trinity Sunday + (offset 56), the RG 91-entry-14-adjacent "octave day" Trinity Sunday + itself names in temporal_ef.ml. *) + (m = 12 && dd >= 25 && dd <= 31) + || (m = 1 && dd = 1) + || (n >= 0 && n <= 7) + || (n >= 49 && n <= 56) + then true + else if + (* RG 475(a): "in qualibet dominica, ETSI EIUS OFFICIUM ALICUI FESTO + LOCUM CEDAT" -- the Creed is said on any Sunday even when a feast + displaces the Sunday's own office (RG 16(a): a Feast of the Lord I + or II class occurring on a II-class Sunday takes its place "cum + omnibus iuribus et privilegiis"). Read off [temporal]'s own weekday + -- the day's calendar fact, independent of whatever [observed] turns + out to be -- never off [observed]'s slug or rank, which is exactly + what would go silently wrong the day such an impeding feast wins: + see {!Colitur_kernel.Precedence.rules.admit}'s own [~temporal] + parameter (precedence.mli) for the identical argument, made there + for RG 111(b) rather than RG 475(a). *) + temporal.Temporal.weekday = Date.Sun + then true + else if + (* RG 23 (Caput IV, "De Feriis"): "Feriae I classis sunt: a) feria IV + cinerum; b) omnes feriae Hebdomadae sanctae." Ash Wednesday and every + feria of Holy Week (Monday through Saturday -- RG 91 entry 2's + Sacred Triduum, Thursday-Saturday, is a THIRD sub-case of this same + "feria", not a "festum": RG 35, immediately below in Caput VI, + defines "festum" as a distinct liturgical-day category from "feria", + RG 21-27) are FERIAE, never FESTA, however high their RG 91 rank -- + so 475(b)/(c)'s "in festis" never reaches them, regardless of rank. + + This single structural check subsumes 476(a)'s own explicit naming + of the Chrism Mass, the Mass of the Lord's Supper (both Holy + Thursday) and the Easter Vigil Mass (Holy Saturday's date): both are + already excluded here as Holy Week feriae, so 476(a) needs no + separate branch. (Good Friday needs no rubric at all -- RG 28's own + closing sentence on the Paschal Vigil aside, Good Friday's own + liturgical action has no Mass in the 1955-restored Holy Week to + begin with, so the question is moot there independent of this + check -- but this structural test correctly excludes it too, since + it is also named in RG 23(b).) + + RG 24-25 (immediately following, same Caput IV) name TWO MORE + ferial classes this branch does not reach: feriae II classis (RG + 24 -- the Advent ferias 17-23 December, and the Quatuor Temporum + sets of Advent, Lent and September) and feriae III classis (RG 25 + -- the numbered Lenten/Passiontide ferias from the Thursday after + Ash Wednesday to the Saturday before Passion Sunday II, and the + un-Embered Advent ferias to 16 December). NEITHER is excluded by a + check anywhere in this module -- this branch and RG 33's vigil + branch immediately below are the whole of what [creed] tests + before falling through to 475(b)/(c)/(e)'s own rank/subject/slug + guards. They do not need an explicit exclusion of their own for + 475(b): temporal_ef.ml's own [ferial_rank] never returns [Class1] + for them (only Ash Wednesday and Holy Week do, RG 23's own population, + already excluded above), so that branch is unreachable for them + regardless of anything checked here. But RG 24's own II-class set + DOES reach 475(c)'s [Class2] guard below, and 475(e)'s + apostle-slug guard carries no rank floor at all, so both classes + genuinely reach a live branch of this function. Getting [false] + there is NOT established by this exclusion, or by any check in + this file: it rests on an unstated property of {!Temporal_ef} -- + every ferial-origin office it builds carries [subject = Temporal] + and an "ef-"-prefixed slug, never [Lord]/[Bvm] or a name on + {!creed_apostle_slugs}. Verified directly in temporal_ef.ml: the + Ember/Rogation/generic-ferial branches all go through [build]'s + own default [subject = Temporal], with exactly two documented + exceptions, neither able to reach a live branch below -- the + Sacred Triduum ([subject = Lord], but [Class1], already excluded + above) and the votive Office of the BVM on Saturday, RG 91 entry + 27 ([subject = Bvm], but [Class4], never satisfying 475(c)'s own + [Class2] guard). + + (CORRECTED, review fix: this comment, and 475(b)'s own immediately + below, previously read as though "the two exclusions immediately + above" disposed of ferias in general -- they dispose of feria I + classis only. RG 24/25's own higher classes were excluded by NO + check, an unstated-invariant gap now named here rather than + silently relied on: test/test_rubrics_ef.ml's own ferial-invariant + sweep now asserts the Temporal_ef property above directly against + real output, so a future change that broke it would fail that + test rather than silently changing the Creed.) *) + n = -46 || (n >= -6 && n <= -1) + then false + else if + (* RG 28-34 (Caput V, "De Vigiliis"): a vigil is its OWN liturgical-day + category, distinct from "festum" (RG 35, Caput VI) the same way a + feria is (immediately above) -- so 475(b)/(c)'s "in festis" does not + reach a vigil either, regardless of its own RG 91 rank. This is also + why 476(a) has to name the Easter Vigil explicitly: RG 28's own + closing sentence says the Paschal Vigil, uniquely, "non sit dies + liturgicus" [is not a liturgical day] at all, so it is not even a + "vigilia" in RG 29-32's numbered sense -- nothing else in this + taxonomy would have excluded it without that explicit clause, unlike + every OTHER vigil, which is excluded merely by being one. + {!Precedence_ef.is_vigil} already tests both slug conventions this + codebase's data uses (the temporal cycle's "-vigil" suffix and the + sanctoral bootstrap's "vigil-of-" prefix) for the identical RG 33 + question; reused here rather than re-derived, on the same footing as + {!Precedence_ef.marian_slugs} just below. *) + Precedence_ef.is_vigil slug + then false + else if + (* RG 476(f): "in Missis defunctorum" -- the Creed is never said at a + Requiem Mass, checked here, ahead of 475(b)'s rank branch, the same + "category excludes regardless of rank" position as the feria and + vigil checks immediately above (All Souls' Day is [Class1], so + without this guard 475(b) would grant it [true] unopposed, which is + exactly the defect this guard fixes -- see this file's own header + for the two-member [Colour.Black] population this proxy rests on, + and {!Colour.Black}'s own citation, RG 117, for why colour is the + Requiem signal. Placed before, not after, 475(b)/(c)/(e) so a black + Class1 or Class2 day can never reach them; nothing above this point + (the Nativity/Easter/Pentecost octave override, the Sunday rule, the + feria and vigil exclusions) is ever reachable by a Requiem Mass on + the shipped data either -- a Requiem is never kept on a Sunday or + inside a privileged octave -- so this guard's own position relative + to THOSE branches is moot on real data, checked, not merely assumed: + {!creed_apostle_slugs} and [marian_slugs] contain no Black-coloured + entry, and 2 November can never fall inside any of the three + octaves 475(d) names. *) + observed.Celebration.colour = Colour.Black + then false + else if + (* RG 475(b): "in festis I classis". Genuine feasts only, by + construction of the two exclusions immediately above (feria I + classis -- Ash Wednesday and Holy Week, the only feriae that are + ever [Class1]; RG 24/25's II- and III-class feriae are a different + population and never reach this rank at all, see the RG 23 + comment's own note above -- and vigils) -- every remaining + [Class1] candidate reaching this branch is a real festum: the + Nativity, Epiphany, Ascension, Corpus Christi, the Sacred Heart, + Christ the King, a I-class sanctoral feast (the Assumption, the + Immaculate Conception...), or a I-class Sunday (already [true] + above via 475(a), so this branch is never the FIRST to grant those + a [true], only ever redundant with it). *) + observed.Celebration.rank = Vocab_ef.Class1 + then true + else if + (* RG 475(c): "in festis II classis Domini et B. Mariae Virg." -- + [subject = Lord] is reliably set on genuine II-class sanctoral + feasts of the Lord (Exaltation of the Holy Cross, the Purification, + the Transfiguration, the Commemoration of the Baptism of the Lord, + the Dedication of the Lateran Archbasilica -- checked directly + against data/ef/sanctoral.sexp: six [subject = Lord] entries ship, + none a vigil or feria) and on the two temporal-cycle Class2 Lord + feasts (Holy Family, Holy Name of Jesus). [subject = Bvm], by + contrast, is NOT reliable for the BVM half: checked directly against + the data, almost every Marian sanctoral entry (the Assumption, the + Annunciation, the Immaculate Heart, the Nativity of the BVM...) + ships [subject = Saint] instead -- {!Precedence_ef.marian_slugs} is + the list built (and, here, reused rather than re-derived) precisely + because the [subject] field cannot be trusted alone for this + question; see its own citation in precedence_ef.mli. + + This [Class2] guard is also the one live branch RG 24's own + II-class feriae (Advent 17-23, the Advent/Lent/September Ember + sets) genuinely reach -- the RG 23 comment above (this file, the + [n = -46 ...] branch) has the full account of why they still come + out [false] here: an unstated Temporal_ef property, checked by a + test, not a guard in this file. *) + observed.Celebration.rank = Vocab_ef.Class2 + && (observed.Celebration.subject = Subject.Lord + || observed.Celebration.subject = Subject.Bvm + || List.mem slug Precedence_ef.marian_slugs) + then true + else + (* RG 475(e): see {!creed_apostle_slugs}'s own citation. Checked last + and without a rank guard, on purpose -- Barnabas is only [Class3] + and the Chair of St Peter's own [subject] is [Saint], so neither + would ever be reached by the two branches above; every [Class1] + entry on the list (Sts Peter & Paul) is already [true] via 475(b), + so this branch is redundant, never wrong, for those. *) + List.mem slug creed_apostle_slugs + +(* Breviarium Romanum, 1961 Codex Rubricarum, "N) De hymno Te Deum" + (docs/research/breviary/rubricae-breviarii-1961.txt; docs/research/ + breviary/PROVENANCE.md has this source's own provenance and weakness in + full), quoted here in full so every branch below can cite its own + letter without re-quoting the whole rubric: + + "237. Hymnus Te Deum dicitur ad Matutinum, post ultimam lectionem, loco + noni vel tertii responsorii: + a) in dominica in albis, in dominica Pentecostes, et in Matutino + dominicae Resurrectionis, quod recitatur ab iis qui Vigiliae paschali + non interfuerunt; + b) in dominicis II classis, exceptis dominicis in Septuagesima, in + Sexagesima et in Quinquagesima; + c) in omnibus festis; + d) per octavas Nativitatis Domini, Paschatis et Pentecostes; + e) in Officio feriali temporis natalicii et temporis paschalis; + f) in vigiliis Ascensionis et Pentecostes; + g) in Officio sanctae Mariae in sabbato. + + 238. Omittitur vero hymnus Te Deum: + a) in Officiis de Tempore a dominica I Adventus usque ad vigiliam + Nativitatis Domini inclusive; et a dominica in Septuagesima usque ad + Sabbatum sanctum inclusive; + b) in vigiliis II et III classis, excepta vigilia Ascensionis + Domini; + c) in omnibus feriis per annum; + d) in Officio defunctorum." + + THE WEAKNESS, restated (PROVENANCE.md has the full account): this is a + SINGLE WEB TRANSCRIPTION (ceremoniaire.net), not yet checked against a + photographic scan -- the weakest-sourced rule in this project. Mitigated, + not resolved, by the FIUV universal Ordo's own Te Deum column + (test/fixtures/fiuv-ordo-2025-2026.sexp, 262 "Te Deum" rows out of 400 -- + an independent day-level witness, never itself derived from this + transcription) -- see test_fiuv_ordo.ml, which compares [te_deum]'s own + output against it. A mismatch there may indict this transcription rather + than [te_deum]; adjudicated per that file's own allow-list, not assumed + either way. + + SCOPE: this predicate exists ONLY because RG 431(a) below defers a MASS + question to it. Building it is not the Divine Office arriving in scope -- + CLAUDE.md's own "Divine Office remains out of scope" line, and the + 2026-08-21 design spec's own SS1, are both unchanged: this borrows ONE + Breviary FACT per day (whether Te Deum was said at Matins), never models + Matins/Vespers/the psalter/concurrence. *) +let te_deum ~(temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) + ~(observed : Vocab_ef.rank Celebration.t) ~(date : Date.t) : bool = + let easter = Computus.gregorian_easter (Date.year date) in + let n = Date.to_rata date - Date.to_rata easter in + let m = Date.month date and dd = Date.day date in + let slug = Slug.to_string observed.Celebration.slug in + if + (* 238(d): "in Officio defunctorum" -- checked first, the same position + and the same {!Colour.Black} proxy [creed]'s own 476(f) branch uses + (this file's own header has the full argument for why colour is a + sound proxy for "this is a Requiem" on the shipped data, and + {!test_colour_black_population_is_exactly_two} in test_rubrics_ef.ml + is the SAME two-member population this predicate also depends on -- + no separate test needed). *) + observed.Celebration.colour = Colour.Black + then false + else if + (* 237(a): the three explicitly named Paschaltide days -- Easter + Sunday's own Matins (n=0), Low Sunday (n=7), Pentecost Sunday + (n=49). Pure Easter-offset arithmetic, the same style [creed]'s own + 475(d) uses and for the identical reason: season/rank alone cannot + express "this exact day", and nothing else in 237/238 names these + three individually. + + HISTORY WORTH KEEPING: this task's own FIRST pass REPLACED this + branch (and 237(b) below) with a blanket "every Sunday" rule, + having found what looked like a clean 15-for-15 FIUV Ordo + contradiction of 237(b)'s own Septuagesima/Sexagesima/Quinquagesima + exception. That evidence was ITSELF corrupted: tools/extract_fiuv_ + ordo.ml's own Te Deum parser recognised only ONE of the source's two + negative phrasings ("non dicitur Te Deum"), so every "sine Te Deum" + occurrence -- which is how the source actually negates a SUNDAY's + own Te Deum, found only by reading the raw pdftotext dump by hand, + not by trusting the fixture's own coverage counts -- fell through to + a bare "Te Deum" substring match and was wrongly recorded [true]. + Fixed in the extractor (see its own citation, tools/extract_fiuv_ + ordo.ml); the fixture was regenerated; 24 of the fixture's 400 rows + flipped, EVERY ONE true->false, EVERY ONE a day this branch or + 237(b) below governs. The blanket rule was reverted the moment the + corrected data confirmed the ORIGINAL literal reading instead: + 238(a)'s own window DOES silence Advent/Septuagesima/Lent/ + Passiontide Sundays after all. Left as a worked example, not + scrubbed from history: the failure mode was believing a clean- + looking oracle correlation over re-deriving the primary text, + exactly backwards from what "adjudicate, don't assume" should have + produced -- caught only by cross-checking the raw source directly + once the shape looked suspiciously total. *) + n = 0 || n = 7 || n = 49 + then true + else if + (* 237(f): the vigils of Ascension (n=38) and Pentecost (n=48), checked + BEFORE 238(b)'s general vigil omission below -- both are otherwise + reachable by it (Ascension's vigil is [Class2], squarely inside + 238(b)'s own "II et III classis"; Pentecost's is [Class1], RG 91 + entry 9, so 238(b) could never have reached it regardless, but is + named here anyway rather than left to fall through to 237(c), the + same "cite the specific clause, not a catch-all" discipline this + whole module holds to). *) + n = 38 || n = 48 + then true + else if + (* 237(d): the three privileged octaves -- reuses [creed]'s own three + windows verbatim (that function's own 475(d) comment has the full + citation and the argument for why a season- or rank-based test + would wrongly include the Ascension/Pentecost-Vigil days this + window must exclude). Overlaps 237(a) at n=0/7/49 -- redundant, not + wrong, the same "never the FIRST branch to grant those [true]" + pattern 475(b) documents for I-class Sundays. *) + (m = 12 && dd >= 25 && dd <= 31) + || (m = 1 && dd = 1) + || (n >= 0 && n <= 7) + || (n >= 49 && n <= 56) + then true + else if + (* 238(b): "vigiliis II et III classis" -- {!Precedence_ef.is_omissible_vigil} + is exactly this rank test (Class2 or Class3), reused rather than + re-derived, paired with {!Precedence_ef.is_vigil} the same way + [creed]'s own RG 28-34 branch already pairs them. The Ascension + vigil (237(f) above, already [true]) can never reach this branch; + the four sanctoral vigils (StJohnBaptist, SsPeter&Paul, StLawrence, + the Assumption -- {!Precedence_ef.vigil_feast_table}'s own + population) are exactly what this branch excludes. *) + Precedence_ef.is_omissible_vigil observed.Celebration.rank && Precedence_ef.is_vigil slug + then false + else if + (* NOT 238(b)'s own text (which names only "II et III classis"): the + Nativity Vigil ([Class1], RG 91 entry 5) is excluded here on the + SAME RG 21/35 taxonomy argument [creed]'s own RG 28-34 comment + already makes for the Paschal Vigil -- "vigilia" is its own + liturgical-day category, distinct from "festum", regardless of + class; RG 30's "beyond losing" is a PRECEDENCE exemption (nothing + lesser can displace it), not a claim that a vigil IS a festum for + Breviary purposes. Flagged honestly as an INFERENCE, not a literal + 238(b) citation -- checked against the FIUV Ordo's own Te Deum + marker for 24 December in test_fiuv_ordo.ml, since this is exactly + the shape a transcription gap could get wrong either direction. *) + Precedence_ef.is_vigil slug + then false + else if + (* 238(c)/RG 23: Ash Wednesday and every feria of Holy Week, the Sacred + Triduum included -- reuses [creed]'s own RG 23 test verbatim (that + function's own comment has the full citation and the argument for + why this excludes feria I classis specifically, not ferias in + general). *) + n = -46 || (n >= -6 && n <= -1) + then false + else if + (* 237(b): "in dominicis II classis, exceptis dominicis in Septuagesima, + in Sexagesima et in Quinquagesima" -- colitur's own single + [Septuagesima] season covers exactly those three Sundays (see + [season_colour]'s own grouping, temporal_ef.ml), so the exception is + one season-equality test. RE-VERIFIED, not merely restored: the + corrected FIUV extraction (237(a)'s own comment above has the full + account) shows all three Septuagesima-season Sundays [false], and + every OTHER, ordinary Class2 Sunday the fixture's window reaches + [true] -- exactly this clause's own literal text, no correction + needed here after all. Reads [temporal.weekday]/[.season], not + [observed]'s slug: unlike [creed]'s own 475(a), the Breviary's text + carries NO "even when a feast displaces the Sunday's own Office" + exception -- when a feast genuinely takes the Sunday's place (RG + 16(a)), Matins says the FEAST's own Office, and 237(c) below decides + it on the feast's own terms, not this clause. Advent/Lent/ + Passiontide Sundays are [Class1], never [Class2] ([creed]'s own RG + 11-12 citation, temporal_ef.ml), so this guard correctly excludes + them without a separate season check; [observed.rank], not + [temporal]'s own season-derived rank, is read here on purpose, for + the same RG 16(a) reason [Precedence.rules.admit]'s own + [~temporal] parameter exists: a feast that wins the day can carry a + DIFFERENT rank than the Sunday it displaced. *) + temporal.Temporal.weekday = Date.Sun + && observed.Celebration.rank = Vocab_ef.Class2 + && temporal.Temporal.season <> Vocab_ef.Septuagesima + then true + else if + (* 237(g): the votive Office of the BVM on Saturday, RG 78/91 entry 27 + -- {!Temporal_ef}'s own [subject = Bvm]/[Class4] pairing, the same + shape [creed]'s own 476(d) comment and the register's RG 112(d) fix + already establish as unique to this office (every OTHER + [subject = Bvm] candidate in the shipped data is [Commemoration_only] + and can therefore never be [observed]). *) + observed.Celebration.subject = Subject.Bvm && observed.Celebration.rank = Vocab_ef.Class4 + then true + else if + (* 237(e): "Officio feriali temporis natalicii et temporis paschalis" -- + every remaining (non-octave, non-vigil, non-BVM-Saturday) FERIA of + Christmastide or Paschaltide: the 2-5 January ferias, and the + ordinary weeks of Paschaltide (Rogation Monday/Tuesday included). + [temporal.weekday <> Sun] keeps this to FERIAS only, matching the + clause's own "Officio FERIALI" text; a Sunday in either season is + already [true] via the Sunday rule above regardless, so this guard + changes no OUTCOME, only which clause gets credit for it. *) + (temporal.Temporal.season = Vocab_ef.Christmastide + || temporal.Temporal.season = Vocab_ef.Paschaltide) + && temporal.Temporal.weekday <> Date.Sun + then true + else + (* 237(c): "in omnibus festis" -- every remaining genuine festum. By + this point every named Paschaltide day, every ordinary Sunday + (Class2, outside Septuagesima), every vigil, every feria I classis, + every Christmastide/Paschaltide feria and every BVM Saturday Office + has already been excluded or granted above, so what reaches here is + exactly: {!Temporal_ef.named}'s remaining population + (Epiphany, Ascension, Corpus Christi, the Sacred Heart, Christ the + King -- tested by PRESENCE in that table, since every [named] entry + carries [subject = Temporal] like any other, see [creed]'s own + 475(c) comment); and every genuine sanctoral feast actually observed + ([subject = Saint], or one of the handful of [subject = Lord]/[Bvm] + entries -- Holy Family, Holy Name of Jesus, the six [Lord]-tagged + sanctoral feasts, [most-holy-name-of-mary] -- [creed]'s own 475(c) + comment has the full census). The two ferial exceptions that ALSO + carry [Lord]/[Bvm] (the Sacred Triduum, the BVM Saturday Office) are + unreachable here: both were already excluded above (feria I + classis; 237(g)). + + [Temporal_ef.named]'s FIRST disjunct EXCLUDES Passion Sunday and + Palm Sunday BY THEIR OWN SLUG -- not by [temporal.weekday <> Sun], + which a first pass of this fix tried and had to REVERT: Christ the + King is ALSO always a Sunday (its own [christ_the_king] anchor + IS "the last Sunday of October"), [Class1] like Passion/Palm + Sunday, so a blanket weekday guard wrongly excluded it too -- + caught immediately by the LMS Ordo's own Gloria axis + (2024-10-27, "colitur gloria=false, Ordo gloria=true"), a + regression a same-session review round found before this task + closed. Passion Sunday and Palm Sunday are excluded because + neither is a genuine "festum" (RG 35's own taxonomy makes + "dominica" its own category, distinct from "festum") -- {!Temporal_ + ef.named} carries them anyway (RG 91 entry 6, for its own + occurrence-table reasons), so without SOME exclusion both would + wrongly reach [true] here BY ACCIDENT of table membership -- + confirmed wrong directly against the corrected FIUV extraction + (237(a)'s own comment above has the full account of the extractor + bug this was found alongside): both dates are [false] in the + source. Epiphany, Ascension, Corpus Christi, the Sacred Heart and + Christ the King -- {!Temporal_ef.named}'s only OTHER population -- + are genuine festa and must NOT be excluded, which is exactly why + the exclusion is two named slugs, not a day-of-week predicate. The + SECOND disjunct (subject) carries no such guard: a genuine feast + that has fully displaced a Sunday's own Office (RG16(a)) still + deserves 237(c)'s grant on the FEAST's own terms, regardless of + what day of the week it falls on. + + A plain, unnamed weekday feria (no Sunday, no vigil, no octave, + [named] = [None], [subject = Temporal]) correctly falls through to + [false] here -- 238(c)'s own "in omnibus feriis". *) + (Temporal_ef.named date <> None && slug <> "ef-passion-sunday" && slug <> "ef-palm-sunday") + || observed.Celebration.subject = Subject.Saint + || observed.Celebration.subject = Subject.Lord + || observed.Celebration.subject = Subject.Bvm + +(* Missale Romanum, Rubricae Generales, Caput XVII("De Ritibus servandis in + celebratione Missae"), "C) De hymno Glória in excélsis" (docs/research/ + LT.txt, grep "Hymnus Glória"), quoted here in full: + + "431. Hymnus Gloria in excelsis dicitur: + a) in Missis quae respondent Officio diei, quotiescumque ad + Matutinum dictus est hymnus Te Deum; + b) in Missis festivis de quibus n. 302; + c) in Missis feriae V in Cena Domini, et in Missa Vigiliae + paschalis; + d) in Missis votivis I, II et III classis, nisi adhibeatur color + violaceus paramentorum; + e) in Missis votivis IV classis de Angelis, quocumque die, et de B. + Maria Virg. quae in sabbato celebrantur. + + 432. Hymnus Gloria in excelsis omittitur: + a) in Missis quae respondent Officio diei, quando ad Matutinum + omittitur hymnus Te Deum; + b) in omnibus Missis in quibus adhibetur color violaceus + paramentorum; + c) in Missis votivis IV classis, iis exceptis de quibus n. 431 e; + d) in Missis defunctorum." + + SCOPE NOTE, checked once here rather than at every clause, the same + discipline [creed]'s own header uses: this engine resolves ONE Mass per + civil day (Rite.t.readings' own doc comment) -- it has no separate + "which votive Mass is said" dimension. n. 301-303 (LT.txt, immediately + above 431), quoted in substance: 301 defines "Missa de festo" in the + NARROW sense as the Mass of the day's own Office -- exactly what + [Rite_ef.Lectionary_ef.readings] already resolves for every day, + including a BORROWED formulary (a weekday resuming the preceding + Sunday's Mass, a saint using his assigned Common): still "the Mass which + corresponds to the day's own Office" in 431(a)/432(a)'s own sense, so + 431(a)/432(a) alone already cover it. 302's WIDER sense -- (a) a + III-class feast's own Mass said despite being impeded by another + III-class feast, (b) a commemoration's own Mass said in place of the + day's Office, (c) a saint's Mass said on his Martyrology elogium day -- + are all cases of a DIFFERENT Mass than the day's own resolved Office + being said, which this engine does not model; 431(b) is therefore + genuinely N/A, not merely unread. 431(d)/(e) and 432(c) are about VOTIVE + MASS CLASSES (I-IV), a dimension this engine has no field for at all -- + also N/A, EXCEPT 431(e)'s own "de B. Maria Virg. quae in sabbato + celebrantur" half: colitur does not model that Office as a votive Mass + (it has no votive-Mass dimension to model it AS), it models it as an + ORDINARY Office (RG 78's own text, [te_deum]'s own 237(g) branch above), + so its Gloria is produced as a side effect of 431(a) reading [te_deum], + not by a dedicated 431(e) branch -- checked directly: [te_deum]'s 237(g) + branch is unconditional (not colour-gated), and this Office's own colour + is white (never violet), so 432(b) below can never suppress it either. + 431(e)'s "de Angelis" half (the votive Mass of the Angels) has no data + in this engine at all and stays N/A. *) +let gloria ~(temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) + ~(observed : Vocab_ef.rank Celebration.t) ~(date : Date.t) : bool = + let easter = Computus.gregorian_easter (Date.year date) in + let n = Date.to_rata date - Date.to_rata easter in + if + (* 432(d): "in Missis defunctorum" -- checked first, the same + {!Colour.Black} proxy [creed]'s own 476(f) and [te_deum]'s own + 238(d) branch both use. Correctly also excludes Good Friday + (n=-2, [Colour.Black], temporal_ef.ml's own RG 132 citation) -- + which has no Mass at all in the 1955-restored Holy Week, so the + question is moot there regardless; the same "belt and braces" + stance [creed]'s own 476(f) comment takes for the identical day. *) + observed.Celebration.colour = Colour.Black + then false + else if + (* 431(c): "in Missis feriae V in Cena Domini, et in Missa Vigiliae + paschalis" -- Holy Thursday (n=-3) and the Easter Vigil Mass (n=-1, + Holy Saturday's own date). Checked BEFORE 432(b)'s general violet + exclusion below and before [te_deum] is ever read: this clause is + lex specialis over both. It must outrank 432(b) specifically + because colitur's own per-day colour model gives Holy Saturday + [Colour.Violet] (Passiontide's [season_colour], temporal_ef.ml -- + the historical vestment change from violet to white happens AT the + Gloria itself, a per-action nuance this whole day/colour model + already cannot express, the same acknowledged gap RG 126's palm + procession and RG 128's Good Friday Communion carry, temporal_ef.ml's + own citations) -- without this clause checked first, 432(b) would + wrongly silence the one Mass whose own Gloria is historically + unmistakable (the bells and organ restored at the Vigil). It must + also outrank [te_deum]: neither day's own Matins says Te Deum + (both are governed by [te_deum]'s own feria-I-classis exclusion, + n=-46/[-6,-1], the Sacred Triduum included), so without this + explicit override the Gloria would be wrongly silenced there too. *) + n = -3 || n = -1 + then true + else if + (* 432(b): "in omnibus Missis in quibus adhibetur color violaceus + paramentorum" -- independent and colour-keyed, exactly as the task + brief states; NOT a substitute for [te_deum] below, which still + decides every Mass this clause does not itself silence. Genuinely + unconditional ("in omnibus Missis") -- checked directly against + every violet day in the domain-wide sweep (see the module's own + test file), never merely assumed. + + [Colour.Rose] found and DELIBERATELY NOT added here, a real + "checked, then reverted" episode kept for the record: a first pass + of this task, WHILE the (since-reverted) blanket "every Sunday + says Te Deum" mutation to [te_deum] was in place, found Gaudete + and Laetare ([is_rose_sunday]) wrongly getting [gloria]=true and + fixed it by unioning [Colour.Rose] into this branch. Once + [te_deum] reverted to 237(b)'s own literal [Class2] guard, the + fix became REDUNDANT, not merely coincidentally silent: Rose can + ONLY ever colour a Sunday of Advent or Lent + ({!Temporal_ef.is_rose_sunday}'s own two cases), and EVERY Sunday + of Advent or Lent is [Class1] BY CONSTRUCTION + ({!Temporal_ef.temporal}'s own [match s with Advent | Lent -> + Class1 | _ -> Class2]) -- a structural guarantee, not a + coincidence of the shipped data, so [te_deum]'s own [Class2] guard + ALREADY excludes every Rose day before this branch is ever + reached. Verified, not assumed: removing this branch's own Rose + arm and re-running the full suite (including the two LMS dates, + 2023-12-17 and 2024-03-10, this finding was originally pinned + against) left every test green. Left out rather than kept as + dead code that would misleadingly read as load-bearing. *) + observed.Celebration.colour = Colour.Violet + then false + else + (* 431(a)/432(a): "in Missis quae respondent Officio diei, + quotiescumque/quando... Te Deum [dictus est/omittitur]" -- the + Gloria mirrors [te_deum] exactly for every Mass not already decided + above. This is the ONE call site [te_deum] exists to serve. *) + te_deum ~temporal ~observed ~date + +(* Missale Romanum, Rubricae Generales, Caput XVII, "H) De praefatione" (RG + 482-499; docs/research/LT.txt, grep "praefatione dicitur quae cuique"), + quoted here in full so every branch below can cite its own paragraph + without re-quoting the whole rubric: + + "482. Praefatio dicitur quae cuique Missae propria est; qua deficiente, + dicitur praefatio de Tempore, secus communis. + + 483. Nulla commemoratio, in Missa occurrens, praefationem propriam + inducit. + + 484. Praefatio de Nativitate Domini dicitur: + a) tamquam propria in Missis de Nativitate Domini et de eiusdem + octava, necnon in festo Purificationis B. Mariae Virg.; + b) tamquam de Tempore, infra octavam Nativitatis Domini, etiam in + Missis quae secus praefationem propriam haberent, exceptis iis Missis + quae praefationem propriam de divinis mysteriis vel Personis habent; et + a die 2 ad 5 ianuarii. + + 485. Praefatio de Epiphania Domini dicitur: + a) tamquam propria in Missis de festo Epiphaniae et de + Commemoratione Baptismatis D. N. Iesu Christi; + b) tamquam de Tempore diebus a 7 ad 13 ianuarii. + + 486. Praefatio de Quadragesima dicitur: + a) tamquam propria in Missis de Tempore a feria IV cinerum usque ad + sabbatum ante dominicam I Passionis; + b) tamquam de Tempore in ceteris Missis quae celebrantur eodem + tempore, et praefatione propria carent. + + 487. Praefatio de sancta Cruce dicitur: + a) tamquam propria in Missis de tempore a dominica I Passionis usque + ad feriam V in Cena Domini; in Missis tam festivis quam votivis de + sancta Cruce, de Passione Domini et instrumentis Passionis Domini, de + pretiosissimo Sanguine D. N. Iesu Christi, de Ss.mo Redemptore; + b) tamquam de Tempore in omnibus Missis a dominica I Passionis usque + ad feriam IV Hebdomadae sanctae, quae praefatione propria carent. + + 488. Praefatio de Missa chrismatis dicitur feria V in Cena Domini, in + sua Missa. + + 489. Praefatio paschalis dicitur: + a) tamquam propria in Missis de Tempore a Missa Vigiliae paschalis + usque ad vigiliam Ascensionis Domini; + b) tamquam de Tempore in ceteris Missis quae celebrantur eodem + tempore, et praefatione propria carent. + + 490. Praefatio de Ascensione Domini dicitur: + a) tamquam propria in festo Ascensionis Domini; + b) tamquam de Tempore in omnibus Missis a feria VI post Ascensionem + usque ad feriam VI ante vigiliam Pentecostes, quae praefatione propria + carent. + + 491. Praefatio de Ss.mo Corde Iesu dicitur in Missis festivis et + votivis de Ss.mo Corde Iesu. + + 492. Praefatio de D. N. Iesu Christo Rege dicitur in Missis festivis + et votivis de D. N. Iesu Christo Rege. + + 493. Praefatio de Spiritu Sancto dicitur: + a) tamquam propria in Missis de Tempore a vigilia Pentecostes usque + ad subsequens sabbatum; et in Missis festivis et votivis de Spiritu + Sancto; + b) tamquam de Tempore in ceteris Missis quae celebrantur eodem + tempore, et praefatione propria carent. + + 494. Praefatio de Ss.ma Trinitate dicitur: + a) tamquam propria in Missis de festo et votivis Ss.mae Trinitatis; + b) tamquam de Tempore in dominicis Adventus, et in omnibus dominicis + II classis, extra tempus natalicium et paschale. + + 495. Praefatio de beata Maria Virgine dicitur in Missis festivis et + votivis beatae Mariae Virginis, praeterquam in festo Purificationis B. + Mariae Virg. + + 496. Praefatio de S. Ioseph dicitur in Missis festivis et votivis S. + Ioseph. + + 497. Praefatio de Apostolis dicitur in Missis festivis et votivis + Apostolorum et Evangelistarum. + + 498. Praefatio communis dicitur in Missis quae praefatione propria + carent, nec sumere debent praefationem de Tempore. + + 499. Praefatio defunctorum dicitur in Missis defunctorum." + + THE SHAPE OF THE RULE, once, rather than at every branch: RG 482's own + chain is "propria, else de Tempore, else communis". Read literally, 484- + 497 look like FOURTEEN SEPARATE RULES, but on inspection each numbered + rubric's own (a)/(b) pair (where it has both) produces the SAME preface + identity either way -- (a) is the propria reading ("this Mass's OWN + preface"), (b) is the de-Tempore reading ("this OTHER Mass, lacking one + of its own, borrows it") -- so for the single question this function + answers (WHICH preface, not WHETHER it counts as propria or de Tempore + for some other purpose) the two halves collapse into one PRIORITY- + ORDERED decision: a fixed list of "genuinely proper" triggers (title/ + mystery feasts, independent of season), checked first in a citable + order, falling through to a fixed list of SEASONAL windows, falling + through to [Common]. RG 483 (a commemoration never induces a proper) + holds by construction, the same way [creed]'s own 476(e) does: every + branch below reads only [observed], never a day's admitted + commemorations. + + THE PRIORITY ORDER ITSELF was cross-checked against 358 real, + individually classifiable entries in the FIUV Ordo's own [praef] column + (test/fixtures/fiuv-ordo-2025-2026.sexp, test_fiuv_ordo.ml) spanning the + WHOLE liturgical year -- not merely derived from the Latin text in + isolation. Two findings the plain text alone would not have settled, + both empirically confirmed rather than assumed: + + - 484(b)'s own "exceptis iis Missis quae praefationem propriam de + divinis mysteriis vel Personis habent" is NARROWER than every other + window's implicit "unless it already has a genuine proper" -- St + John the Evangelist (27 December, on {!creed_apostle_slugs}, so his + OWN Apostles preface (497) would otherwise apply) is overridden to + [Nativity] inside the octave (confirmed: the Ordo's own 27 December + entry reads "de Nativ.", not "App."), while St Barnabas/Sts Philip & + James/the other Apostles OUTSIDE the octave keep their own Apostles + preface even inside another window (Sts Philip & James, 11 May, + inside the Easter window: confirmed "App." in the Ordo, not + "Pasch."). So [Apostles] is checked AFTER the Nativity window below, + but every OTHER title trigger (Holy Cross/Sacred Heart/Christ the + King/Trinity/St Joseph/BVM) is checked BEFORE it -- RG 484(b)'s own + narrower carve-out, read literally: unreachable on the shipped + calendar for the other five (no such feast falls 25 December-5 + January), so this ordering is defensive for them, not observed live, + the same "checked, not merely assumed" discipline + {!Precedence_ef.marian_slugs}'s own citation follows elsewhere. + - RG 495's own "et votivis" half is live on this engine's data after + all, for the ONE office this project already models as a votive- + shaped Mass without a votive-Mass DIMENSION (RG 78/91 entry 27, the + Saturday Office of the BVM, {!Temporal_ef}'s own [subject = Bvm] + tag): confirmed directly (3 January and 10 January 2026, both the + Saturday Office, both read "BMV" in the Ordo) -- including on 3 + January, itself inside the Nativity's own "2 ad 5 ianuarii" de- + Tempore window, where BVM still wins, corroborating the same + "genuine propria outranks every window" ordering the Apostles + finding above established from the opposite direction. + + Good Friday's own printed [praef] text ("comm. Feria VI prima in + mense.") was NOT used to check this function's own [None] answer for + that day: {!test_fiuv_ordo.ml}'s own F1 (Gloria) already adjudicated + this exact date's raw text as unreliable (a copied, not a considered, + line -- see that allow-list entry's own citation for the full argument, + confirmed against the PDF's own page image, not merely the extracted + fixture) -- the same defect, read again, would apply equally to + whatever trails "praef." on the identical corrupted line, so this + function's [None] rests on RG 28's own "no Mass" structural argument + alone (the same argument [creed]/[gloria]/[te_deum] already give for + this date), not on any Ordo corroboration. *) + +(* RG 487(a): the two GENUINE fixed-date feast triggers in the shipped + universal calendar -- the Exaltation of the Holy Cross (14 September) + and the Most Precious Blood (1 July), both [subject = Lord]. RG 487(a)'s + own further-named categories ("de Passione Domini et instrumentis + Passionis Domini, de Ss.mo Redemptore") have NO corresponding entry + anywhere in data/ef/sanctoral.sexp (checked directly, grepping for + "instrument"/"redeem": zero hits) -- genuinely absent from the shipped + 1962 universal calendar, not merely unmatched by this list, so they are + N/A rather than silently unreachable. *) +let preface_holy_cross_slugs = + [ "exaltation-of-the-holy-cross"; "precious-blood-of-our-lord-jesus-christ" ] + +(* RG 496: the two St Joseph feasts in the shipped calendar (19 March, 1 + May) -- both [subject = Saint], so (unlike RG 495's own BVM feasts) no + [subject]-based fallback exists or is needed; this closed list is the + whole of what RG 496 can ever reach on shipped data. *) +let preface_st_joseph_slugs = [ "joseph-spouse-of-the-bl-virgin-mary"; "joseph-the-workman" ] + +(* RG 497's own [Apostolorum et Evangelistarum] population is WIDER than + {!creed_apostle_slugs}: RG 475(e) is restricted to a NATALICIUM ("festis + NATALICIIS Apostolorum...", that module's own citation), but RG 497 has + no such restriction at all ("in Missis festivis et votivis Apostolorum + et Evangelistarum" -- ANY festive/votive Mass of an Apostle or + Evangelist). FOUND, not assumed: the FIUV Ordo's own 30 June entry + ("In Commemoratione S. Pauli Ap.", data/ef/adjustments.sexp's own RG + 110(c) [Add], {!Precedence_ef}'s own citation -- a genuine [Feast]- + status office of Paul the Apostle, but NOT his own dies natalis, so + {!creed_apostle_slugs} deliberately excludes it) reads "App. I", not + "comm." -- checked directly while building this comparison, not + guessed. [creed_apostle_slugs] itself is UNCHANGED (RG 475(e)'s own + narrower "natalicium" reading still holds for the Creed); this is a + SEPARATE, wider list for RG 497 alone. + + "conversion-of-st-paul" (25 January, Class3, the SAME "not a + natalicium" shape {!creed_apostle_slugs}'s own citation excludes it + for) is a SECOND member, by the identical RG 497 reasoning -- + NOW WITNESSED (Preface-witnesses task, 2026-08-23): unlike + {!test_fiuv_ordo.ml}'s own single-year window (where 25 January falls + on a Sunday, hence impeded), the Latin Mass Society Ordo's own THREE + editions (test/test_lms_ordo.ml) each carry an UNIMPEDED 25 January -- + two of them fall outside a Sunday (2024, 2025) and both read "Pr of + the Apostles" for the Conversion of St Paul, confirmed directly + against two INDEPENDENT civil years, not merely two printings of the + same one (the third, 2026, is impeded by a Sunday exactly like FIUV's + own witness year -- the same date, the same reason, an entirely + different underlying calendar fact confirmed twice over, not a + coincidence). Added on this evidence. + + A FOURTH and FIFTH informal confirmation, from a SECOND, independent + publisher (extraordinaryform.org's own three annual PDFs, + docs/research/ordo/2024-2025Ordo.pdf / 2025-2026Ordo.pdf / + 2026-2027Ordo.pdf -- characterised, not wired in as an automated layer; + see the Preface-witnesses task's own report for why): its own per-day + PREFACE table column reads "Apostles" for the Conversion of St Paul on + BOTH of its own unimpeded years, 2025-01-25 and 2027-01-25 (its middle + edition's 2026-01-25 is impeded by a Sunday, the identical fact the + other two sources already independently establish) -- a spot check, + not a fixture, but a real cross-publisher agreement on the exact + question this list answers. + + SURVEYED, not merely patched: every other Apostle/Evangelist-named + slug in data/ef/sanctoral.sexp was checked against this same + three-edition LMS witness before deciding this list needed exactly + one addition, not more: + - "dedication-of-the-basilicas-of-sts-peter-paul" (18 November, + Class3) is Peter and Paul's own BASILICAS, not the Apostles + themselves -- confirmed NOT an RG 497 trigger in all three LMS + editions, identical across all three ("Pr of the Dedication of a + Church or Common Pr"), corroborating {!preface_bvm_slugs}'s own + "Dedication of a Church" finding rather than RG 497: this feast's + own subject is the building, governed by the SAME non-RG-482 + "extra" preface every other church dedication uses (RG 91 entry + 27's own header has the fuller account of this Ordo's option-list + shape). + - "vigil-of-sts-peter-paul" (28 June) reads "Common Pr" in the LMS + Ordo (2024-2025 edition, checked directly) -- confirming, not + merely assuming, this branch's own long-standing "no [is_vigil] + guard needed, no entry here is ever a vigil slug" comment below: + a vigil is not a "festum... votiva" either, the identical RG 21/35 + taxonomy {!preface_bvm_slugs}'s own [is_vigil] guard already + states for the BVM branch above. + - No other Peter/Paul/John/Andrew/James/Philip/Bartholomew/Thomas/ + Matthew/Jude/Simon/Matthias/Mark/Luke/Barnabas-named slug in the + shipped data names an Apostle or Evangelist at all (checked by + grepping every slug in data/ef/sanctoral.sexp against those ten + names): the rest are unrelated same-named saints (e.g. "mark-i", a + Pope, {!creed_apostle_slugs}'s own citation; "sts-john-paul", two + Roman martyrs unrelated to the Evangelist and the Apostle) or + genuinely unreachable RG 110 companions ("peter"/"paul", + [Commemoration_only], {!creed_apostle_slugs}'s own citation). *) +let preface_apostle_slugs = + "in-commemoratione-sancti-pauli-apostoli" :: "conversion-of-st-paul" :: creed_apostle_slugs + +(* RG 495's own [beatae Mariae Virginis] population is also WIDER than + {!Precedence_ef.marian_slugs}: that list was built for a DIFFERENT + rubric (RG 112(d), whether a commemoration invokes HER OWN + intercession specifically) with a correspondingly narrower, oration- + checked standard, and its own citation explicitly EXCLUDES "dedication- + of-the-basilica-of-st-mary-major" (5 August) for exactly that reason -- + "whose own oration could not be found... to confirm it invokes her + intercession". RG 495 asks a different, WIDER question ("is this Mass + festive or votive OF the Blessed Virgin Mary at all"), which the + Dedication of St Mary Major answers on its own title alone, without + needing the oration-level standard RG 112(d) requires. FOUND, not + assumed: the FIUV Ordo's own 5 August entry reads "BMV Et te in + Festivitate.", not "comm." -- checked directly. *) +let preface_bvm_slugs = "dedication-of-the-basilica-of-st-mary-major" :: Precedence_ef.marian_slugs + +let preface ~(temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) + ~(observed : Vocab_ef.rank Celebration.t) ~(date : Date.t) : Preface.t option = + let easter = Computus.gregorian_easter (Date.year date) in + let n = Date.to_rata date - Date.to_rata easter in + let m = Date.month date and dd = Date.day date in + let slug = Slug.to_string observed.Celebration.slug in + if + (* RG 28-34/RG 23(b), the same structural "no Mass at all" position + [creed]'s own vigil comment and [gloria]'s own 432(d) comment both + take for Good Friday specifically: the 1955-restored Holy Week has + no Mass whatsoever that day (only the afternoon liturgical action), + so there is no Mass to preface. Checked ahead of the + {!Colour.Black} Requiem proxy immediately below -- unlike All + Souls, Good Friday sharing that colour is coincidental, not + diagnostic (temporal_ef.ml's own RG 132 citation), and the two need + DIFFERENT answers here (unlike [creed]/[gloria]/[te_deum], where + both collapse to the same boolean) -- so this function cannot reuse + their shared single guard and must split Good Friday out first. *) + n = -2 + then None + else if + (* RG 499: "in Missis defunctorum" -- the same {!Colour.Black} proxy + [creed]'s own 476(f), [te_deum]'s own 238(d) and [gloria]'s own + 432(d) already use (this file's own header has the full argument + and the two-member population this proxy rests on). With Good + Friday split out above, the one remaining member is All Souls. *) + observed.Celebration.colour = Colour.Black + then Some Preface.Requiem + else if + (* RG 487(a)'s own fixed-feast half -- checked first among the title + triggers per this file's own header (arbitrary among these six, + since none can ever co-occur with another on shipped data; Holy + Cross is placed first only because it is also the anchor for the + Passiontide WINDOW checked later below, keeping both citations + adjacent in this file). *) + List.mem slug preface_holy_cross_slugs + then Some Preface.Holy_cross + else if + (* RG 491: "in Missis festivis... de Ss.mo Corde Iesu" -- the Friday + after the Octave of Corpus Christi (Easter+68), {!Temporal_ef}'s own + named slug. Confirmed against the Ordo (12 June 2026: "de Ss.mi + Corde Iesu"). *) + slug = "ef-sacred-heart" + then Some Preface.Sacred_heart + else if + (* RG 492: "in Missis festivis... de D. N. Iesu Christo Rege" -- the + last Sunday of October, {!Temporal_ef.christ_the_king}'s own named + slug. Confirmed against the Ordo (25 October 2026: "de Domino + Nostro Jesu Rege"). *) + slug = "ef-christ-the-king" + then Some Preface.Christ_the_king + else if + (* RG 490(a): "in festo Ascensionis Domini" -- the feast itself + (Easter+39), checked here by slug rather than folded into the + Ascension WINDOW below (which starts the day AFTER, Easter+40): + Ascension Day itself needs no window at all, its own slug already + identifies it uniquely. Confirmed against the Ordo (14 May 2026: + "Ascensionis, Communic pr."). *) + slug = "ef-ascension" + then Some Preface.Ascension + else if + (* RG 494(a): "in Missis de festo... Ss.mae Trinitatis" -- Trinity + Sunday itself (Easter+56), {!Temporal_ef}'s own named slug. Checked + ahead of 494(b)'s own WIDER de-Tempore grant (checked last below, + after every other window) for the same "specific propria before any + season fallback" reason every other title trigger is. Confirmed + against the Ordo (31 May 2026: "Trinit. II"). *) + slug = "ef-trinity" + then Some Preface.Trinity + else if + (* RG 496: see {!preface_st_joseph_slugs}'s own citation. *) + List.mem slug preface_st_joseph_slugs + then Some Preface.St_joseph + else if + (* RG 495: "in Missis festivis et votivis beatae Mariae Virginis" -- + {!preface_bvm_slugs} (its own citation has the full account of why + it is wider than {!Precedence_ef.marian_slugs}) covers every + genuine Marian FEAST; [subject = Bvm] covers the one VOTIVE-shaped + office this engine models without a votive-Mass dimension of its + own (RG 78/91 entry 27, the Saturday Office of the BVM -- this + file's own header has the empirical confirmation, 3/10 January + 2026). The Purification is deliberately ABSENT from both: + {!Precedence_ef.marian_slugs} already excludes it by name (its own + citation), and it never carries [subject = Bvm] (tagged [Lord] + instead, register §6.0) -- RG 495's own "praeterquam in festo + Purificationis" exclusion therefore holds by construction, not by + a guard written here. + + [not (is_vigil slug)]: RG 495's own "festivis" reads "festum", not + "vigilia" -- the SAME RG 21/35 taxonomy distinction {!creed}'s own + RG 28-34 comment already makes ("a vigil is its OWN liturgical-day + category, distinct from 'festum'"), applied here for the first + time in THIS function because it is the first branch a vigil can + actually reach: {!Precedence_ef.marian_slugs} includes + "vigil-of-the-assumption" (that list's own citation), which without + this guard would wrongly claim [Bvm] for 14 August. FOUND, not + assumed: the FIUV Ordo's own 14 August entry reads "comm. I", not + "BMV" -- checked directly, the same as every other finding in this + branch's own history. Corroborates, from the opposite direction, + {!creed}'s own RG 28-34 comment: colitur's own Nativity WINDOW + below already excludes 24 December (the Nativity Vigil) by + construction (it starts at 25 December, never 24th), so this guard + makes the SAME "a vigil is not a festum" answer explicit here too, + rather than relying on a second, unrelated accident of a date + range to produce it. *) + (not (Precedence_ef.is_vigil slug)) + && (List.mem slug preface_bvm_slugs || observed.Celebration.subject = Subject.Bvm) + then Some Preface.Bvm + else if + (* RG 484(a)'s own explicit Purification clause ("necnon in festo + Purificationis B. Mariae Virg.") -- 2 February, nowhere near the + Nativity's own Christmas-to-Epiphany calendar position, so this is + a standalone slug check, not part of the WINDOW test below (unlike + every other 484 trigger, which IS date-based). Checked here, after + the BVM check immediately above (which the Purification's own + [subject = Lord] tag never reaches) and before the Nativity window + (which its own actual date, 2 February, never reaches either) -- + positioned with the rest of 484's own citations for readability, + not because anything below could otherwise pre-empt it. *) + slug = "purification-of-the-blessed-virgin-mary" + then Some Preface.Nativity + else if + (* RG 484(a)/(b) merged, per this file's own header: 25 December-1 + January (the Nativity itself and its octave, propria) UNION 2-5 + January (498(b)'s own explicit extra de-Tempore days) -- one + contiguous window, since both halves produce the identical + preface. Checked BEFORE Apostles (below) but AFTER every genuine + "divine mysteries/Persons" propria above, per this file's own + header (St John the Evangelist, 27 December, is the live witness: + Apostles would otherwise apply and does not). *) + (m = 12 && dd >= 25) || (m = 1 && dd <= 5) + then Some Preface.Nativity + else if + (* RG 497: "in Missis festivis et votivis Apostolorum et + Evangelistarum" -- {!preface_apostle_slugs} (its own citation has + the full account of why it is wider than {!creed_apostle_slugs}), + confirmed by this file's own header to produce the SAME preface + answer as the Ordo on every Apostle date outside the Nativity + octave: 11 June (Barnabas), 29-30 June (Peter & Paul, In + Commemoratione Pauli), 11 May (Philip & James, RG 484(b)'s own + witness against the Nativity window immediately above). Checked + AFTER the Nativity window specifically (RG 484(b)'s own narrower + carve-out), but before every OTHER season window below -- an + Apostle feast keeps his own preface inside Lent, Passiontide, + Paschaltide etc., where nothing narrows the exception the way + 484(b) does. No [is_vigil] guard is needed here the way RG 495's + own branch above needs one: checked directly, no entry on + {!preface_apostle_slugs} is ever a vigil slug (every Apostle vigil + in the shipped data -- "vigil-of-sts-peter-paul" -- carries its own + distinct slug, absent from this list). *) + List.mem slug preface_apostle_slugs + then Some Preface.Apostles + else if + (* RG 485(a): "in Missis de festo Epiphaniae et de Commemoratione + Baptismatis D. N. Iesu Christi" -- the feast itself and its own + named commemoration (13 January, {!Precedence_ef}'s own + "commemoration-of-the-baptism-of-the-lord" -- {!creed}'s own 475(c) + comment already documents this entry's [subject = Lord] tag), both + checked by slug so 485(b)'s own WIDER window below need not repeat + them. *) + slug = "ef-epiphany" || slug = "commemoration-of-the-baptism-of-the-lord" + then Some Preface.Epiphany + else if + (* RG 485(b): "diebus a 7 ad 13 ianuarii" -- every OTHER Mass in this + window (Holy Family Sunday, an ordinary Time-after-Epiphany feria + or Sunday, a saint's feast with no propria of its own), confirmed + against the Ordo's own 11 January 2026 entry (Holy Family Sunday: + "de Epiphania. II", not a Holy-Family-specific preface -- this + engine has none to offer it anyway). Colitur's own Christmastide + season already spans 25 December-13 January (RG 72-73, + {!Vocab_ef.season}'s own citation), so this window is exactly its + OWN post-Epiphany tail; written as an explicit date range rather + than a season test only because the Nativity window above already + claims the season's FIRST half by date, not by season either, for + symmetry. *) + m = 1 && dd >= 6 && dd <= 13 + then Some Preface.Epiphany + else if + (* RG 486(a)/(b) merged: Ash Wednesday (Easter-46) through the + Saturday before Passion Sunday I (Easter-15) inclusive -- every + Lenten feria/Sunday's own Mass (a), and every OTHER Mass in the + same span lacking a proper of its own (b). Confirmed against the + Ordo throughout (e.g. 18 February/19-20 February 2026: "Quadr."). + {!creed}'s own RG 23 comment already explains why Ash Wednesday + (feria I classis) reaches this branch on [observed]'s own terms + regardless of rank -- this function reads no rank at all here, + only the date. *) + n >= -46 && n <= -15 + then Some Preface.Lent + else if + (* RG 487(a)/(b) merged: Passion Sunday I (Easter-14) through Holy + Thursday (Easter-3) inclusive -- (a)'s own "de tempore"/festive- + votive half extends through Holy Thursday itself (the Mass of the + Lord's Supper), (b)'s own narrower saint-Mass half stops one day + earlier (Holy Wednesday) but reaches no LIVE day this check does + not already cover identically (Holy Thursday is a feria I classis, + RG 23(b), so no saint's feast can ever occupy it -- {!creed}'s own + RG 23 citation). Confirmed against the Ordo throughout (22 March + 2026, Passion Sunday: "de Sancta Cruce."; 2 April 2026, Holy + Thursday: "de Sancta Cruce, Communicantes..."). *) + n >= -14 && n <= -3 + then Some Preface.Holy_cross + else if + (* RG 489(a)/(b) merged: the Easter Vigil Mass (Easter-1, on Holy + Saturday's own date) through the vigil of the Ascension (Easter+38) + inclusive. [n = -1] is this engine's own OVERLOADED representation + of "the Vigil Mass", not Holy Saturday's daytime (which has no Mass + of its own at all, unlike Good Friday's [n = -2] this function + excludes by name above) -- [gloria]'s own RG 431(c) comment already + establishes the same convention for the identical date, and RG + 489(a) resolves the question on its own terms regardless: the + Paschal preface's window STARTS at the Vigil Mass, so [n = -1] is + correctly [Easter]. Confirmed against the Ordo throughout (5 April + 2026, Easter Sunday: "Pasch."; 13 May 2026, the Ascension Vigil: + "Pasch. I"); the fixture prints nothing at all for Holy Saturday's + own daytime square (4 April 2026), corroborating rather than + contradicting this reading -- see test_fiuv_ordo.ml's own citation. *) + n >= -1 && n <= 38 + then Some Preface.Easter + else if + (* RG 490(b): "a feria VI post Ascensionem usque ad feriam VI ante + vigiliam Pentecostes" -- the Friday after Ascension (Easter+40) + through the Friday before the Pentecost vigil (Easter+47) + inclusive; Ascension Day itself (Easter+39) is already handled by + its own slug check above, not repeated here. Confirmed against the + Ordo throughout (15-22 May 2026: "Ascensionis"). *) + n >= 40 && n <= 47 + then Some Preface.Ascension + else if + (* RG 493(a)/(b) merged: the vigil of Pentecost (Easter+48) through + "subsequens sabbatum" (the FOLLOWING Saturday, i.e. the Ember + Saturday within the Octave of Pentecost, Easter+55) inclusive. + Confirmed against the Ordo throughout (23-24 May 2026, the vigil + and Pentecost itself: "de Spirito Sancto"; 30 May 2026, the Ember + Saturday: "de Spirito Sancto"). *) + n >= 48 && n <= 55 + then Some Preface.Holy_spirit + else if + (* RG 494(b): "in dominicis Adventus, et in omnibus dominicis II + classis, extra tempus natalicium et paschale". Read off + [temporal]'s own season, NOT [observed]'s rank -- CORRECTED from an + earlier version of this branch that DID read [observed.rank] and + required it to equal [Class2], which is wrong for the identical RG + 16(a) reason {!Precedence.rules.admit}'s own [~temporal] parameter + exists and [creed]'s own 237(b)/475(a) comments already give: a + feast that has WON the day can carry a different rank than the + Sunday it stands on. FOUND, not assumed: All Saints' Day (1 + November), Class1, observed outright over an ordinary + Time-after-Pentecost Sunday it commemorates + ([+ef-time-after-pentecost-sunday-23]), reads "Trinit." in the + Ordo -- [observed.rank] there is [Class1], so the OLD guard wrongly + answered [Common]; there is no dedicated preface for All Saints + among RG 484-497's own fourteen, so RG 482's chain correctly falls + through to the SUNDAY's own de-Tempore grant regardless of which + rank actually won the day. + + {!Temporal_ef.temporal}'s own [match s with Advent | Lent -> Class1 + | _ -> Class2] means EVERY Sunday's own TEMPORAL identity is + [Class2] except in Advent and Lent -- so "in omnibus dominicis II + classis" and "in dominicis Adventus" collapse into ONE test, "any + Sunday outside Christmastide and Paschaltide" (Lent's own Sundays + need no explicit exclusion here: {!creed}'s own RG 23/Lent-window + reasoning already means every one of them is claimed by the LENT + window earlier in this very priority chain, provably unreachable + here, the same "checked, not merely assumed" position the previous + version of this comment already took for Christmastide/Paschaltide + -- confirmed by the SAME domain sweep in test_rubrics_ef.ml, which + still finds zero Christmastide/Paschaltide/Lent days reaching this + branch after this change). Confirmed against the Ordo throughout + (e.g. every Advent/Time-after-Epiphany/Septuagesima/Time-after- + Pentecost Sunday not otherwise claimed: "Trinit."), now including + All Saints' Day itself. *) + temporal.Temporal.weekday = Date.Sun + && temporal.Temporal.season <> Vocab_ef.Christmastide + && temporal.Temporal.season <> Vocab_ef.Paschaltide + then Some Preface.Trinity + else + (* RG 498: "in Missis quae praefatione propria carent, nec sumere + debent praefationem de Tempore" -- everything else: an ordinary + weekday feria outside every window above, a plain sanctoral saint + with no title of his own, an ordinary (non-Sunday, non-Class2, or + Christmastide/Paschaltide) day. Confirmed against the Ordo + throughout (the single most common value in the fixture, 188 of + 360 comparable rows). *) + Some Preface.Common diff --git a/lib/rites/rite_ef/rubrics_ef.mli b/lib/rites/rite_ef/rubrics_ef.mli new file mode 100644 index 0000000..c005aaf --- /dev/null +++ b/lib/rites/rite_ef/rubrics_ef.mli @@ -0,0 +1,107 @@ +(** RG 475-476 (docs/research/LT.txt, grep "dicitur symbolum") -- whether the + Creed is said at Mass. The first rubric in this phase governing a PART OF + MASS rather than occurrence/precedence, hence its own module: see the + .ml's own header for the rubric quoted in full and every branch's + citation. *) + +open Colitur_kernel + +(** RG 475(e)'s "festis nataliciis Apostolorum et Evangelistarum, necnon in + festis Cathedrae S. Petri et S. Barnabae Ap." -- see the .ml's own + citation for how each entry was derived from and verified against + data/ef/sanctoral.sexp, and for what was deliberately excluded. Exposed + so the test suite can assert completeness against the shipped data the + same way {!Precedence_ef.vigil_feast_table} already lets it. *) +val creed_apostle_slugs : string list + +(** Whether the Creed is said, post-Gospel/homily, at the Mass this day + resolves to. + + [temporal] is read for exactly one fact -- RG 475(a)'s own "in qualibet + dominica, ETSI EIUS OFFICIUM ALICUI FESTO LOCUM CEDAT" ("on any Sunday, + EVEN WHEN a feast displaces its own Office"): a Sunday impeded by a + Feast of the Lord (RG 16(a)) still says the Creed, so this reads the + TEMPORAL cycle's own weekday, never [observed]'s. Every other clause + reads [observed] -- the celebration whose Mass is actually said -- and + [date], read once against the rite's own (Gregorian) Easter for the two + Easter-relative window questions (RG 475(d)'s three octaves, RG 23's + Ash-Wednesday-and-Holy-Week feriae). [creed] never reads + {!Liturgical_day.t.commemorations}: RG 476(e), "ratione alicuius + commemorationis in Missa occurrentis" [never say the Creed merely + because of a commemoration], holds by construction rather than by a + checked branch. RG 476(f) ("in Missis defunctorum") reads + [observed]'s [colour]: see the .ml's own header for why [Colour.Black] + is a sound proxy for "this Mass is a Requiem" on the shipped data, and + what would have to be re-checked if that ever stops being true. *) +val creed : + temporal:(Vocab_ef.season, Vocab_ef.rank) Temporal.t -> + observed:Vocab_ef.rank Celebration.t -> + date:Date.t -> + bool + +(** Whether the Te Deum was said at Matins (Breviary 1961 Codex Rubricarum + nn. 237-238) -- NOT the Divine Office arriving in scope, but a single + Breviary fact {!gloria}'s own RG 431(a) defers a Mass question to. See + the .ml's own header for the rubric quoted in full, every branch's own + citation, and this source's own stated weakness (a single, not yet + scan-verified, web transcription -- docs/research/breviary/PROVENANCE.md). + Same three parameters as {!creed}, for the same reasons: [temporal] for + the day's own weekday/season, [observed] for the celebration whose + Office is actually kept, [date] for the Easter-relative window + questions. *) +val te_deum : + temporal:(Vocab_ef.season, Vocab_ef.rank) Temporal.t -> + observed:Vocab_ef.rank Celebration.t -> + date:Date.t -> + bool + +(** Whether the Gloria in excelsis is said at this day's Mass (RG 431-432). + 431(a)/432(a) defer to {!te_deum}; 431(c) (Holy Thursday, the Easter + Vigil Mass) and 432(b)/(d) (violet vestments; a Requiem) are + independent overrides, checked ahead of the Te Deum-derived answer -- + see the .ml's own header for the full account, including which of + 431/432's own clauses this engine has no votive-Mass-class dimension to + implement and are therefore marked not-applicable rather than silently + skipped. *) +val gloria : + temporal:(Vocab_ef.season, Vocab_ef.rank) Temporal.t -> + observed:Vocab_ef.rank Celebration.t -> + date:Date.t -> + bool + +(** RG 487(a)'s own two fixed-feast triggers for the Holy Cross preference + (the Exaltation of the Holy Cross, the Most Precious Blood) -- see the + .ml's own citation for what RG 487(a)'s further-named categories (the + Passion/Instruments of the Passion, the Most Holy Redeemer) are absent + from the shipped calendar entirely, not merely from this list. *) +val preface_holy_cross_slugs : string list + +(** RG 496's own two St Joseph feasts in the shipped calendar. *) +val preface_st_joseph_slugs : string list + +(** RG 497's own [Apostolorum et Evangelistarum] population -- WIDER than + {!creed_apostle_slugs} (no natalicium restriction); includes + "conversion-of-st-paul" (Preface-witnesses task, 2026-08-23, four + independent unimpeded-year confirmations across two publishers -- see + the .ml's own citation for the full evidence and the survey of every + other Apostle/Evangelist-named slug that was checked and NOT added. *) +val preface_apostle_slugs : string list + +(** RG 495's own [beatae Mariae Virginis] population -- WIDER than + {!Precedence_ef.marian_slugs} (a different, looser standard than that + list's own RG 112(d) oration-level one); see the .ml's own citation + for the FIUV Ordo evidence. *) +val preface_bvm_slugs : string list + +(** Which preface is said at this day's Mass (RG 482-499). [None] both when + this engine resolves a day with no Mass at all (Good Friday) and -- for + a rite that has not implemented this function at all -- as the type's + own neutral value; see the .ml's own header for the rubric quoted in + full, the priority order every branch follows and why, and the FIUV + Ordo evidence that order rests on. Same three parameters as {!creed}/ + {!te_deum}/{!gloria}, for the same reasons. *) +val preface : + temporal:(Vocab_ef.season, Vocab_ef.rank) Temporal.t -> + observed:Vocab_ef.rank Celebration.t -> + date:Date.t -> + Preface.t option diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml index c16732b..fe08b2e 100644 --- a/lib/rites/rite_ef/temporal_ef.ml +++ b/lib/rites/rite_ef/temporal_ef.ml @@ -823,12 +823,36 @@ let temporal d = "ef-rogation-monday"/"-tuesday" are colitur-only keys and a lectionary gap for Plan 4 (CORRECTED, final fix wave, item 7 -- the lectionary bootstrap is Plan 4, not Plan 3), like the Ember - and Nativity-vigil keys above. *) + and Nativity-vigil keys above. + + COLOUR (L6, data/ef/expected-divergences-lms.sexp, CLOSED by this + fix): this branch used to hardcode [Colour.Violet] with no + citation at all. RG 119 (Caput XVIII, "De Colore Paramentorum"): + white is used "in Officio et Missa de Tempore ... a Missa Vigiliae + paschalis usque ad Missam vigiliae Pentecostes exclusive" -- the + de-Tempore Office AND Mass are white from the Paschal Vigil Mass + until the Pentecost Vigil Mass exclusive, and days 36/37 (Rogation + Monday/Tuesday) sit squarely inside that window. RG 128's own + exhaustive four-case list for violet (Advent I-Christmas Eve; + Septuagesima-Paschal Vigil; the September Ember ferias; vigils of + II/III class OUTSIDE Paschaltide) names Rogation days nowhere, and + its vigil clause is inapplicable twice over -- these are not + vigils, and they ARE inside Paschaltide. RG 88 ("de Litaniis + minoribus nihil fit in Officio, sed tantum in Missa") is why: the + violet belongs to the ROGATION MASS/procession alone, a distinct + votive text this engine does not model as a separate Mass (the + same per-action colour nuance temporal_ef.ml's own RG 126/RG 128 + Good-Friday-Communion citations already flag as unmodelled + elsewhere) -- the day's own OFFICE, which is what [colour] here + expresses, stays [season_colour s] like any other Paschaltide + feria. Witnessed directly: LMS 2023-2024, 2024-05-06 (Rogation + Monday), "FERIA IV Cl W" (white), "Mass of 5th Sunday after + Easter". *) let rogation = days_between easter d in if rogation = 36 || rogation = 37 then build ~season:s ~slug:(if rogation = 36 then "ef-rogation-monday" else "ef-rogation-tuesday") - ~colour:Colour.Violet ~rank:(ferial_rank d s) ~week:(week d) () + ~colour:(season_colour s) ~rank:(ferial_rank d s) ~week:(week d) () else match ember d with | Some (slug, rank, colour) -> build ~season:s ~slug ~colour ~rank ~week:(week d) () @@ -1158,6 +1182,68 @@ let anchors y = | Some d -> [ ("ef-holy-name-sunday", d) ] | None -> [ ("ef-holy-name", holy_name_fallback_date y) ]) +(* The Missale Romanum's own CALENDARIUM table, February, footnote + (docs/research/LT.txt:5011-5014, scan-corroborated at + docs/research/scan2.txt:3050-3058, where OCR mangles it to + "bi&sextili"/"Matthue"/"Cabrielis" -- transcription and scan agree, so + this rests on two witnesses of the same document): + + "In anno bissextili mensis februarius est dierum 29, et festum S. + Matthiae celebratur die 25 februarii, ac festum S. Gabrielis a + Virgine perdolente 28 februarii, et bis dicitur sexto calendas, id + est die 24 et die 25; et littera dominicalis, quae assumpta fuit in + mense ianuario, mutetur in praecedentem..." + + In a leap year February has 29 days, St Matthias is kept on 25 February + (not 24), St Gabriel of Our Lady of Sorrows on 28 February (not 27), and + the sixth kalends of March is said TWICE -- "bis dicitur sexto + calendas... die 24 et die 25". That last clause names the MECHANISM, not + two independent exceptions: the Roman calendar's intercalary day is + inserted by DOUBLING the sixth kalends (civil 24 February in a common + year), not by appending a 29th day at the month's end. Reckoned by + kalends position: 24 Feb = VI Kal. Mart., 25 Feb = V Kal., 26 Feb = IV + Kal., 27 Feb = III Kal., 28 Feb = pridie Kal. In a leap year VI Kal. + itself falls on TWO consecutive civil days (24th and 25th, "bis"), and + every kalends position after it is pushed one civil day later as a + result: V Kal. from 25th to 26th, IV Kal. from 26th to 27th, III Kal. + (Gabriel) from 27th to 28th, pridie Kal. from 28th to 29th. A feast fixed + at VI Kal. itself (Matthias) is kept on the SECOND occurrence, not the + first -- 25 February carries it, 24 February carries no fixed office at + all that year (confirmed against the LMS Ordo witness, + data/ef/expected-divergences-lms.sexp entry L3: 24 February 2024 is + titled plainly "EMBER SATURDAY of LENT", no Matthias anywhere near it). + + IMPLEMENTED AS THE GENERAL MECHANISM, not as "shift these two named + feasts": only three sanctoral entries exist in 23-29 February on shipped + data (peter-damien the 23rd, before the doubled kalends and therefore + unaffected; matthias the 24th; gabriel-of-our-lady-of-sorrows the 27th), + so "shift the two named feasts" and "shift every fixed entry from 24 + February" are indistinguishable on universal data -- they produce + identical output. They differ only for a locally-supplied entry, e.g. an + [--overlay] patronal feast fixed at 26 February: under the mechanism + reading it shifts to 27 February in a leap year (IV Kal. -> the civil day + IV Kal. falls on that year), exactly as a diocesan calendar compiled + against the same kalends convention would expect. The rubric's own text + states a MECHANISM ("bis dicitur sexto calendas"), not a closed list of + two saints, and this project has already been bitten once by a rule + implemented against the shipped data's coincidental shape rather than the + rubric itself (RG 16(a), CLAUDE.md's own carried lesson) -- so the general + reading is the one implemented here. + + Threaded through {!Rite.t}'s [fixed_key] field, read only by + {!Colitur_kernel.Layer.on_date}'s FIXED half: the kernel stays + rite-agnostic (a Byzantine or other non-Roman rite supplies nothing and + is unaffected), and the MOVABLE half ({!Date_spec.Easter_offset}, + {!Date_spec.Nth_weekday}) is untouched -- nothing in the footnote + concerns Easter-relative dates. *) +let bissextile_fixed_key (d : Date.t) : (int * int) option = + let m = Date.month d and day = Date.day d in + if m = 2 && Date.is_leap (Date.year d) then + if day = 24 then None (* the FIRST VI Kal.: no fixed entry lands here in a leap year *) + else if day >= 25 && day <= 29 then Some (2, day - 1) (* the SECOND VI Kal. onward, one day later *) + else Some (m, day) + else Some (m, day) + (* Compile-time check that this module satisfies the kernel's rite contract. *) module _ : Colitur_kernel.Temporal.RITE = struct let id = id diff --git a/lib/rites/rite_ef/temporal_ef.mli b/lib/rites/rite_ef/temporal_ef.mli index 5e85111..2bed5b6 100644 --- a/lib/rites/rite_ef/temporal_ef.mli +++ b/lib/rites/rite_ef/temporal_ef.mli @@ -51,6 +51,17 @@ val week : Date.t -> int option (** The lectionary key for a Sunday, or [None] if [d] is not a Sunday. *) val sunday_slug : Date.t -> string option +(** The calendarium's own bissextile (leap-year) footnote, February + (docs/research/LT.txt:5011-5014): in a leap year the sixth kalends of + March (24 February) is doubled rather than a 29th day appended, so every + fixed entry from 24 through 28 February is kept one civil day later than + usual (Matthias 24->25, Gabriel of Our Lady of Sorrows 27->28), and 24 + February itself carries no fixed office that year. Supplied as {!Rite.t}'s + [fixed_key] field -- see that field's own doc comment and this function's + definition for the full citation and the general-mechanism-vs-two-named- + feasts reasoning. *) +val bissextile_fixed_key : Date.t -> (int * int) option + val id : string (** Total over 1583..9999: every date yields exactly one temporal identity. *) diff --git a/man/colitur.1 b/man/colitur.1 index 4a3c580..3f485d5 100644 --- a/man/colitur.1 +++ b/man/colitur.1 @@ -3,7 +3,7 @@ colitur \- deterministic liturgical calendar and lectionary engine (Roman rite, 1962) .SH SYNOPSIS .B colitur -.BR easter | temporal | day | readings +.BR easter | temporal | day | readings | rubrics .I YEAR .br .B colitur @@ -17,6 +17,11 @@ colitur \- deterministic liturgical calendar and lectionary engine (Roman rite, .RB [ \-\-raw ] .br .B colitur +.B rubrics +.I YEAR +.RB [ \-\-overlay " FILE" " ...]" +.br +.B colitur .B emit .BI \-\-format " FMT" .BI \-\-from " YEAR" @@ -116,6 +121,18 @@ occurrence, commemoration and transfer. .BI readings " YEAR" The Mass reading citations, one line per day. .TP +.BI rubrics " YEAR" +Four rubrics of the Mass, one line per day: which formulary is actually +said \(em not always the day's own: a weekday with no proper resumes the +preceding Sunday's, a saint with no proper says his assigned Common, and +RG 78/309(a)'s votive Saturday Mass of Our Lady is said in place of an +unoccupied office's own \(em whether the Creed is said (RG 475\-476), +whether the Gloria in excelsis is said (RG 431\-432, deferring to the +Breviary's own Te Deum rule, nn. 237\-238, for RG 431(a)), and which +preface is said (RG 482\-499). See +.B OUTPUT FORMAT +below. +.TP .B emit Render a civil\-year range through one of five emitters \(em .BR csv ", " json ", " sexp ", " xml " or " ics . @@ -210,7 +227,7 @@ for the config file's location and precedence in full. .TP .BI \-\-overlay " FILE" Apply a user calendar on top of the shipped one. Repeatable and ordered; -.BR day ", " readings ", " emit ", " table ", " render " and " publish +.BR day ", " readings ", " rubrics ", " emit ", " table ", " render " and " publish only. See .B OVERLAYS below. @@ -442,17 +459,110 @@ own trailing field, above. 2038\-03\-06 sts\-felicitas\-perpetua | Ecclus 51:1\-8, 12 | Matt 13:44\-52 | Ss. Perpetuae et Felicitatis Mm. .fi .RE +.SS rubrics +.RS +.nf +date [TAB] formulary\-slug [TAB] source [TAB] creed [TAB] gloria [TAB] preface +.fi +.RE .PP -Both reports are one line per day and ordered by date, so they compose with +The day's own Mass formulary (which slug's Mass is actually said, and how +that was decided), followed by whether the Creed is said (RG 475\-476), +whether the Gloria in excelsis is said (RG 431\-432), and which preface is +said (RG 482\-499). +.B rubrics +separates its fields with a literal TAB \(em not a plain space like +.B day +or +.RB \(lq " | " \(rq +like +.B readings +\(em because a resolved formulary NAME (a column a later version may add, +not either of these) can carry both spaces and punctuation a citation never +does, which rules out either separator already in use above. A separate +command for the identical mechanical reason +.B day +is separate from +.BR readings : +.BR day 's +own row is fixed\-width space\-separated with a variable\-length +.RI + slug +tail, so appending anything with its own internal whitespace there would +leave it unsplittable by field number. +.I source +is one of +.BR proper ", " own ", " preceding\-sunday ", " common " or " votive . +.I creed +and +.I gloria +are each +.B true +or +.B false +(OCaml's own literal, not +.RB \(lq yes / no \(rq +or +.RB \(lq 1/0 \(rq : +this row has no other boolean field to be consistent with). A day with no +Mass at all for a rite that has not implemented a rule reads +.B false +outright \(em it is a decision, never a third \(lqunknown\(rq state. +.I preface +is one of +.BR nativity ", " epiphany ", " lent ", " holy\-cross ", " easter ", " +.BR ascension ", " sacred\-heart ", " christ\-the\-king ", " holy\-spirit ", " +.BR trinity ", " bvm ", " st\-joseph ", " apostles ", " common " or " requiem , +or a literal +.B \- +when this engine resolves no Mass at all that day (Good Friday) \(em unlike +.I creed / gloria , +.I preface +is a genuine option, so +.B \- +here can also mean a rite that has not implemented the rule at all. +.RS +.nf + +2026\-01\-01 [TAB] ef\-circumcision [TAB] own [TAB] true [TAB] true [TAB] nativity +2038\-03\-08 [TAB] john\-of\-god [TAB] proper [TAB] false [TAB] true [TAB] common +2025\-12\-01 [TAB] ef\-advent\-sunday\-1 [TAB] preceding\-sunday [TAB] false [TAB] false [TAB] common +.fi +.RE +.PP +Unlike +.B day +and +.BR readings , +.B rubrics +resolves no display name and no citation, so it takes none of +.BR \-\-lang ", " \-\-raw +or any +.B \-\-sigla\-* +flag \(em refused rather than silently ignored, the same discipline +.B \-\-overlay +gets on +.B easter +and +.BR temporal . +.PP +All three reports are one line per day and ordered by date, so they compose +with .BR grep (1), .BR awk (1) and .BR join (1) in the ordinary way. Pass .B \-\-raw -to restore the pre\-naming byte\-exact output of either report \(em no -trailing field at all \(em for a script written against it before this -feature existed. +to restore the pre\-naming byte\-exact output of +.B day +or +.B readings +\(em no trailing field at all \(em for a script written against either +before the naming feature existed; +.B rubrics +is already in that form and has no +.B \-\-raw +of its own to pass. .SH EMIT .BI "colitur emit " \-\-format " FMT " \-\-from " YEAR " \-\-to " YEAR" renders the same resolved day \(em season, week, slug, rank, colour, @@ -903,7 +1013,7 @@ shapes: .RE .PP Accepted on -.BR day ", " readings ", " emit ", " table ", " render " and " publish . +.BR day ", " readings ", " rubrics ", " emit ", " table ", " render " and " publish . .BR easter " and " temporal read no sanctoral data at all, so the flag would have no effect there and is .I refused @@ -911,7 +1021,7 @@ rather than silently ignored. .PP .B An overlay is applied, not validated. This program's test layers \(em properties over every year in the domain, a -differential against a sibling engine, two published\-calendar oracles, and +differential against a sibling engine, three published\-calendar oracles, and hand\-verified pins \(em assert things about the .I shipped calendar. None of them can vouch for a file you supply. A directive naming a @@ -1477,6 +1587,18 @@ emits. Published calendars \(em missalemeum, Divinum Officium, gcatholic \(em are used as comparison oracles in the test suite only: a divergence from one is flagged loudly and adjudicated against the Missal, never silently adopted. Several such divergences have been resolved in this engine's favour. +Missalemeum's own data derives from Divinum Officium, so those two are one +lineage rather than two independent witnesses; a printed +.I Ordo +from the Latin Mass Society of England and Wales, compiled directly from the +Missal and never passed through that lineage, is used as a genuinely +independent oracle for one liturgical year (Advent 2024 through the end of +1962's 2025) \(em the Creed rubric, the Saturday votive Mass of Our Lady's +own seasonal selection, and which Mass a day borrows, each compared against +it in full. It covers only the universal calendar (its own diocesan propers +and local patrons are excluded from every comparison), one civil year, and +one publisher's transcription \(em a divergence against it is a question, +not a verdict, the same discipline applied to every other oracle here. .SH LIMITATIONS Only the Extraordinary Form (1962) is implemented; the Ordinary Form is a planned peer module, not an overlay of this one. @@ -17,7 +17,7 @@ A year outside the supported domain is rejected (exit 2): No/garbage arguments give a usage error (exit 2): $ colitur - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur rubrics <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] The EF temporal cycle for a year, one line per day: @@ -199,6 +199,91 @@ A year outside the supported domain is rejected (exit 2): colitur: year 1000 out of range 1583..9999 [2] +Rubrics (Task 4, celebrant-rubrics-phase1): the day's own Mass formulary, one +row per day: date, the formulary's slug (which Mass is actually said, not +always the day's own), and how that was decided +(proper/own/preceding-sunday/common/votive). TAB-separated -- not space like +`day`, not " | " like `readings` -- because a resolved formulary NAME (a +later column, not this one) can itself contain both spaces and punctuation a +citation never does, and TAB is what stays unambiguous either way. A +separate command for the same mechanical reason `readings` is: `day`'s row +is fixed-width space-separated with a variable-length "+slug" tail. + + $ colitur rubrics 2026 | head -3 + 2026-01-01 ef-circumcision own true true nativity + 2026-01-02 ef-christmas-1-friday own false true nativity + 2026-01-03 ef-christmas-1-saturday votive false true bvm + + $ colitur rubrics 2026 | wc -l + 365 + +1 January reads "own", not "proper": the Circumcision is a TEMPORAL-origin +office (Rite_ef.Temporal_ef, not the sanctoral Layer), so step 1 of the +resolution chain (a SANCTORAL observed celebration's own proper) does not +apply to it -- step 2 does (the day's own temporal slug in the lectionary), +tagged `own`. Contrast a real sanctoral saint with his own proper: + + $ colitur rubrics 2038 | grep '^2038-03-08' + 2038-03-08 john-of-god proper false true common + +A saint with no proper of his own says his assigned Common (step 4): + + $ colitur rubrics 2038 | grep '^2038-03-06' + 2038-03-06 common-of-non-virgins-1 common false true common + +A weekday with no proper of its own resumes the preceding Sunday's, never +its own observed slug -- 1 December 2025 is the Monday after Advent I, and +Advent's ferias have no Mass of their own (step 3): + + $ colitur rubrics 2025 | grep '^2025-12-01' + 2025-12-01 ef-advent-sunday-1 preceding-sunday false false common + +3 January 2026 above ("votive") is the RG 78/309(a) Saturday Mass of Our +Lady, said IN PLACE of the day's own office's Mass while the office (an +unoccupied IV-class Saturday) itself is kept unchanged -- distinct from +`own` precisely because a votive Mass is not the day's own, even though +`said` names the identical slug either way. + +A year outside the supported domain is rejected (exit 2): + + $ colitur rubrics 1000 + colitur: year 1000 out of range 1583..9999 + [2] + +--overlay is accepted, the same reasoning `readings` gets it: an overlay can +change which celebration is observed, hence which Mass formulary is said. +Baseline, the unoccupied Saturday says Our Lady's votive Mass; with the +diocesan overlay's local patron observed instead (no proper or Common of his +own in the fixture), the chain falls all the way back to step 3: + + $ colitur rubrics 2026 --overlay fixtures/overlay-example-diocesan.sexp | grep '^2026-07-11' + 2026-07-11 ef-time-after-pentecost-sunday-6 preceding-sunday false true common + $ colitur rubrics 2026 | grep '^2026-07-11' + 2026-07-11 ef-time-after-pentecost-6-saturday votive false true bvm + +`--lang`/`--raw`/`--sigla-*` are refused rather than silently ignored, unlike +`readings`: this row resolves no display name and no citation for any of +them to affect. + + $ colitur rubrics 2026 --lang en + colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them + [2] + + $ colitur rubrics 2026 --raw + colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them + [2] + + $ colitur rubrics 2026 --sigla-style en + colitur: --sigla-style/--sigla-book/--sigla-tradition have no effect on `rubrics`; refusing rather than ignoring them + [2] + +`colitur day` and `colitur readings` are unaffected by any of the above: + + $ colitur day 2026 --raw | head -1 + 2026-01-01 thursday christmastide - ef-circumcision class-1 white + $ colitur readings 2026 --raw | head -1 + 2026-01-01 ef-circumcision | Titus 2:11-15 | Luke 2:21 + An explicit COLITUR_DATA_DIR that does not hold the data is an error (exit 2), never a silent fall-back to some other copy. A packager or operator who names a directory has stated an intent; quietly calendaring off a different one @@ -247,7 +332,24 @@ The error path is the mirror image -- nothing on stdout, exit 2: Every command the help lists is a command the binary actually accepts. This is the check that catches help text drifting away from the dispatch: - $ for c in easter temporal day readings; do colitur $c 2026 > /dev/null || echo "$c FAILED"; done + $ for c in easter temporal day readings rubrics; do colitur $c 2026 > /dev/null || echo "$c FAILED"; done + +`rubrics`' own field count drifted once already (Task 5 landed a fourth +column, creed; --help's "output formats" section and its worked example +still showed three, and stayed wrong for a whole review round because +nothing here pinned the help BODY, only command dispatch above). This +compares --help's own worked example against what `rubrics` actually +prints for the identical day, so the two cannot silently drift apart +again in either direction: + + $ colitur --help | grep '^ rubrics date' + rubrics date, formulary slug, source, creed, gloria, preface -- TAB-separated + + $ colitur --help | sed -n '/^ rubrics date/{n;p}' + 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity + + $ colitur rubrics 2026 | grep '^2026-01-01' | sed $'s/\t/[TAB]/g' + 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity --version prints the version alone, to standard output, exit 0. Deliberately not embedded in the help text above: this pin would then have to be edited @@ -327,14 +429,14 @@ A flag needing a value, given none: $ colitur day 2026 --overlay colitur: --overlay needs a file path - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur rubrics <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] An unknown option is rejected rather than treated as a positional word: $ colitur day 2026 --diocese colitur: unknown option --diocese - colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) + colitur: usage: colitur easter <year> | colitur temporal <year> | colitur day <year> | colitur readings <year> | colitur rubrics <year> | colitur emit --format FMT --from Y --to Y | colitur table --year Y --template FILE | colitur render --template FILE --year Y | colitur publish --from Y --to Y --out DIR | colitur lang --list|--dump CODE|--check FILE | colitur config --show | colitur check FILE | colitur new-overlay (try: colitur --help) [2] The shipped example overlay is runnable documentation, and it must actually @@ -449,10 +551,55 @@ CSV run rather than one per year: $ colitur emit --format csv --from 2027 --to 2028 | wc -l 732 -sexp and xml are also available: +sexp and xml are also available. This line count moved twice in the same +whole-branch review fix round, for two different reasons, both cosmetic: +[emit --format sexp] pretty-prints with [Sexplib.Sexp.to_string_hum], a +column-width wrapping printer, not a fixed-shape one, so any change to a +value's own rendered WIDTH can shift where it wraps. + +9010 -> 9011 (RG 476(f)): 2027's All Souls' Day (2 November) record grew +a single wrapped line when its own [creed] field's value changed from +[true] to [false] (the Creed is never said at a Requiem Mass; see +rubrics_ef.ml), because "false" is one character longer than "true" and +pushed that one line's rendered width over the wrap threshold. + +9011 -> 9025 (Mass_formulary.t.said honesty, Fix 3): [said] gained an +[option] (its own .mli has the full account) -- every day's formulary +record now prints [(said (<slug>))] instead of [(said <slug>)], one +character wider, and a [Votive] day (the RG 78 Saturday Mass of Our +Lady) prints [(said ())] instead of naming a slug at all, since the +data genuinely names none for the Mass actually said. Both changes ripple +across many lines' own wrap points, not just the days whose DATA changed +-- confirmed directly (diffed the full sexp output line by line): every +difference is exactly this [said] shape change or a consequent wrap +shift, nothing else. Not a claim that [emit]'s FORMAT changed, only that +individual records' pretty-printed SHAPE did. + +9025 -> 9197 (Gloria, celebrant-rubrics-phase1 Phase 2): {!Liturgical_day.t} +gained a [gloria] field, the same seam [creed] already used -- [emit +--format sexp] dumps the whole record ({!Sexplib.Sexp.to_string_hum} over +[Liturgical_day.sexp_of_t]) unlike [csv]/[json]/[xml] (a curated +[View]/[Record] projection that has never included [creed] either, hence +their own line counts above are UNCHANGED by this task -- confirmed by +this cram file's own diff touching only the [sexp] count). All 365 of +2027's records print a new [(gloria <bool>)] token (checked directly, +[grep -c gloria]), but the wrap-point mechanics are the same cosmetic +reflow the two entries above describe, not a fixed one-line-per-record +addition: 2027-01-01's own record wraps [gloria] onto its own new line, +while 2027-01-02's fits it on the same line as [creed] and [formulary] -- +172 of 365 records happened to cross a wrap boundary, the rest did not. + +9197 -> 9252 (preface, celebrant-rubrics-phase1 Phase 3): {!Liturgical_day.t} +gained a [preface] field, the same seam [gloria] just above used -- all +365 of 2027's records print a new [(preface (<variant>))] token (checked +directly, [grep -c "(preface"]), [(preface ())] on exactly one day +(2027's own Good Friday, 26 March -- this engine resolves no Mass at all +that day, {!Rite_ef.Rubrics_ef.preface}'s own citation). Same cosmetic +reflow mechanics as every entry above, not a fixed one-line-per-record +addition. $ colitur emit --format sexp --from 2027 --to 2027 | wc -l - 8472 + 9252 $ colitur emit --format xml --from 2027 --to 2027 | head -2 <?xml version="1.0" encoding="UTF-8"?> @@ -9,6 +9,9 @@ ../lang/traditions.ini ../data/ef/expected-divergences.sexp ../data/ef/expected-divergences-missalemeum.sexp + ../data/ef/expected-divergences-lms.sexp + ../data/ef/expected-divergences-fiuv.sexp + ../data/ef/expected-divergences-efdotorg.sexp ../data/ef/lectionary.sexp ../data/ef/commons.sexp ../data/ef/examples/diocesan-example.sexp @@ -16,6 +19,13 @@ fixtures/missalemeum-ef-2026-2027.txt fixtures/missalemeum-ef-2038.txt fixtures/missalemeum-ef-2035.txt + fixtures/lms-ordo-2023-2024.sexp + fixtures/lms-ordo-2024-2025.sexp + fixtures/lms-ordo-2025-2026.sexp + fixtures/fiuv-ordo-2025-2026.sexp + fixtures/efdotorg-ordo-2024-2025.sexp + fixtures/efdotorg-ordo-2025-2026.sexp + fixtures/efdotorg-ordo-2026-2027.sexp ../templates/ef/ordo.tex ../templates/ef/ordo.ms ../templates/ef/ordo.html diff --git a/test/fixtures/efdotorg-ordo-2024-2025.sexp b/test/fixtures/efdotorg-ordo-2024-2025.sexp new file mode 100644 index 0000000..be69daa --- /dev/null +++ b/test/fixtures/efdotorg-ordo-2024-2025.sexp @@ -0,0 +1,398 @@ +; test/fixtures/efdotorg-ordo-2024-2025.sexp -- efdotorg-preface task +; (2026-08-24-colitur-celebrant-rubrics-phase1): the THIRD independent +; preface witness (RG 482-499), extraordinaryform.org's 2024-2025 Ordo, +; extracted from the already-parsed, fidelity-audited corpus +; docs/research/ordo/ordo-2024-2027.json (SHA-256 18a417fb8b30dc438c3f12f64b43dfdf5e2e9313857f2eccd04bf02072ca7e3c) rather than +; re-parsed from the PDF -- see tools/extract_efdotorg_ordo.py's own +; header for the full characterisation this fixture rests on (the menu- +; trap office filter, the Christ-the-King classifier-gap recovery, why +; "Advent" is not baked into a single mapping here, the known Vigil-of- +; St-Lawrence gap, and the two source-PDF defects that turn out not to +; touch this field). +; +; Generator: tools/extract_efdotorg_ordo.py -- do not hand-edit; re-run +; against the same JSON and commit the diff instead. +; python3 tools/extract_efdotorg_ordo.py docs/research/ordo/ordo-2024-2027.json test/fixtures +; +; Source PDF (gitignored, CLAUDE.md: "docs/ is gitignored", see +; docs/research/ordo/SHA256SUMS for its own hash): 2024-2025Ordo.pdf, +; extraordinaryform.org. +; +; COVERAGE: 364 day-rows, 2024-12-01..2025-11-29 (this edition's own civil-date +; span, re-derived from the JSON's own seams -- see the generator's own +; EDITIONS comment). 0 row(s) are a genuine SOURCE GAP (2027-03-03 +; only, a PDF row-drop, ordo-fidelity-report.md) -- mass/cls/colour/praef +; all absent, the same shape a structurally blank day (Good Friday) uses. +; 1 further row(s) have mass/cls/colour but no praef at all +; (Good Friday -- RG 28, no Mass in the 1955-restored Holy Week). +; +; Each row's `praef` is RAW TEXT from the day's own OFFICE (after the +; menu-trap filter, with the Christ-the-King recovery already applied) -- +; classified against {!Colitur_kernel.Preface.t} by +; test/test_efdotorg_ordo.ml, not here. +( + ((date 2024-12-01) (mass ("First Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-02) (mass ("St. Bibiana, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2024-12-03) (mass ("St. Francis Xavier, Confessor")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2024-12-04) (mass ("St. Peter Chrysologus, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2024-12-05) (mass ("Feria \226\128\147 First Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-06) (mass ("St. Nicholas, Confessor & Bishop")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2024-12-07) (mass ("St. Ambrose, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2024-12-08) (mass ("Immaculate Conception")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2024-12-09) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-10) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-11) (mass ("St. Damasus I, Pope")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2024-12-12) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-13) (mass ("St. Lucy, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2024-12-14) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-15) (mass ("Third Sunday of Advent \226\128\147 Gaudete")) (cls (1)) (colour ("rose")) (praef ("Advent"))) + ((date 2024-12-16) (mass ("St. Eusebius, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2024-12-17) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-18) (mass ("Ember Wednesday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-19) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-20) (mass ("Ember Friday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-21) (mass ("St. Thomas, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2024-12-22) (mass ("Fourth Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-23) (mass ("Feria - Fourth Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-24) (mass ("Vigil of Nativity of Our Lord")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2024-12-25) (mass ("Nativity of Our Lord - Mass at Midnight")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2024-12-26) (mass ("Day II in the Octave, St. Stephen, Protomartyr")) (cls (2)) (colour ("red")) (praef ("Nativity"))) + ((date 2024-12-27) (mass ("Day III in the Octave, St. John, Apostle & Evangelist")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2024-12-28) (mass ("Day IV in the Octave, Holy Innocents")) (cls (2)) (colour ("red")) (praef ("Nativity"))) + ((date 2024-12-29) (mass ("Sunday within the Octave of Christmas")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2024-12-30) (mass ("Day VI in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2024-12-31) (mass ("Day VII in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-01-01) (mass ("Day VIII in the Octave, Circumcision of Our Lord")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-01-02) (mass ("Feria in Christmastide")) (cls (4)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-01-03) (mass ("Feria in Christmastide")) (cls (4)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-01-04) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-01-05) (mass ("Holy Name of Jesus")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-01-06) (mass ("Epiphany of Our Lord")) (cls (1)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-07) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-08) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-09) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-10) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-11) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-01-12) (mass ("Holy Family")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-13) (mass ("Baptism of Our Lord")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2025-01-14) (mass ("St. Hilary, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-15) (mass ("St. Paul, First Hermit, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-16) (mass ("St. Marcellus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-17) (mass ("St. Anthony, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-18) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-01-19) (mass ("Second Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-01-20) (mass ("Ss. Fabian, Pope, & Sebastian, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-21) (mass ("St. Agnes, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-22) (mass ("Ss. Vincent & Anastasius, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-23) (mass ("St. Raymund of Pennafort, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-24) (mass ("St. Timothy, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-25) (mass ("Conversion of St. Paul, Apostle")) (cls (3)) (colour ("white")) (praef ("Apostles"))) + ((date 2025-01-26) (mass ("Third Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-01-27) (mass ("St. John Chrysostom, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-28) (mass ("St. Peter Nolasco, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-29) (mass ("St. Francis de Sales, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-01-30) (mass ("St. Martina, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-01-31) (mass ("St. John Bosco, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-01) (mass ("St. Ignatius of Antioch, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-02-02) (mass ("and Purification of the BVM")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-02-03) (mass ("St. Blase, Bishop & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-02-04) (mass ("St. Andrew Corsini, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-05) (mass ("St. Agatha, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-02-06) (mass ("St. Titus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-07) (mass ("St. Romuald, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-08) (mass ("St. John of Matha, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-09) (mass ("Fifth Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-02-10) (mass ("St. Scholastica, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-11) (mass ("Our Lady of Lourdes")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2025-02-12) (mass ("Seven Holy Founders, Confessors")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-13) (mass ("Feria \226\128\147 Fifth Sunday after Epiphany")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-02-14) (mass ("St. Valentine, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-02-15) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-02-16) (mass ("Septuagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2025-02-17) (mass ("Feria - Septuagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-18) (mass ("St. Simeon, Bishop & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-02-19) (mass ("Feria - Septuagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-20) (mass ("Feria - Septuagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-21) (mass ("Feria - Septuagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-22) (mass ("Chair of St. Peter")) (cls (2)) (colour ("white")) (praef ("Apostles"))) + ((date 2025-02-23) (mass ("Sexagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2025-02-24) (mass ("St. Matthias, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-02-25) (mass ("Feria - Sexagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-26) (mass ("Feria - Sexagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-02-27) (mass ("St. Gabriel of Our Lady of Sorrows")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-02-28) (mass ("Feria - Sexagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-03-01) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-03-02) (mass ("Quinquagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2025-03-03) (mass ("Feria - Quinquagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2025-03-04) (mass ("St. Casimir, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-03-05) (mass ("and Ash Wednesday")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-06) (mass ("Thursday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-07) (mass ("Friday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-08) (mass ("Saturday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-09) (mass ("1st Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-10) (mass ("Monday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-11) (mass ("Tuesday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-12) (mass ("Ember Wednesday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-13) (mass ("Thursday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-14) (mass ("Ember Friday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-15) (mass ("Ember Saturday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-16) (mass ("2nd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-17) (mass ("Monday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-18) (mass ("Tuesday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-19) (mass ("St. Joseph, Spouse of the BVM")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2025-03-20) (mass ("Thursday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-21) (mass ("Friday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-22) (mass ("Saturday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-23) (mass ("3rd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-24) (mass ("Monday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-25) (mass ("Annunciation of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2025-03-26) (mass ("Wednesday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-27) (mass ("Thursday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-28) (mass ("Friday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-29) (mass ("Saturday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-03-30) (mass ("4th Sunday of Lent \226\128\147 L\195\166tare Sunday")) (cls (1)) (colour ("rose")) (praef ("Lent"))) + ((date 2025-03-31) (mass ("Monday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-01) (mass ("Tuesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-02) (mass ("Wednesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-03) (mass ("Thursday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-04) (mass ("Friday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-05) (mass ("Saturday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2025-04-06) (mass ("Passion Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-07) (mass ("Monday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-08) (mass ("Tuesday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-09) (mass ("Wednesday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-10) (mass ("Thursday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-11) (mass ("Friday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-12) (mass ("Saturday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-13) (mass ("and Palm Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-14) (mass ("Monday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-15) (mass ("Tuesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-16) (mass ("Wednesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2025-04-17) (mass ("Holy Thursday")) (cls (1)) (colour ("white")) (praef ("Holy Cross"))) + ((date 2025-04-18) (mass ("Good Friday")) (cls (1)) (colour ("black")) (praef ())) + ((date 2025-04-19) (mass ("and Easter Vigil Mass")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-20) (mass ("Easter Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-21) (mass ("Easter Monday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-22) (mass ("Easter Tuesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-23) (mass ("Easter Wednesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-24) (mass ("Easter Thursday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-25) (mass ("Easter Friday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-26) (mass ("Easter Saturday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-27) (mass ("Low Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-28) (mass ("St. Paul of the Cross, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-04-29) (mass ("St. Peter of Verona, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2025-04-30) (mass ("St. Catherine of Siena, Virgin")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-01) (mass ("St. Joseph the Workman, Confessor")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2025-05-02) (mass ("St. Athanasius, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-03) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-05-04) (mass ("Second Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-05) (mass ("St. Pius V, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-06) (mass ("St. John before the Latin Gate")) (cls (4)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-05-07) (mass ("St. Stanislaus, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2025-05-08) (mass ("Apparition of St. Michael")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-09) (mass ("St. Gregory Nanzianzen, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-10) (mass ("St. Antoninus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-11) (mass ("Third Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-12) (mass ("Ss. Nereus, Achilleus, Domitila, & Pancras, Martyrs")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2025-05-13) (mass ("St. Robert Bellarmine, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-14) (mass ("St. Boniface, Martyr")) (cls (4)) (colour ("red")) (praef ("Easter"))) + ((date 2025-05-15) (mass ("St. John Baptist de la Salle, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-16) (mass ("St. Ubald, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-17) (mass ("St. Paschal Baylon, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-18) (mass ("Fourth Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-19) (mass ("St. Peter Celestine, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-20) (mass ("St. Bernardine of Siena, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-21) (mass ("Feria - Fourth Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-22) (mass ("Feria - Fourth Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-23) (mass ("Feria - Fourth Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-24) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-05-25) (mass ("5th Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-26) (mass ("St. Philip Neri, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-27) (mass ("St. Bede the Venerable, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-28) (mass ("Vigil of Ascension")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2025-05-29) (mass ("Ascension of Our Lord")) (cls (1)) (colour ("white")) (praef ("Ascension"))) + ((date 2025-05-30) (mass ("St. Felix I, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Ascension"))) + ((date 2025-05-31) (mass ("Queenship of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-06-01) (mass ("Sunday after the Ascension")) (cls (2)) (colour ("white")) (praef ("Ascension"))) + ((date 2025-06-02) (mass ("Ss. Marcellinus, Peter, & Erasmus, Martyrs")) (cls (4)) (colour ("red")) (praef ("Ascension"))) + ((date 2025-06-03) (mass ("Feria - Ascension")) (cls (4)) (colour ("white")) (praef ("Ascension"))) + ((date 2025-06-04) (mass ("St. Francis Caracciolo, Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2025-06-05) (mass ("St. Boniface, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Ascension"))) + ((date 2025-06-06) (mass ("St. Norbert, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2025-06-07) (mass ("Vigil of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-08) (mass ("Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-09) (mass ("Monday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-10) (mass ("Tuesday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-11) (mass ("Ember Wednesday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-12) (mass ("Thursday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-13) (mass ("Ember Friday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-14) (mass ("Ember Saturday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2025-06-15) (mass ("Trinity Sunday")) (cls (1)) (colour ("white")) (praef ("Holy Trinity"))) + ((date 2025-06-16) (mass ("Feria - First Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-06-17) (mass ("St. Gregory Barbarigo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-18) (mass ("St. Ephrem of Syria, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-19) (mass ("Corpus Christi")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-20) (mass ("St. Silverius, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-06-21) (mass ("St. Aloyisius Gonzaga, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-22) (mass ("Second Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-06-23) (mass ("Vigil of Nativity of St. John the Baptist")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-06-24) (mass ("Nativity of St. John the Baptist")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-25) (mass ("St. William, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-06-26) (mass ("Ss. John & Paul, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-06-27) (mass ("Most Sacred Heart of Jesus")) (cls (1)) (colour ("white")) (praef ("Sacred Heart"))) + ((date 2025-06-28) (mass ("Vigil of Ss. Peter & Paul")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-06-29) (mass ("Ss. Peter & Paul, Apostles")) (cls (1)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-06-30) (mass ("Commemoration of St. Paul, Apostle")) (cls (3)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-07-01) (mass ("Most Precious Blood of Our Lord")) (cls (1)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2025-07-02) (mass ("Visitation of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-07-03) (mass ("St. Irenaeus, Doctor of the Church")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-04) (mass ("In Commemoration of All Holy Popes")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-05) (mass ("St. Anthony Mary Zaccaria, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-06) (mass ("Fourth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-07-07) (mass ("Ss. Cyril & Methodius, Bishops & Confessors")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-08) (mass ("St. Elizabeth of Portugal, Queen & Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-09) (mass ("Feria - Fourth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-07-10) (mass ("Seven Holy Brothers, & Ss. Rufina & Secunda, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-11) (mass ("St. Pius I, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-12) (mass ("St. John Gualbert, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-13) (mass ("Fifth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-07-14) (mass ("St. Bonaventure, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-15) (mass ("St. Henry II, Emperor, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-16) (mass ("Our Lady of Mt. Carmel")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-07-17) (mass ("St. Alexius, Confessor")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-18) (mass ("St. Camillus de Lellis, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-19) (mass ("St. Vincent de Paul, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-20) (mass ("Sixth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-07-21) (mass ("St. Lawrence of Brindisi, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-22) (mass ("St. Mary Magdalene, Penitent")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-23) (mass ("St. Apollinarus, Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-24) (mass ("St. Christina, Virgin & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-25) (mass ("St. James the Greater, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-07-26) (mass ("St. Anne, Mother of the BVM")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-27) (mass ("Seventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-07-28) (mass ("Ss. Nazarius & Celsus, Martyrs, Victor I, Pope & Martyr,")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-29) (mass ("St. Martha, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-07-30) (mass ("Ss. Abdon & Sennen, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-07-31) (mass ("St. Ignatius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-01) (mass ("Holy Machabees, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-02) (mass ("St. Alphonsus of Liguori, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-03) (mass ("Eighth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-08-04) (mass ("St. Dominic, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-05) (mass ("Our Lady of the Snows")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2025-08-06) (mass ("Transfiguration of Our Lord")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-07) (mass ("St. Cajetan, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-08) (mass ("St. John Mary Vianney, Confessor & Priest")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-09) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-08-10) (mass ("Ninth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-08-11) (mass ("Ss. Tiburtius & Susanna, Virgin, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-12) (mass ("St. Clare, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-13) (mass ("Ss. Hippolytus & Cassian, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-14) (mass ("Vigil of the Assumption")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-08-15) (mass ("Assumption of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2025-08-16) (mass ("St. Joachim, Father of the BVM")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-17) (mass ("Tenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-08-18) (mass ("St. Agapitus, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-19) (mass ("St. John Eudes, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-20) (mass ("St. Bernard of Clairvaux, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-21) (mass ("St. Jane Frances de Chantal, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-22) (mass ("Immaculate Heart of Mary")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-08-23) (mass ("St. Philip Benizi, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-24) (mass ("Eleventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-08-25) (mass ("St. Louis IX, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-26) (mass ("St. Zephirynus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-27) (mass ("St. Joseph Calasanctius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-28) (mass ("St. Augustine, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-29) (mass ("Beheading of St. John the Baptist")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-08-30) (mass ("St. Rose of Lima, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-08-31) (mass ("Twelfth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-09-01) (mass ("St. Giles, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-02) (mass ("St. Stephen, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-03) (mass ("St. Pius X, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-04) (mass ("Feria - Twelfth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-09-05) (mass ("St. Lawrence Justinian, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-06) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-07) (mass ("Thirteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-09-08) (mass ("Nativity of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-09) (mass ("St. Gorgonius, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-09-10) (mass ("St. Nicholas of Tolentino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-11) (mass ("Ss. Protus & Hyacinth, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-09-12) (mass ("Most Holy Name of Mary")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-13) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-14) (mass ("Exaltation of the Holy Cross")) (cls (2)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2025-09-15) (mass ("Seven Sorrows of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-16) (mass ("St. Cornelius, Pope, & St. Cyprian, Bishop, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-09-17) (mass ("Stigmata of St. Francis")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-18) (mass ("St. Joseph of Cupertino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-19) (mass ("St. Januarius, Bishop, & Companions, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-09-20) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-09-21) (mass ("Fifteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-09-22) (mass ("St. Thomas of Villanova, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-09-23) (mass ("St. Linus, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-09-24) (mass ("Ember Wednesday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-09-25) (mass ("Feria - Fifteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-09-26) (mass ("Ember Friday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-09-27) (mass ("Ember Saturday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2025-09-28) (mass ("Sixteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-09-29) (mass ("St. Michael the Archangel")) (cls (1)) (colour ("white")) (praef ("Holy Trinity"))) + ((date 2025-09-30) (mass ("St. Jerome, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-01) (mass ("St. Remigius, Bishop & Confessor")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-02) (mass ("Holy Guardian Angels")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-03) (mass ("St. Teresa of the Child Jesus, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-04) (mass ("St. Francis of Assisi, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-05) (mass ("Seventeenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-10-06) (mass ("St. Bruno, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-07) (mass ("Our Lady of the Rosary")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-10-08) (mass ("St. Bridget, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-09) (mass ("St. John Leonard, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-10) (mass ("St. Francis Borgia, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-11) (mass ("Maternity of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2025-10-12) (mass ("Eighteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-10-13) (mass ("St. Edward, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-14) (mass ("St. Callistus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-10-15) (mass ("St. Teresa of Avila, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-16) (mass ("St. Hedwig, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-17) (mass ("St. Margaret Mary Alacoque, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-18) (mass ("St. Luke the Evangelist")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-10-19) (mass ("Nineteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-10-20) (mass ("St. John Cantius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-21) (mass ("St. Hilarion, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-22) (mass ("Feria - Nineteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-10-23) (mass ("St. Anthony Mary Claret, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-24) (mass ("St. Raphael the Archangel")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-10-25) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-10-26) (mass ("Christ the King")) (cls (1)) (colour ("white")) (praef ("Christ the King"))) + ((date 2025-10-27) (mass ("Feria - Twentieth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-10-28) (mass ("Ss. Simon & Jude, Apostles")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2025-10-29) (mass ("Feria - Twentieth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-10-30) (mass ("Feria - Twentieth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-10-31) (mass ("Feria - Twentieth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-11-01) (mass ("All Saints")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-02) (mass ("Twenty-first Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-11-03) (mass ("All Souls - Mass 1")) (cls (1)) (colour ("black")) (praef ("For the Dead"))) + ((date 2025-11-04) (mass ("St. Charles Borromeo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-05) (mass ("The Holy Relics")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2025-11-06) (mass ("Feria - Twenty-first Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-11-07) (mass ("Feria - Twenty-first Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-11-08) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-11-09) (mass ("Dedication of the Archbasilica of Our Holy Savior")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-11-10) (mass ("St. Andrew Avellino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-11) (mass ("St. Martin of Tours, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-12) (mass ("St. Martin I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-11-13) (mass ("St. Didacus, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-14) (mass ("St. Josaphat, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-11-15) (mass ("St. Albert the Great, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-16) (mass ("Twenty-third Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-11-17) (mass ("St. Gregory Thaumaturgus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-18) (mass ("Dedication of the Basilicas of Ss. Peter & Paul")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-19) (mass ("St. Elizabeth of Hungary, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-20) (mass ("St. Felix of Valois, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-21) (mass ("Presentation of the BVM")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2025-11-22) (mass ("St. Cecilia, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-11-23) (mass ("Last Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2025-11-24) (mass ("St. John of the Cross, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-25) (mass ("St. Catherine of Alexandria, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2025-11-26) (mass ("St. Sylvester, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2025-11-27) (mass ("Our Lady of the Miraculous Medal")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2025-11-28) (mass ("Feria - Last Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2025-11-29) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("Common"))) +) diff --git a/test/fixtures/efdotorg-ordo-2025-2026.sexp b/test/fixtures/efdotorg-ordo-2025-2026.sexp new file mode 100644 index 0000000..c94a0a8 --- /dev/null +++ b/test/fixtures/efdotorg-ordo-2025-2026.sexp @@ -0,0 +1,398 @@ +; test/fixtures/efdotorg-ordo-2025-2026.sexp -- efdotorg-preface task +; (2026-08-24-colitur-celebrant-rubrics-phase1): the THIRD independent +; preface witness (RG 482-499), extraordinaryform.org's 2025-2026 Ordo, +; extracted from the already-parsed, fidelity-audited corpus +; docs/research/ordo/ordo-2024-2027.json (SHA-256 18a417fb8b30dc438c3f12f64b43dfdf5e2e9313857f2eccd04bf02072ca7e3c) rather than +; re-parsed from the PDF -- see tools/extract_efdotorg_ordo.py's own +; header for the full characterisation this fixture rests on (the menu- +; trap office filter, the Christ-the-King classifier-gap recovery, why +; "Advent" is not baked into a single mapping here, the known Vigil-of- +; St-Lawrence gap, and the two source-PDF defects that turn out not to +; touch this field). +; +; Generator: tools/extract_efdotorg_ordo.py -- do not hand-edit; re-run +; against the same JSON and commit the diff instead. +; python3 tools/extract_efdotorg_ordo.py docs/research/ordo/ordo-2024-2027.json test/fixtures +; +; Source PDF (gitignored, CLAUDE.md: "docs/ is gitignored", see +; docs/research/ordo/SHA256SUMS for its own hash): 2025-2026Ordo.pdf, +; extraordinaryform.org. +; +; COVERAGE: 364 day-rows, 2025-11-30..2026-11-28 (this edition's own civil-date +; span, re-derived from the JSON's own seams -- see the generator's own +; EDITIONS comment). 0 row(s) are a genuine SOURCE GAP (2027-03-03 +; only, a PDF row-drop, ordo-fidelity-report.md) -- mass/cls/colour/praef +; all absent, the same shape a structurally blank day (Good Friday) uses. +; 1 further row(s) have mass/cls/colour but no praef at all +; (Good Friday -- RG 28, no Mass in the 1955-restored Holy Week). +; +; Each row's `praef` is RAW TEXT from the day's own OFFICE (after the +; menu-trap filter, with the Christ-the-King recovery already applied) -- +; classified against {!Colitur_kernel.Preface.t} by +; test/test_efdotorg_ordo.ml, not here. +( + ((date 2025-11-30) (mass ("First Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-01) (mass ("Feria \226\128\147 First Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-02) (mass ("St. Bibiana, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2025-12-03) (mass ("St. Francis Xavier, Confessor")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2025-12-04) (mass ("St. Peter Chrysologus, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2025-12-05) (mass ("Feria \226\128\147 First Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-06) (mass ("St. Nicholas, Confessor & Bishop")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2025-12-07) (mass ("Second Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-08) (mass ("Immaculate Conception")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2025-12-09) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-10) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-11) (mass ("St. Damasus I, Pope")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2025-12-12) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-13) (mass ("St. Lucy, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2025-12-14) (mass ("Third Sunday of Advent \226\128\147 Gaudete")) (cls (1)) (colour ("rose")) (praef ("Advent"))) + ((date 2025-12-15) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-16) (mass ("St. Eusebius, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2025-12-17) (mass ("Ember Wednesday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-18) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-19) (mass ("Ember Friday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-20) (mass ("Ember Saturday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-21) (mass ("Fourth Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-22) (mass ("Feria - Fourth Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-23) (mass ("Feria - Fourth Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-24) (mass ("Vigil of Nativity of Our Lord")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2025-12-25) (mass ("Nativity of Our Lord - Mass at Midnight")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-12-26) (mass ("Day II in the Octave, St. Stephen, Protomartyr")) (cls (2)) (colour ("red")) (praef ("Nativity"))) + ((date 2025-12-27) (mass ("Day III in the Octave, St. John, Apostle & Evangelist")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-12-28) (mass ("Sunday within the Octave of Christmas")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-12-29) (mass ("Day V in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-12-30) (mass ("Day VI in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2025-12-31) (mass ("Day VII in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-01-01) (mass ("Day VIII in the Octave, Circumcision of Our Lord")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-01-02) (mass ("Feria in Christmastide")) (cls (4)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-01-03) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-01-04) (mass ("Holy Name of Jesus")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-01-05) (mass ("St. Telesphorus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Nativity"))) + ((date 2026-01-06) (mass ("Epiphany of Our Lord")) (cls (1)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-07) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-08) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-09) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-10) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-01-11) (mass ("Holy Family")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-12) (mass ("Feria after Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-13) (mass ("Baptism of Our Lord")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2026-01-14) (mass ("St. Hilary, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-15) (mass ("St. Paul, First Hermit, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-16) (mass ("St. Marcellus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-17) (mass ("St. Anthony, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-18) (mass ("Second Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-01-19) (mass ("Ss. Marius, Martha, Audifax, & Abachum, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-20) (mass ("Ss. Fabian, Pope, & Sebastian, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-21) (mass ("St. Agnes, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-22) (mass ("Ss. Vincent & Anastasius, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-23) (mass ("St. Raymund of Pennafort, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-24) (mass ("St. Timothy, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-25) (mass ("Third Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-01-26) (mass ("St. Polycarp, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-27) (mass ("St. John Chrysostom, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-28) (mass ("St. Peter Nolasco, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-29) (mass ("St. Francis de Sales, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-01-30) (mass ("St. Martina, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-01-31) (mass ("St. John Bosco, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-01) (mass ("Septuagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2026-02-02) (mass ("and Purification of BVM")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-02-03) (mass ("St. Blaise, Bishop & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-02-04) (mass ("St. Andrew Corsini, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-05) (mass ("St. Agatha, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-02-06) (mass ("St. Titus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-07) (mass ("St. Romuald, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-08) (mass ("Sexagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2026-02-09) (mass ("St. Cyril, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-10) (mass ("St. Scholastica, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-11) (mass ("Our Lady of Lourdes")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2026-02-12) (mass ("Seven Holy Founders, Confessors")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-02-13) (mass ("Feria - Sexagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2026-02-14) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-02-15) (mass ("Quinquagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2026-02-16) (mass ("Feria - Quinquagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2026-02-17) (mass ("Feria - Quinquagesima")) (cls (4)) (colour ("violet")) (praef ("Common"))) + ((date 2026-02-18) (mass ("and Ash Wednesday")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-19) (mass ("Thursday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-20) (mass ("Friday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-21) (mass ("Saturday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-22) (mass ("1st Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-23) (mass ("Monday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-24) (mass ("St. Matthias, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-02-25) (mass ("Ember Wednesday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-26) (mass ("Thursday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-27) (mass ("Ember Friday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-02-28) (mass ("Ember Saturday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-01) (mass ("2nd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-02) (mass ("Monday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-03) (mass ("Tuesday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-04) (mass ("Wednesday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-05) (mass ("Thursday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-06) (mass ("Friday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-07) (mass ("Saturday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-08) (mass ("3rd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-09) (mass ("Monday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-10) (mass ("Tuesday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-11) (mass ("Wednesday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-12) (mass ("Thursday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-13) (mass ("Friday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-14) (mass ("Saturday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-15) (mass ("4th Sunday of Lent \226\128\147 L\195\166tare Sunday")) (cls (1)) (colour ("rose")) (praef ("Lent"))) + ((date 2026-03-16) (mass ("Monday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-17) (mass ("Tuesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-18) (mass ("Wednesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-19) (mass ("St. Joseph, Spouse of the BVM")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2026-03-20) (mass ("Friday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-21) (mass ("Saturday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2026-03-22) (mass ("Passion Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-23) (mass ("Monday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-24) (mass ("Tuesday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-25) (mass ("Annunciation of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2026-03-26) (mass ("Thursday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-27) (mass ("Friday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-28) (mass ("Saturday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-29) (mass ("and Palm Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-30) (mass ("Monday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-03-31) (mass ("Tuesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-04-01) (mass ("Wednesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2026-04-02) (mass ("Holy Thursday")) (cls (1)) (colour ("white")) (praef ("Holy Cross"))) + ((date 2026-04-03) (mass ("Good Friday")) (cls (1)) (colour ("black")) (praef ())) + ((date 2026-04-04) (mass ("and Easter Vigil Mass")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-05) (mass ("Easter Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-06) (mass ("Easter Monday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-07) (mass ("Easter Tuesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-08) (mass ("Easter Wednesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-09) (mass ("Easter Thursday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-10) (mass ("Easter Friday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-11) (mass ("Easter Saturday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-12) (mass ("Low Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-13) (mass ("St.Hermenegild, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-14) (mass ("St. Justin, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-15) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-16) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-17) (mass ("St. Anicetus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-18) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-04-19) (mass ("Second Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-20) (mass ("Feria - Second Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-21) (mass ("St. Anselm, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-22) (mass ("Ss. Soter & Cajus, Popes & Martyrs")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-23) (mass ("St. George, Martyr")) (cls (4)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-24) (mass ("St. Fidelis. Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-25) (mass ("St. Mark, Evangelist")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-04-26) (mass ("Third Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-27) (mass ("St. Peter Canisius, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-28) (mass ("St. Paul of the Cross, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-04-29) (mass ("St. Peter of Verona, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-04-30) (mass ("St. Catherine of Siena, Virgin")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-01) (mass ("St. Joseph the Workman, Confessor")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2026-05-02) (mass ("St. Athanasius, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-03) (mass ("Fourth Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-04) (mass ("St. Monica, Widow")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-05) (mass ("St. Pius V, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-06) (mass ("St. John before the Latin Gate")) (cls (4)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-05-07) (mass ("St. Stanislaus, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-05-08) (mass ("Apparition of St. Michael")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-09) (mass ("St. Gregory Nanzianzen, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-10) (mass ("5th Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-11) (mass ("Ss. Philip & James, Apostles")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-05-12) (mass ("Ss. Nereus, Achilleus, Domitila, & Pancras, Martyrs")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2026-05-13) (mass ("Vigil of Ascension")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2026-05-14) (mass ("Ascension of Our Lord")) (cls (1)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-15) (mass ("St. John Baptist de la Salle, Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-16) (mass ("St. Ubald, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-17) (mass ("Sunday after the Ascension")) (cls (2)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-18) (mass ("St. Venantius, Martyr")) (cls (3)) (colour ("red")) (praef ("Ascension"))) + ((date 2026-05-19) (mass ("St. Peter Celestine, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-20) (mass ("St. Bernardine of Siena, Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-21) (mass ("Feria - Ascension")) (cls (4)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-22) (mass ("Feria - Ascension")) (cls (4)) (colour ("white")) (praef ("Ascension"))) + ((date 2026-05-23) (mass ("Vigil of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-24) (mass ("Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-25) (mass ("Monday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-26) (mass ("Tuesday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-27) (mass ("Ember Wednesday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-28) (mass ("Thursday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-29) (mass ("Ember Friday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-30) (mass ("Ember Saturday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2026-05-31) (mass ("Trinity Sunday")) (cls (1)) (colour ("white")) (praef ("Holy Trinity"))) + ((date 2026-06-01) (mass ("St. Angela Merici, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-02) (mass ("Ss. Marcellinus, Peter, & Erasmus, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-06-03) (mass ("Feria - First Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-06-04) (mass ("Corpus Christi")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-05) (mass ("St. Boniface, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-06-06) (mass ("St. Norbert, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-07) (mass ("Second Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-06-08) (mass ("Feria - Second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-06-09) (mass ("Ss. Primus & Felician, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-06-10) (mass ("St. Margaret, Queen of Scotland, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-11) (mass ("St. Barnabas, Apostle")) (cls (3)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-06-12) (mass ("Most Sacred Heart of Jesus")) (cls (1)) (colour ("white")) (praef ("Sacred Heart"))) + ((date 2026-06-13) (mass ("St. Anthony of Padua, Doctor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-14) (mass ("Third Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-06-15) (mass ("Ss. Vitus, Modestus, & Crescentia, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-06-16) (mass ("Feria - Third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-06-17) (mass ("St. Gregory Barbarigo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-18) (mass ("St. Ephrem of Syria, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-19) (mass ("St. Juliana Falconieri, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-20) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-06-21) (mass ("Fourth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-06-22) (mass ("St. Paulinus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-23) (mass ("Vigil of Nativity of St. John the Baptist")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2026-06-24) (mass ("Nativity of St. John the Baptist")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-25) (mass ("St. William, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-06-26) (mass ("Ss. John & Paul, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-06-27) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-06-28) (mass ("Fifth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-06-29) (mass ("Ss. Peter & Paul, Apostles")) (cls (1)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-06-30) (mass ("Commemoration of St. Paul, Apostle")) (cls (3)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-07-01) (mass ("Most Precious Blood of Our Lord")) (cls (1)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2026-07-02) (mass ("Visitation of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2026-07-03) (mass ("St. Irenaeus, Doctor of the Church")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-04) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-07-05) (mass ("Sixth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-07-06) (mass ("St. Maria Goretti, Virgin Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-07) (mass ("Ss. Cyril & Methodius, Bishops & Confessors")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-08) (mass ("St. Elizabeth of Portugal, Queen & Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-09) (mass ("Feria - Sixth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-07-10) (mass ("Seven Holy Brothers, & Ss. Rufina & Secunda, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-11) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-07-12) (mass ("Seventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-07-13) (mass ("Feria - Seventh Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-07-14) (mass ("St. Bonaventure, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-15) (mass ("St. Henry II, Emperor, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-16) (mass ("Our Lady of Mt. Carmel")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-07-17) (mass ("St. Alexius, Confessor")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-18) (mass ("St. Camillus de Lellis, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-19) (mass ("Eighth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-07-20) (mass ("St. Jerome Emiliani, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-21) (mass ("St. Lawrence of Brindisi, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-22) (mass ("St. Mary Magdalene, Penitent")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-23) (mass ("St. Apollinarus, Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-24) (mass ("St. Christina, Virgin & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-25) (mass ("St. James the Greater, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-07-26) (mass ("Ninth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-07-27) (mass ("St. Pantaleon, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-28) (mass ("Ss. Nazarius & Celsus, Martyrs, Victor I, Pope & Martyr,")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-29) (mass ("St. Martha, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-07-30) (mass ("Ss. Abdon & Sennen, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-07-31) (mass ("St. Ignatius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-01) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-08-02) (mass ("Tenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-08-03) (mass ("The Finding of the Body of St. Stephen")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-04) (mass ("St. Dominic, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-05) (mass ("Our Lady of the Snows")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2026-08-06) (mass ("Transfiguration of Our Lord")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-07) (mass ("St. Cajetan, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-08) (mass ("St. John Mary Vianney, Confessor & Priest")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-09) (mass ("Eleventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-08-10) (mass ("St. Lawrence, Deacon & Martyr")) (cls (2)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-11) (mass ("Ss. Tiburtius & Susanna, Virgin, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-12) (mass ("St. Clare, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-13) (mass ("Ss. Hippolytus & Cassian, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-14) (mass ("Vigil of the Assumption")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2026-08-15) (mass ("Assumption of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2026-08-16) (mass ("Twelfth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-08-17) (mass ("St. Hyacinth of Poland, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-18) (mass ("St. Agapitus, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-19) (mass ("St. John Eudes, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-20) (mass ("St. Bernard of Clairvaux, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-21) (mass ("St. Jane Frances de Chantal, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-22) (mass ("Immaculate Heart of Mary")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2026-08-23) (mass ("Thirteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-08-24) (mass ("St. Bartholomew, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-08-25) (mass ("St. Louis IX, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-26) (mass ("St. Zephirynus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-27) (mass ("St. Joseph Calasanctius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-28) (mass ("St. Augustine, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-08-29) (mass ("Beheading of St. John the Baptist")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-08-30) (mass ("Fourteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-08-31) (mass ("St. Raymond Nonnatus, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-01) (mass ("St. Giles, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-02) (mass ("St. Stephen, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-03) (mass ("St. Pius X, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-04) (mass ("Feria - Fourteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-09-05) (mass ("St. Lawrence Justinian, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-06) (mass ("Fifteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-09-07) (mass ("Feria - Fifteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-09-08) (mass ("Nativity of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2026-09-09) (mass ("St. Gorgonius, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-09-10) (mass ("St. Nicholas of Tolentino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-11) (mass ("Ss. Protus & Hyacinth, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-09-12) (mass ("Most Holy Name of Mary")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2026-09-13) (mass ("Sixteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-09-14) (mass ("Exaltation of the Holy Cross")) (cls (2)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2026-09-15) (mass ("Seven Sorrows of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2026-09-16) (mass ("St. Cornelius, Pope, & St. Cyprian, Bishop, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-09-17) (mass ("Stigmata of St. Francis")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-18) (mass ("St. Joseph of Cupertino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-19) (mass ("St. Januarius, Bishop, & Companions, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-09-20) (mass ("Seventeenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-09-21) (mass ("St. Matthew, Apostle & Evangelist")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-09-22) (mass ("St. Thomas of Villanova, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-23) (mass ("Ember Wednesday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2026-09-24) (mass ("Our Lady of Ransom")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-09-25) (mass ("Ember Friday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2026-09-26) (mass ("Ember Saturday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2026-09-27) (mass ("Eighteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-09-28) (mass ("St. Wenceslaus, Duke, Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-09-29) (mass ("St. Michael the Archangel")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2026-09-30) (mass ("St. Jerome, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-01) (mass ("St. Remigius, Bishop & Confessor")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-02) (mass ("Holy Guardian Angels")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-03) (mass ("St. Teresa of the Child Jesus, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-04) (mass ("Nineteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-10-05) (mass ("Ss. Placid & Companions, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-10-06) (mass ("St. Bruno, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-07) (mass ("Our Lady of the Rosary")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2026-10-08) (mass ("St. Bridget, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-09) (mass ("St. John Leonard, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-10) (mass ("St. Francis Borgia, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-11) (mass ("Twentieth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-10-12) (mass ("Feria - Twentieth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-10-13) (mass ("St. Edward, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-14) (mass ("St. Callistus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-10-15) (mass ("St. Teresa of Avila, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-16) (mass ("St. Hedwig, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-17) (mass ("St. Margaret Mary Alacoque, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-18) (mass ("Twenty-first Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-10-19) (mass ("St. Peter of Alcantara, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-20) (mass ("St. John Cantius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-21) (mass ("St. Hilarion, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-22) (mass ("Feria - Twenty-first Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-10-23) (mass ("St. Anthony Mary Claret, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-24) (mass ("St. Raphael the Archangel")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-10-25) (mass ("Christ the King")) (cls (1)) (colour ("white")) (praef ("Christ the King"))) + ((date 2026-10-26) (mass ("St. Evaristus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-10-27) (mass ("Feria - Twenty-second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-10-28) (mass ("Ss. Simon & Jude, Apostles")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-10-29) (mass ("Feria - Twenty-second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-10-30) (mass ("Feria - Twenty-second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-10-31) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-11-01) (mass ("All Saints")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-02) (mass ("All Souls - Mass 1")) (cls (1)) (colour ("black")) (praef ("For the Dead"))) + ((date 2026-11-03) (mass ("Feria - Twenty-third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-11-04) (mass ("St. Charles Borromeo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-05) (mass ("The Holy Relics")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2026-11-06) (mass ("Feria - Twenty-third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2026-11-07) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-11-08) (mass ("Resumed 5th Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-11-09) (mass ("Dedication of the Archbasilica of Our Holy Savior")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-10) (mass ("St. Andrew Avellino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-11) (mass ("St. Martin of Tours, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-12) (mass ("St. Martin I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-11-13) (mass ("St. Didacus, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-14) (mass ("St. Josaphat, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-11-15) (mass ("Resumed 6th Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-11-16) (mass ("St. Gertrude, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-17) (mass ("St. Gregory Thaumaturgus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-18) (mass ("Dedication of the Basilicas of Ss. Peter & Paul")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-19) (mass ("St. Elizabeth of Hungary, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-20) (mass ("St. Felix of Valois, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-21) (mass ("Presentation of the BVM")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2026-11-22) (mass ("Last Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2026-11-23) (mass ("St. Clement I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-11-24) (mass ("St. John of the Cross, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-25) (mass ("St. Catherine of Alexandria, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2026-11-26) (mass ("St. Sylvester, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2026-11-27) (mass ("Our Lady of the Miraculous Medal")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2026-11-28) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) +) diff --git a/test/fixtures/efdotorg-ordo-2026-2027.sexp b/test/fixtures/efdotorg-ordo-2026-2027.sexp new file mode 100644 index 0000000..dc95641 --- /dev/null +++ b/test/fixtures/efdotorg-ordo-2026-2027.sexp @@ -0,0 +1,398 @@ +; test/fixtures/efdotorg-ordo-2026-2027.sexp -- efdotorg-preface task +; (2026-08-24-colitur-celebrant-rubrics-phase1): the THIRD independent +; preface witness (RG 482-499), extraordinaryform.org's 2026-2027 Ordo, +; extracted from the already-parsed, fidelity-audited corpus +; docs/research/ordo/ordo-2024-2027.json (SHA-256 18a417fb8b30dc438c3f12f64b43dfdf5e2e9313857f2eccd04bf02072ca7e3c) rather than +; re-parsed from the PDF -- see tools/extract_efdotorg_ordo.py's own +; header for the full characterisation this fixture rests on (the menu- +; trap office filter, the Christ-the-King classifier-gap recovery, why +; "Advent" is not baked into a single mapping here, the known Vigil-of- +; St-Lawrence gap, and the two source-PDF defects that turn out not to +; touch this field). +; +; Generator: tools/extract_efdotorg_ordo.py -- do not hand-edit; re-run +; against the same JSON and commit the diff instead. +; python3 tools/extract_efdotorg_ordo.py docs/research/ordo/ordo-2024-2027.json test/fixtures +; +; Source PDF (gitignored, CLAUDE.md: "docs/ is gitignored", see +; docs/research/ordo/SHA256SUMS for its own hash): 2026-2027Ordo.pdf, +; extraordinaryform.org. +; +; COVERAGE: 364 day-rows, 2026-11-29..2027-11-27 (this edition's own civil-date +; span, re-derived from the JSON's own seams -- see the generator's own +; EDITIONS comment). 1 row(s) are a genuine SOURCE GAP (2027-03-03 +; only, a PDF row-drop, ordo-fidelity-report.md) -- mass/cls/colour/praef +; all absent, the same shape a structurally blank day (Good Friday) uses. +; 1 further row(s) have mass/cls/colour but no praef at all +; (Good Friday -- RG 28, no Mass in the 1955-restored Holy Week). +; +; Each row's `praef` is RAW TEXT from the day's own OFFICE (after the +; menu-trap filter, with the Christ-the-King recovery already applied) -- +; classified against {!Colitur_kernel.Preface.t} by +; test/test_efdotorg_ordo.ml, not here. +( + ((date 2026-11-29) (mass ("First Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-11-30) (mass ("St. Andrew, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-12-01) (mass ("Feria \226\128\147 First Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-02) (mass ("St. Bibiana, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Advent"))) + ((date 2026-12-03) (mass ("St. Francis Xavier, Confessor")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2026-12-04) (mass ("St. Peter Chrysologus, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2026-12-05) (mass ("Feria \226\128\147 First Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-06) (mass ("Second Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-07) (mass ("St. Ambrose, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2026-12-08) (mass ("Immaculate Conception")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2026-12-09) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-10) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-11) (mass ("St. Damasus I, Pope")) (cls (3)) (colour ("white")) (praef ("Advent"))) + ((date 2026-12-12) (mass ("Feria \226\128\147 Second Sunday of Advent")) (cls (3)) (colour ("rose")) (praef ("Advent"))) + ((date 2026-12-13) (mass ("Third Sunday of Advent \226\128\147 Gaudete")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-14) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-15) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (3)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-16) (mass ("Ember Wednesday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-17) (mass ("Feria \226\128\147 Third Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-18) (mass ("Ember Friday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-19) (mass ("Ember Saturday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-20) (mass ("Fourth Sunday of Advent")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-21) (mass ("St. Thomas, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2026-12-22) (mass ("Feria - Fourth Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-23) (mass ("Feria - Fourth Sunday of Advent")) (cls (2)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-24) (mass ("Vigil of Nativity of Our Lord")) (cls (1)) (colour ("violet")) (praef ("Advent"))) + ((date 2026-12-25) (mass ("Nativity of Our Lord - Mass at Midnight")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-12-26) (mass ("Day II in the Octave, St. Stephen, Protomartyr")) (cls (2)) (colour ("red")) (praef ("Nativity"))) + ((date 2026-12-27) (mass ("Sunday within the Octave of Christmas")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-12-28) (mass ("Day IV in the Octave, Holy Innocents")) (cls (2)) (colour ("red")) (praef ("Nativity"))) + ((date 2026-12-29) (mass ("Day V in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-12-30) (mass ("Day VI in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2026-12-31) (mass ("Day VII in the Octave")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2027-01-01) (mass ("Day VIII in the Octave, Circumcision of Our Lord")) (cls (1)) (colour ("white")) (praef ("Nativity"))) + ((date 2027-01-02) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-01-03) (mass ("Holy Name of Jesus")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2027-01-04) (mass ("Feria in Christmastide")) (cls (4)) (colour ("white")) (praef ("Nativity"))) + ((date 2027-01-05) (mass ("St. Telesphorus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Nativity"))) + ((date 2027-01-06) (mass ("Epiphany of Our Lord")) (cls (1)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-07) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-08) (mass ("Feria of Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-09) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-01-10) (mass ("Holy Family")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-11) (mass ("St. Hyginus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Epiphany"))) + ((date 2027-01-12) (mass ("Feria after Epiphany")) (cls (4)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-13) (mass ("Baptism of Our Lord")) (cls (2)) (colour ("white")) (praef ("Epiphany"))) + ((date 2027-01-14) (mass ("St. Hilary, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-15) (mass ("St. Paul, First Hermit, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-16) (mass ("St. Marcellus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-17) (mass ("Second Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-01-18) (mass ("St. Prisca, Virgin & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-19) (mass ("Ss. Marius, Martha, Audifax, & Abachum, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-20) (mass ("Ss. Fabian, Pope, & Sebastian, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-21) (mass ("St. Agnes, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-22) (mass ("Ss. Vincent & Anastasius, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-23) (mass ("St. Raymund of Pennafort, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-24) (mass ("Septuagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2027-01-25) (mass ("Conversion of St. Paul, Apostle")) (cls (3)) (colour ("white")) (praef ("Apostles"))) + ((date 2027-01-26) (mass ("St. Polycarp, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-27) (mass ("St. John Chrysostom, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-28) (mass ("St. Peter Nolasco, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-29) (mass ("St. Francis de Sales, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-01-30) (mass ("St. Martina, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-01-31) (mass ("Sexagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2027-02-01) (mass ("St. Ignatius of Antioch, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-02-02) (mass ("and Purification of BVM")) (cls (2)) (colour ("white")) (praef ("Nativity"))) + ((date 2027-02-03) (mass ("St. Blaise, Bishop & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-02-04) (mass ("St. Andrew Corsini, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-02-05) (mass ("St. Agatha, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-02-06) (mass ("St. Titus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-02-07) (mass ("Quinquagesima")) (cls (2)) (colour ("violet")) (praef ("Holy Trinity"))) + ((date 2027-02-08) (mass ("St. John of Matha, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-02-09) (mass ("St. Cyril, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-02-10) (mass ("and Ash Wednesday")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-11) (mass ("Thursday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-12) (mass ("Friday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-13) (mass ("Saturday after Ash Wednesday")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-14) (mass ("1st Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-15) (mass ("Monday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-16) (mass ("Tuesday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-17) (mass ("Ember Wednesday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-18) (mass ("Thursday after the 1st Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-19) (mass ("Ember Friday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-20) (mass ("Ember Saturday of Lent")) (cls (2)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-21) (mass ("2nd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-22) (mass ("Chair of St. Peter")) (cls (2)) (colour ("white")) (praef ("Apostles"))) + ((date 2027-02-23) (mass ("Tuesday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-24) (mass ("St. Matthias, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-02-25) (mass ("Thursday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-26) (mass ("Friday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-27) (mass ("Saturday after the 2nd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-02-28) (mass ("3rd Sunday of Lent")) (cls (1)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-01) (mass ("Monday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-02) (mass ("Wednesday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-03) (mass ()) (cls ()) (colour ()) (praef ())) + ((date 2027-03-04) (mass ("Thursday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-05) (mass ("Friday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-06) (mass ("Saturday after the 3rd Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-07) (mass ("4th Sunday of Lent \226\128\147 L\195\166tare Sunday")) (cls (1)) (colour ("rose")) (praef ("Lent"))) + ((date 2027-03-08) (mass ("Monday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-09) (mass ("Tuesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-10) (mass ("Wednesday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-11) (mass ("Thursday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-12) (mass ("Friday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-13) (mass ("Saturday after the 4th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Lent"))) + ((date 2027-03-14) (mass ("Passion Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-15) (mass ("Monday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-16) (mass ("Tuesday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-17) (mass ("Wednesday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-18) (mass ("Thursday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-19) (mass ("St. Joseph, Spouse of the BVM")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2027-03-20) (mass ("Saturday after the 5th Sunday of Lent")) (cls (3)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-21) (mass ("and Palm Sunday")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-22) (mass ("Monday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-23) (mass ("Tuesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-24) (mass ("Wednesday of Holy Week")) (cls (1)) (colour ("violet")) (praef ("Holy Cross"))) + ((date 2027-03-25) (mass ("Holy Thursday")) (cls (1)) (colour ("white")) (praef ("Holy Cross"))) + ((date 2027-03-26) (mass ("Good Friday")) (cls (1)) (colour ("black")) (praef ())) + ((date 2027-03-27) (mass ("and Easter Vigil Mass (circa midnight)")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-03-28) (mass ("Easter Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-03-29) (mass ("Easter Monday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-03-30) (mass ("Easter Tuesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-03-31) (mass ("Easter Wednesday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-01) (mass ("Easter Thursday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-02) (mass ("Easter Friday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-03) (mass ("Easter Saturday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-04) (mass ("Low Sunday")) (cls (1)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-05) (mass ("Annunciation of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2027-04-06) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-07) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-08) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-09) (mass ("Feria - First Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-10) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-04-11) (mass ("Second Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-12) (mass ("Feria - Second Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-13) (mass ("St.Hermenegild, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-14) (mass ("St. Justin, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-15) (mass ("Feria - Second Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-16) (mass ("Feria - Second Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-17) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-04-18) (mass ("Third Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-19) (mass ("Feria - Third Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-20) (mass ("Feria - Third Sunday after Easter")) (cls (4)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-21) (mass ("St. Anselm, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-22) (mass ("Ss. Soter & Cajus, Popes & Martyrs")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-23) (mass ("St. George, Martyr")) (cls (4)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-24) (mass ("St. Fidelis. Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-25) (mass ("Fourth Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-26) (mass ("Ss. Cletus & Marcellinus, Popes & Martyrs")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-27) (mass ("St. Peter Canisius, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-28) (mass ("St. Paul of the Cross, Confessor")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2027-04-29) (mass ("St. Peter of Verona, Martyr")) (cls (3)) (colour ("red")) (praef ("Easter"))) + ((date 2027-04-30) (mass ("St. Catherine of Siena, Virgin")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2027-05-01) (mass ("St. Joseph the Workman, Confessor")) (cls (1)) (colour ("white")) (praef ("St. Joseph"))) + ((date 2027-05-02) (mass ("5th Sunday after Easter")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2027-05-03) (mass ("Ss. Alexander, Eventius, & Theodulus, Martyrs")) (cls (4)) (colour ("red")) (praef ("Easter"))) + ((date 2027-05-04) (mass ("St. Monica, Widow")) (cls (3)) (colour ("white")) (praef ("Easter"))) + ((date 2027-05-05) (mass ("Vigil of Ascension")) (cls (2)) (colour ("white")) (praef ("Easter"))) + ((date 2027-05-06) (mass ("Ascension of Our Lord")) (cls (1)) (colour ("white")) (praef ("Ascension"))) + ((date 2027-05-07) (mass ("St. Stanislaus, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Ascension"))) + ((date 2027-05-08) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-05-09) (mass ("Sunday after the Ascension")) (cls (2)) (colour ("white")) (praef ("Ascension"))) + ((date 2027-05-10) (mass ("St. Antoninus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2027-05-11) (mass ("Ss. Philip & James, Apostles")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-05-12) (mass ("Ss. Nereus, Achilleus, Domitila, & Pancras, Martyrs")) (cls (3)) (colour ("red")) (praef ("Ascension"))) + ((date 2027-05-13) (mass ("St. Robert Bellarmine, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Ascension"))) + ((date 2027-05-14) (mass ("St. Boniface, Martyr")) (cls (4)) (colour ("red")) (praef ("Ascension"))) + ((date 2027-05-15) (mass ("Vigil of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-16) (mass ("Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-17) (mass ("Monday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-18) (mass ("Tuesday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-19) (mass ("Ember Wednesday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-20) (mass ("Thursday after Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-21) (mass ("Ember Friday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-22) (mass ("Ember Saturday of Pentecost")) (cls (1)) (colour ("red")) (praef ("Holy Spirit"))) + ((date 2027-05-23) (mass ("Trinity Sunday")) (cls (1)) (colour ("white")) (praef ("Holy Trinity"))) + ((date 2027-05-24) (mass ("Feria - First Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-05-25) (mass ("St. Gregory VII, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-05-26) (mass ("St. Philip Neri, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-05-27) (mass ("Corpus Christi")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2027-05-28) (mass ("St. Augustine of Canterbury, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-05-29) (mass ("St. Mary Magdalen de Pazzi, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-05-30) (mass ("Second Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-05-31) (mass ("Queenship of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-06-01) (mass ("St. Angela Merici, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-02) (mass ("Ss. Marcellinus, Peter, & Erasmus, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-06-03) (mass ("Feria - Second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-06-04) (mass ("Most Sacred Heart of Jesus")) (cls (1)) (colour ("white")) (praef ("Sacred Heart"))) + ((date 2027-06-05) (mass ("St. Boniface, Bishop & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-06-06) (mass ("Third Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-06-07) (mass ("Feria - Third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-06-08) (mass ("Feria - Third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-06-09) (mass ("Ss. Primus & Felician, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-06-10) (mass ("St. Margaret, Queen of Scotland, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-11) (mass ("St. Barnabas, Apostle")) (cls (3)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-06-12) (mass ("St. John of San Facundo, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-13) (mass ("Fourth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-06-14) (mass ("St. Basil the Great, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-15) (mass ("Ss. Vitus, Modestus, & Crescentia, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-06-16) (mass ("Feria - Fourth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-06-17) (mass ("St. Gregory Barbarigo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-18) (mass ("St. Ephrem of Syria, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-19) (mass ("St. Juliana Falconieri, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-20) (mass ("Fifth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-06-21) (mass ("St. Aloysius Gonzaga, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-22) (mass ("St. Paulinus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-23) (mass ("Vigil of Nativity of St. John the Baptist")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-06-24) (mass ("Nativity of St. John the Baptist")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-25) (mass ("St. William, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-06-26) (mass ("Ss. John & Paul, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-06-27) (mass ("Sixth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-06-28) (mass ("Vigil of Ss. Peter & Paul")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-06-29) (mass ("Ss. Peter & Paul, Apostles")) (cls (1)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-06-30) (mass ("Commemoration of St. Paul, Apostle")) (cls (3)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-07-01) (mass ("Most Precious Blood of Our Lord")) (cls (1)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2027-07-02) (mass ("Visitation of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-07-03) (mass ("St. Irenaeus, Doctor of the Church")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-04) (mass ("Seventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-07-05) (mass ("St. Anthony Mary Zaccaria, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-06) (mass ("St. Maria Goretti, Virgin Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-07) (mass ("Ss. Cyril & Methodius, Bishops & Confessors")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-08) (mass ("St. Elizabeth of Portugal, Queen & Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-09) (mass ("Feria - Seventh Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-07-10) (mass ("Seven Holy Brothers, & Ss. Rufina & Secunda, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-11) (mass ("Eighth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-07-12) (mass ("St. John Gualbert, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-13) (mass ("Feria - Eighth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-07-14) (mass ("St. Bonaventure, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-15) (mass ("St. Henry II, Emperor, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-16) (mass ("Our Lady of Mt. Carmel")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-07-17) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-07-18) (mass ("Ninth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-07-19) (mass ("St. Vincent de Paul, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-20) (mass ("St. Jerome Emiliani, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-21) (mass ("St. Lawrence of Brindisi, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-22) (mass ("St. Mary Magdalene, Penitent")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-23) (mass ("St. Apollinarus, Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-24) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-07-25) (mass ("Tenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-07-26) (mass ("St. Anne, Mother of the BVM")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-27) (mass ("St. Pantaleon, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-28) (mass ("Ss. Nazarius & Celsus, Martyrs, Victor I, Pope & Martyr,")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-29) (mass ("St. Martha, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-07-30) (mass ("Ss. Abdon & Sennen, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-07-31) (mass ("St. Ignatius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-01) (mass ("Eleventh Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-08-02) (mass ("St. Alphonsus of Liguori, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-03) (mass ("The Finding of the Body of St. Stephen")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-04) (mass ("St. Dominic, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-05) (mass ("Our Lady of the Snows")) (cls (3)) (colour ("white")) (praef ("BVM"))) + ((date 2027-08-06) (mass ("Transfiguration of Our Lord")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-07) (mass ("St. Cajetan, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-08) (mass ("Twelfth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-08-09) (mass ("St. Romanus, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-10) (mass ("St. Lawrence, Deacon & Martyr")) (cls (2)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-11) (mass ("Ss. Tiburtius & Susanna, Virgin, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-12) (mass ("St. Clare, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-13) (mass ("Ss. Hippolytus & Cassian, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-14) (mass ("Vigil of the Assumption")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-08-15) (mass ("Assumption of the BVM")) (cls (1)) (colour ("white")) (praef ("BVM"))) + ((date 2027-08-16) (mass ("St. Joachim, Father of the BVM")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-17) (mass ("St. Hyacinth of Poland, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-18) (mass ("St. Agapitus, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-19) (mass ("St. John Eudes, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-20) (mass ("St. Bernard of Clairvaux, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-21) (mass ("St. Jane Frances de Chantal, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-22) (mass ("Fourteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-08-23) (mass ("St. Philip Benizi, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-24) (mass ("St. Bartholomew, Apostle")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-08-25) (mass ("St. Louis IX, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-26) (mass ("St. Zephirynus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-08-27) (mass ("St. Joseph Calasanctius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-28) (mass ("St. Augustine, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-29) (mass ("Fifteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-08-30) (mass ("St. Rose of Lima, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-08-31) (mass ("St. Raymond Nonnatus, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-01) (mass ("St. Giles, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-02) (mass ("St. Stephen, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-03) (mass ("St. Pius X, Pope & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-04) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-09-05) (mass ("Sixteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-09-06) (mass ("Feria - Sixteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-09-07) (mass ("Feria - Sixteenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-09-08) (mass ("Nativity of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-09-09) (mass ("St. Gorgonius, Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-10) (mass ("St. Nicholas of Tolentino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-11) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-09-12) (mass ("Seventeenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-09-13) (mass ("Feria - Seventeenth Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-09-14) (mass ("Exaltation of the Holy Cross")) (cls (2)) (colour ("red")) (praef ("Holy Cross"))) + ((date 2027-09-15) (mass ("Seven Sorrows of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-09-16) (mass ("St. Cornelius, Pope, & St. Cyprian, Bishop, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-17) (mass ("Stigmata of St. Francis")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-18) (mass ("St. Joseph of Cupertino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-19) (mass ("Eighteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-09-20) (mass ("St. Eustace & Companions, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-21) (mass ("St. Matthew, Apostle & Evangelist")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-09-22) (mass ("Ember Wednesday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-09-23) (mass ("St. Linus, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-24) (mass ("Ember Friday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-09-25) (mass ("Ember Saturday")) (cls (2)) (colour ("violet")) (praef ("Common"))) + ((date 2027-09-26) (mass ("Nineteenth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-09-27) (mass ("Ss. Cosmas & Damian, Martyrs")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-28) (mass ("St. Wenceslaus, Duke, Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-09-29) (mass ("St. Michael the Archangel")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2027-09-30) (mass ("St. Jerome, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-01) (mass ("St. Remigius, Bishop & Confessor")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-02) (mass ("Holy Guardian Angels")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-03) (mass ("Twentieth Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-10-04) (mass ("St. Francis of Assisi, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-05) (mass ("Ss. Placid & Companions, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-10-06) (mass ("St. Bruno, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-07) (mass ("Our Lady of the Rosary")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-10-08) (mass ("St. Bridget, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-09) (mass ("St. John Leonard, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-10) (mass ("Twenty-first Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-10-11) (mass ("Maternity of the BVM")) (cls (2)) (colour ("white")) (praef ("BVM"))) + ((date 2027-10-12) (mass ("Feria - Twenty-first Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-10-13) (mass ("St. Edward, King, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-14) (mass ("St. Callistus I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-10-15) (mass ("St. Teresa of Avila, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-16) (mass ("St. Hedwig, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-17) (mass ("Twenty-second Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-10-18) (mass ("St. Luke the Evangelist")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-10-19) (mass ("St. Peter of Alcantara, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-20) (mass ("St. John Cantius, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-21) (mass ("St. Hilarion, Abbot")) (cls (4)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-22) (mass ("Feria - Twenty-second Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-10-23) (mass ("St. Anthony Mary Claret, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-10-24) (mass ("Twenty-third Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-10-25) (mass ("Ss. Chrysanthus & Darius, Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-10-26) (mass ("St. Evaristus, Pope & Martyr")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-10-27) (mass ("Feria - Twenty-third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-10-28) (mass ("Ss. Simon & Jude, Apostles")) (cls (2)) (colour ("red")) (praef ("Apostles"))) + ((date 2027-10-29) (mass ("Feria - Twenty-third Sunday after Pentecost")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-10-30) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-10-31) (mass ("Christ the King")) (cls (1)) (colour ("white")) (praef ("Christ the King"))) + ((date 2027-11-01) (mass ("All Saints")) (cls (1)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-02) (mass ("All Souls - Mass 1")) (cls (1)) (colour ("black")) (praef ("For the Dead"))) + ((date 2027-11-03) (mass ("Feria - Resumed 4th Sunday after Epiphany")) (cls (4)) (colour ("green")) (praef ("Common"))) + ((date 2027-11-04) (mass ("St. Charles Borromeo, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-05) (mass ("The Holy Relics")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-06) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) + ((date 2027-11-07) (mass ("Resumed 5th Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-11-08) (mass ("Four Holy Crowned Martyrs")) (cls (4)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-09) (mass ("Dedication of the Archbasilica of Our Holy Savior")) (cls (2)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-10) (mass ("St. Andrew Avellino, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-11) (mass ("St. Martin of Tours, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-12) (mass ("St. Martin I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-13) (mass ("St. Didacus, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-14) (mass ("Resumed 6th Sunday after Epiphany")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-11-15) (mass ("St. Albert the Great, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-16) (mass ("St. Gertrude, Virgin")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-17) (mass ("St. Gregory Thaumaturgus, Bishop & Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-18) (mass ("Dedication of the Basilicas of Ss. Peter & Paul")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-19) (mass ("St. Elizabeth of Hungary, Widow")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-20) (mass ("St. Felix of Valois, Confessor")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-21) (mass ("Last Sunday after Pentecost")) (cls (2)) (colour ("green")) (praef ("Holy Trinity"))) + ((date 2027-11-22) (mass ("St. Cecilia, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-23) (mass ("St. Clement I, Pope & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-24) (mass ("St. John of the Cross, Doctor of the Church")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-25) (mass ("St. Catherine of Alexandria, Virgin & Martyr")) (cls (3)) (colour ("red")) (praef ("Common"))) + ((date 2027-11-26) (mass ("St. Sylvester, Abbot")) (cls (3)) (colour ("white")) (praef ("Common"))) + ((date 2027-11-27) (mass ("Saturday of Our Lady")) (cls (4)) (colour ("white")) (praef ("BVM"))) +) diff --git a/test/fixtures/fiuv-ordo-2025-2026.sexp b/test/fixtures/fiuv-ordo-2025-2026.sexp new file mode 100644 index 0000000..2ea9913 --- /dev/null +++ b/test/fixtures/fiuv-ordo-2025-2026.sexp @@ -0,0 +1,1817 @@ +; test/fixtures/fiuv-ordo-2025-2026.sexp -- Witnesses task (2026-08-22-colitur- +; celebrant-rubrics-phase1)'s SEVENTH validation layer, and the first +; UNIVERSAL (non-diocesan), SECOND-COMPILER witness: the FIUV (Foederatio +; Internationalis Una Voce) Ordo, compiled independently of the Latin Mass +; Society's own three editions (test/test_lms_ordo.ml) -- see +; docs/research/ordo/PROVENANCE-ordo-corpus.md for the full four-reasons +; account of why this source is the more valuable of the two newly- +; acquired ones. +; +; Generator: tools/extract_fiuv_ordo.ml -- do not hand-edit; re-run +; against a fresh pdftotext dump and commit the diff instead. +; +; Source: "Ordo Divini Officii recitandi sacrique peragendi secundum +; antiquam Ritus Romani formam pro anno Domini 2026", Foederatio +; Internationalis Una Voce, compiled by Joseph Shaw (Praefatio signed +; "Joseph Shaw, President", Feast of the Nativity of Our Lady [8 Sept] +; 2025) -- title page and Praefatio, verified directly against the PDF's +; own extracted text. 2025 is stated as the Federation's own 60th +; anniversary year. +; PDF metadata: Creator "TeX", Producer "pdfTeX-1.40.22", CreationDate +; 2025-11-08, 128 pages. +; URL: identified via web search as +; https://lms.org.uk/sites/default/files/u5374/fiuv_ordo_2025-2026_1.1_a5_format.pdf +; (hosted by the Latin Mass Society's own site alongside its own three +; editions -- Joseph Shaw is both FIUV President and LMS Chairman, which +; plausibly also explains why this PDF's own trailing malformed entry +; (see COVERAGE below) is structurally identical to the LMS PDFs' own, +; despite the two being compiled by different people); NOT independently +; re-downloaded and byte-compared in this session -- recorded honestly +; rather than presented as verified, the same discipline the LMS +; fixtures' own headers use. +; The local PDF (docs/research/ordo/fiuv-ordo-2025-2026.pdf) is gitignored (CLAUDE.md: "docs/ +; is gitignored"), so this header, not git, is this fixture's only record +; of where it came from. +; SHA-256 of docs/research/ordo/fiuv-ordo-2025-2026.pdf: 4335cc112b5fb6ec4d9511465ccc9381bed9b6056a56bc82dbaa5b2d85d0d855 +; Extracted (UTC): 2026-08-22 +; Exact commands: +; pdftotext -layout docs/research/ordo/fiuv-ordo-2025-2026.pdf /tmp/fiuv.txt +; dune exec tools/extract_fiuv_ordo.exe -- /tmp/fiuv.txt \ +; docs/research/ordo/fiuv-ordo-2025-2026.pdf test/fixtures/fiuv-ordo-2025-2026.sexp +; +; COVERAGE: 400 day-rows, 2025-11-27 through 2026-12-31. Starts at the book's own first +; real content line ("November MMXXV", the FIRST month header found with +; a parseable Roman-numeral year -- used as this parser's sole date +; anchor, see the tool's own header on why no LATER header's year is ever +; read, the second one being a publisher typo, "December MMXV" for 2025). +; Stops before a malformed trailing entry, structurally the SAME artefact +; found in all three LMS editions (a stray, mislabelled duplicate of the +; fixture's own already-extracted 1 January row, headed "1st Jan / 2025." +; -- see extract_lms_ordo.ml's own COVERAGE section for the fuller +; account of this shared publisher-side quirk). +; +; CHARACTERISATION FINDINGS (non-negotiable per the task brief -- the +; extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; this Ordo was probed with the same discipline +; before a single divergence was adjudicated): +; +; 1. UNIVERSAL, not diocesan: unlike the three LMS editions (which had to +; exclude diocesan variants from every comparison, quantified in each +; of their own fixture headers), this Ordo carries ONE block per day, +; always. There is no [has_diocesan_variant] field in this fixture's +; own [row] at all -- there is nothing to exclude. +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN against its own extracted +; [rows] before this header was even written -- a failed probe is a +; hard [die], never a printed claim: +; 2025-11-30 (Advent Sunday, I class, RG 475(a)) -> TRUE +; 2025-12-01 (ordinary Advent feria, III class, RG 476(b)/(d)) -> FALSE +; 2025-12-26 (St Stephen, II class, inside the Nativity octave, RG 475(d)) -> TRUE +; 2026-08-10 (St Laurence, II class martyr, no Lord/BVM/apostle clause applies, RG 476(b)) -> FALSE +; 2026-08-15 (the Assumption, I class, RG 475(b)) -> TRUE +; All 5 predictions confirmed, both directions -- this source is +; discriminating, not a constant, on the Creed. +; +; 3. THE SUBSTRING TRAP this parser defends against, found live in this +; corpus: "Gloria" is also the first word of "Gloria Patri" (the psalm +; doxology), which can appear INSIDE the very Mass clause being +; scanned (Good Friday, 3 April 2026: "Missa pr., (omittuntur ps. +; Iudica me et Gloria Patri), Gloria, sine Credo, praef. comm." -- the +; real, standalone Gloria mention follows immediately after). See +; [find_word]'s own citation. +; +; 4. RAW SUBSTRING COUNTS measured against this session's own pdftotext +; dump, for comparison against the task brief's own figures (328 +; Gloria / 132 sine Gloria / 119 Credo / 260 sine Credo, 262 Te Deum): +; "sine Gloria" 132 (EXACT match), "sine Credo" 260 (EXACT match), raw +; "Te Deum" substring 262 (EXACT match, includes negated occurrences +; as substring hits -- 42 of them are "non dicitur Te Deum"). Raw +; "Gloria"/"Credo" substring totals (494/411) do NOT match the brief's +; implied positive totals (328/119) even after subtracting the 25 +; "Gloria Patri" occurrences (469, still 9 over) -- not chased further +; here; this extractor's own token-scoped, Missa-clause-bounded counts +; below are what this fixture actually asserts, not a forced match to +; the brief's approximate figures. +; +; 5. THE ALTERNATIVE-OFFICE TRAP (celebrant-rubrics-phase1 Phase 2 +; correction, 2026-08-22, closing F3): six real days print BOTH a +; strict-1962 reading and a complete SECOND office (the same saint +; kept outright under the 2020 decree Cum Sanctissima), separated by +; a literal "-VEL-" token. [extract_te_deum] used to scan the WHOLE +; block unbounded, so on these six days -- whose PRIMARY office states +; no "Ad Mat." of its own -- it silently read the SECOND office's own +; Te Deum instead, manufacturing a same-day contradiction with colitur +; that F3 first recorded as "colitur's own possible gap". Every field +; now reads the PRIMARY office only (module header point 5 has the +; full account); the alternative is captured, not discarded, in its +; own [alt_te_deum] field. Confirmed to fire on EXACTLY six dates by a +; hard characterisation probe (this run's own output, above), not +; merely asserted here. +; +; MEASURED DISTRIBUTION (this extraction, not the brief's figures): Gloria +; true=269 false=130 unresolved=1; Credo true=116 false=283 unresolved=1; +; Te Deum true=201 false=66 unresolved=133; alt Te Deum (the six "-VEL-" +; Cum Sanctissima alternatives, point 5 above) true=6 false=0 none=394 +; (a day contributes to "none" here either because it has no "-VEL-" +; alternative at all -- 394 of 400 -- or, for a day that does, because +; that alternative's own text doesn't state Te Deum either; not +; distinguished by this one count). +; +; FIX HISTORY (fixed text, HISTORICAL counts from the run that found each +; bug, not re-verified live by every later run -- this section exists so +; regenerating this fixture from a fresh pdftotext dump, which rewrites +; this whole header from the template, does not silently erase either +; finding; earlier this header carried the first entry below as a +; hand-appended note that a regeneration between then and now had +; already dropped once): +; +; 1. RE-EXTRACTED (celebrant-rubrics-phase1 Phase 2, 2026-08-22): the FIRST +; extraction's own Te Deum parser recognised only ONE of the source's two +; negative phrasings ("non dicitur Te Deum") -- "sine Te Deum" (how the +; source actually negates a SUNDAY's own Te Deum, among others) fell +; through to a bare "Te Deum" substring match and was wrongly read +; [true]. Found by hand, comparing the raw pdftotext dump against this +; fixture's own values directly, not by any coverage check (both counted +; the same 127 unresolved rows before and after). Fixed in +; tools/extract_fiuv_ordo.ml's own [extract_te_deum] (see its own +; citation); this fixture re-extracted from the SAME pdftotext dump +; (SHA-256 of the source PDF unchanged, above). 24 of 400 rows changed, +; every one Te Deum true->false, every one independently confirmed +; against the raw text: true 231->207, false 42->66, unresolved 127 +; unchanged. See lib/rites/rite_ef/rubrics_ef.ml's own [te_deum] header +; (237(a)'s comment) for the full account of what this corrected, and +; the .superpowers task report for the complete before/after date list. +; +; 2. RE-EXTRACTED (celebrant-rubrics-phase1 Phase 2 correction, 2026-08-22): +; module header point 5 and CHARACTERISATION point 5 above have the +; full account of the "-VEL-" alternative-office bug this closes +; (data/ef/expected-divergences-fiuv.sexp's own F3). This fixture +; re-extracted from the SAME pdftotext dump (SHA-256 of the source PDF +; unchanged, above). 6 of 400 rows changed, every one Te Deum +; true->unresolved (2026-03-06/07/09/12/21/24), every one independently +; confirmed against the raw text: Te Deum true 207->201 (this run's own +; unresolved count went 127->133, consistent with those same 6 rows). +; Gloria/Credo/class_/title/praef are UNCHANGED on all 400 rows -- +; those fields were already correctly bounded to the primary office +; before this fix (a Vespers-line token always intervened before the +; "-VEL-" separator on all six real instances), confirmed by a direct +; diff of the fixture before and after, not merely by argument. +; +; 3. RE-EXTRACTED (celebrant-rubrics-phase1 same correction, defensive +; hardening, 2026-08-22): auditing for the SAME trap elsewhere (the +; task brief's own item 5) found a THIRD, narrower alternate-Mass +; marker, "Vel (sec. decretum <<Cum sanct.>>) Missa ...", offering a +; Cum-Sanctissima Mass FORMULARY choice within a single office +; (unlike point 5 above, no second "Ad Mat." set of lessons -- a +; narrower thing than a full alternate office). 20 occurrences in the +; whole corpus, confirmed by direct grep; on all 20, Gloria/Credo were +; ALREADY stated before reaching this marker, so this was NEVER a +; live divergence for those two fields (confirmed by this same diff: +; 0 Gloria/Credo/class_/title/alt_te_deum rows changed). [praef] +; alone changed on 20 of 400 rows (its own "rest of the primary +; clause" capture no longer runs past this marker into the +; alternative's own text) -- harmless in itself ([praef] is +; documented CAPTURED, NOT VALIDATED, compared by nothing), but added +; as a defensive boundary in [extract_missa_fields] so a FUTURE year +; whose primary clause does not restate Gloria/Credo before this +; marker cannot silently read the alternative's own value instead -- +; the identical failure shape as point 2 above, closed before it was +; ever observed live rather than after. +(((date 2025-11-27) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XXIV & Ultima post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2025-11-28) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XXIV & Ultima post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2025-11-29) (class_ ("IV cl.")) + (title "Alb Sabb. S. Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2025-11-30) (class_ ("I cl.")) + (title "Viol DOM. I ADVENTUS, De ea,") (te_deum (false)) (gloria (false)) + (credo (true)) (praef ("Trinit. Ad II")) (alt_te_deum ())) + ((date 2025-12-01) (class_ ("III cl.")) + (title "Viol Feria II post Dom. I Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-02) (class_ ("III cl.")) + (title "Rub Feria III. S Bibianae Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. AD")) + (alt_te_deum ())) + ((date 2025-12-03) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Francisci Xavierii Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. AD")) (alt_te_deum ())) + ((date 2025-12-04) (class_ ("III cl.")) + (title "Alb Feria V. S Petri Chrysologi Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2025-12-05) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. I Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("comm. Feria VI prima in mense.")) (alt_te_deum ())) + ((date 2025-12-06) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Nicolai Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Sabbatum primum in mense. I")) (alt_te_deum ())) + ((date 2025-12-07) (class_ ("I cl.")) + (title "Viol DOM. II ADVENTUS, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2025-12-08) (class_ ("I cl.")) + (title "Alb Feria II. IN CONCEPTIONE IMMACULATA B. MARIAE VIRGINIS,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("BMV Et te in Conceptione Immaculata. AD")) (alt_te_deum ())) + ((date 2025-12-09) (class_ ("III cl.")) + (title "Viol Feria III post Dom. II Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-10) (class_ ("III cl.")) + (title "Viol Feria IV post Dom. II Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-11) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Damasi I Papae et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. AD")) (alt_te_deum ())) + ((date 2025-12-12) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. II Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-13) (class_ ("III cl. (Priv.)")) + (title "Rub Sabb. S Luciae Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. I")) + (alt_te_deum ())) + ((date 2025-12-14) (class_ ("I cl.")) + (title "Viol/ DOM. III ADVENTUS (GAUDETE), De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2025-12-15) (class_ ("III cl.")) + (title "Viol Feria II post Dom. III Adventus (Gaudete), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2025-12-16) (class_ ("III cl.")) + (title "Alb Feria III. S Eusebii Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. AD")) (alt_te_deum ())) + ((date 2025-12-17) (class_ ("II cl.")) + (title "Viol FERIA IV QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("comm.\226\128\147 Quoad Flectamus genua vide RM 440.")) + (alt_te_deum ())) + ((date 2025-12-18) (class_ ("II cl.")) + (title "Viol FERIA V POST DOM. III ADVENTUS (GAUDETE), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2025-12-19) (class_ ("II cl.")) + (title "Viol FERIA VI QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-20) (class_ ("II cl.")) + (title "Viol SABB. QUATTUOR TEMP., De eo,") (te_deum ()) (gloria (false)) + (credo (false)) + (praef + ("comm. \226\128\147 Quoad Flectamus genua vide RM 440. Quoad lectiones vide RM 468. I")) + (alt_te_deum ())) + ((date 2025-12-21) (class_ ("I cl.")) + (title "Viol DOM. IV ADVENTUS, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2025-12-22) (class_ ("II cl.")) + (title "Viol FERIA II POST DOM. IV ADVENTUS, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-23) (class_ ("II cl.")) + (title "Viol FERIA III POST DOM. IV ADVENTUS, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2025-12-24) (class_ ("I cl.")) + (title "Viol Feria IV. VIGILIA NATIVITATIS DOMINI,") (te_deum (false)) + (gloria (false)) (credo (false)) (praef ("comm. I")) (alt_te_deum ())) + ((date 2025-12-25) (class_ ("I cl.")) + (title "Alb Feria V. IN NATIVITATE DOMINI,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef + ("et Communic. pr. per totam oct. \226\128\147 In Communicantes: in 1\194\170 Missa dicitur Noctem sacratissimam celebrantes, qua, in 2\194\170 et 3\194\170 Missa et per octavam Diem sacratissimum celebrantes, quo. \226\128\147 In 2\194\170 Missa (etiam in cantu) fit comm. S. Anastasi\195\166 * M. \226\128\147 In Missis in cantu, ad verba symboli Et incarnatus est\226\128\166 et homo factus est, omnes genuflectunt versus altare, non tantum cum a celebrante recitantur, sed etiam cum a choro canuntur (RM 518 b). II")) + (alt_te_deum ())) + ((date 2025-12-26) (class_ ("II cl.")) + (title "Rub Feria VI. S STEPHANI * PROTOMARTYRIS,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. AD")) + (alt_te_deum ())) + ((date 2025-12-27) (class_ ("II cl.")) + (title "Alb Sabb. S IOANNIS * AP. ET EV.,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. AD")) + (alt_te_deum ())) + ((date 2025-12-28) (class_ ("II cl.")) + (title "Alb DOM. INFRA OCTAVAM NATIVITATIS, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. Ad II")) + (alt_te_deum ())) + ((date 2025-12-29) (class_ ("II cl.")) + (title "Alb FERIA II DOM. INFRA OCTAVAM NATIVITATIS, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum.")) + (alt_te_deum ())) + ((date 2025-12-30) (class_ ("II cl.")) + (title "Alb FERIA III DOM. INFRA OCTAVAM NATIVITATIS, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum.")) + (alt_te_deum ())) + ((date 2025-12-31) (class_ ()) + (title + "Alb FERIA IV DOM. INFRA OCTAVAM NATIVITATIS, De ea. \226\128\147 Off. semifestivum. \226\128\147 Ad MAT. invit., hymnus, 9 antt. et 9 pss. cum ultimo V de festo Nativ., Ll. de Scr. occ. cum suis RR (ad 2um additur Gloria Patri)\226\128\147 Ad Laudes antt. de Nativ., pss. de dom., comm. S Silvestri I Papae et Conf. \226\128\147 Ad HORAS ant. et pss. de feria curr., rel ut in festo Nativ. \226\128\147 Ad Primam in R Br. V Qui natus es de Maria Virgine. Missa Puer natus de diebus infra octavam, Gloria, Credo, comm. S Silvestri I Papae et Conf., praef. de Nativ., Communic. de Nativ. diem sacratissimum. I VESPER\195\134 de seq. \226\128\147 Compl. de dom. Hodie ad solemnem recitationem hymni Te Deum, indulgentia plenaria lucrari potest. 16") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. I")) + (alt_te_deum ())) + ((date 2026-01-01) (class_ ("I cl.")) + (title "Al Feria V. OCTAVA NATIVITATIS,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. II")) + (alt_te_deum ())) + ((date 2026-01-02) (class_ ("IV cl.")) + (title "Alb Feria VI post Octavam Nativitatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("de Nativ., sine Communic. pr. Feria VI prima in mense.")) + (alt_te_deum ())) + ((date 2026-01-03) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-01-04) (class_ ("II cl.")) + (title "Alb Dom. SS.MI NOMINIS IESU,") (te_deum ()) (gloria (true)) + (credo (true)) (praef ("de Nativ., sine Communic. pr. II")) + (alt_te_deum ())) + ((date 2026-01-05) (class_ ("IV cl.")) + (title "Alb Feria II post Octavam Nativitatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("de Nativ., sine Communic. pr. \226\128\147")) (alt_te_deum ())) + ((date 2026-01-06) (class_ ("I cl.")) + (title "Alb Feria III. IN EPIPHANIA DOMINI,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("et Communic pr. II")) + (alt_te_deum ())) + ((date 2026-01-07) (class_ ("IV cl.")) + (title "Alb Feria IV post Epiphaniam, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("de Epiphania.")) + (alt_te_deum ())) + ((date 2026-01-08) (class_ ("IV cl.")) + (title "Alb Feria V post Epiphaniam, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("de Epiphania.")) + (alt_te_deum ())) + ((date 2026-01-09) (class_ ("IV cl.")) + (title "Alb Feria VI post Epiphaniam, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("de Epiphania.")) + (alt_te_deum ())) + ((date 2026-01-10) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione. I")) (alt_te_deum ())) + ((date 2026-01-11) (class_ ("II cl.")) + (title + "Alb Dom. I post Epiphaniam. SANCT\195\134 FAMILI\195\134 IESU, MARI\195\134, IOSEPH *,") + (te_deum ()) (gloria (true)) (credo (true)) (praef ("de Epiphania. II")) + (alt_te_deum ())) + ((date 2026-01-12) (class_ ("IV cl.")) + (title "Alb Feria II post Dom. I post Epiphaniam, De ea,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("de Epiphania.")) (alt_te_deum ())) + ((date 2026-01-13) (class_ ("II cl.")) + (title "Alb Feria III. IN COMMEMORATIONE BAPTISMATIS D.N.I.C.,") + (te_deum ()) (gloria (true)) (credo (true)) (praef ("de Epiphania. Ad")) + (alt_te_deum ())) + ((date 2026-01-14) (class_ ("III cl.")) + (title "Alb Feria IV. S Hilarii Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-01-15) (class_ ("III cl.")) + (title "Alb Feria V. S Pauli Primi Eremitae Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-01-16) (class_ ("III cl.")) + (title "Rub Feria VI. S Marcelli I Papae et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-01-17) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Antonii Abb.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. I")) (alt_te_deum ())) + ((date 2026-01-18) (class_ ("II cl.")) + (title "Vir DOM. II POST EPIPHANIAM, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-01-19) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. II post Epiphaniam, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-01-20) (class_ ("III cl. (Priv.)")) + (title "Rub Feria III. SS Fabiani Papae et Sebastiani Mm.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-01-21) (class_ ("III cl. (Priv.)")) + (title "Rub Feria IV. S Agnetis * Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. Ad")) + (alt_te_deum ())) + ((date 2026-01-22) (class_ ("III cl.")) + (title "Rub Feria V. SS Vincentii et Anastasii Mm.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-01-23) (class_ ("III cl.")) + (title "Alb Feria VI. S Raymundi de Pe\195\177afort Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-01-24) (class_ ("III cl. (Priv.)")) + (title "Rub Sabb. S Timothei Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. I")) + (alt_te_deum ())) + ((date 2026-01-25) (class_ ("II cl.")) + (title "Vir DOM. III POST EPIPHANIAM, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-01-26) (class_ ("III cl. (Priv.)")) + (title "Rub Feria II. S Polycarpi Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-01-27) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Ioannis Chrysostomi Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-01-28) (class_ ("III cl.")) + (title "Alb Feria IV. S Petri Nolasci Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-01-29) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Francisci Salesii Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-01-30) (class_ ("III cl.")) + (title "Rub Feria VI. S Martinae Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-01-31) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Ioannis Bosco Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. I")) (alt_te_deum ())) + ((date 2026-02-01) (class_ ("II cl.")) + (title "Viol DOM. SEPTUAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. II")) (alt_te_deum ())) + ((date 2026-02-02) (class_ ("II cl.")) + (title "Alb Feria II. IN PURIFICATIONE B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("de Nativ. Ad benedictionem candelarum: ut in Missali. Ad")) + (alt_te_deum ())) + ((date 2026-02-03) (class_ ("IV cl.")) + (title "Viol Feria III Dom. Septuagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-02-04) (class_ ("III cl.")) + (title "Alb Feria IV. S Andreae Corsini Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-02-05) (class_ ("III cl. (Priv.)")) + (title "Rub Feria V. S Agathae * Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. Ad")) + (alt_te_deum ())) + ((date 2026-02-06) (class_ ("III cl. (Priv.)")) + (title "Alb Feria VI. S Titi Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Feria VI prima in mense.")) (alt_te_deum ())) + ((date 2026-02-07) (class_ ("III cl.")) + (title "Alb Sabb. S Romualdi Abb.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. Sabbatum primum in mense. I")) + (alt_te_deum ())) + ((date 2026-02-08) (class_ ("II cl.")) + (title "Viol DOM. SEXAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. II")) (alt_te_deum ())) + ((date 2026-02-09) (class_ ("III cl.")) + (title "Alb Feria II. S Cyrilli Ep. Alexandrini, Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-02-10) (class_ ("III cl.")) + (title "Alb Feria III. S Scholasticae Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-02-11) (class_ ("III cl.")) + (title "Alb Feria IV. In Apparitione B. Mariae Virg. Immaculatae,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("BMV Et te in Conceptione Immaculata.")) (alt_te_deum ())) + ((date 2026-02-12) (class_ ("III cl.")) + (title + "Alb Feria V. SS Septem Fundatorum Ordinis Servorum B. Mariae Virg., Cc.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-02-13) (class_ ("IV cl.")) + (title "Viol Feria VI Dom. Sexagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-02-14) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-02-15) (class_ ("II cl.")) + (title "Viol DOM. QUINQUAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. II")) (alt_te_deum ())) + ((date 2026-02-16) (class_ ("IV cl.")) + (title "Viol Feria II Dom. Quinquagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-02-17) (class_ ("IV cl.")) + (title "Viol Feria III Dom. Quinquagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-02-18) (class_ ("I cl.")) + (title "Viol FERIA IV CINERUM, De ea,") (te_deum ()) (gloria (false)) + (credo (false)) + (praef + ("Quadr., or. super populum. In Missa qu\195\166 dicitur post benedictionem et impositionem cinerum omittuntur omnes preces ad gradus altaris dicend\195\166, necnon ors. Aufer a nobis et Oramus te, Domine, non autem osculum altaris (RM, 424 a).")) + (alt_te_deum ())) + ((date 2026-02-19) (class_ ("III cl.")) + (title "Viol Feria V Dom. Quinquagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-02-20) (class_ ("III cl.")) + (title "Viol Feria VI Dom. Quinquagesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-02-21) (class_ ("III cl.")) + (title "Viol Sabb. Dom. Quinquagesimae, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum. I")) + (alt_te_deum ())) + ((date 2026-02-22) (class_ ("I cl.")) + (title "Viol DOM. I QUADRAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Quadr. II")) (alt_te_deum ())) + ((date 2026-02-23) (class_ ("III cl.")) + (title "Viol Feria II post Dom. I Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-02-24) (class_ ("II cl.")) + (title "Rub Feria III. S MATTHIAE AP.,") (te_deum ()) (gloria (true)) + (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-02-25) (class_ ("II cl.")) + (title "Viol FERIA IV QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef + ("Quadr., or. super populum. \226\128\147 Quoad Flectamus genua vide RM 440.")) + (alt_te_deum ())) + ((date 2026-02-26) (class_ ("III cl.")) + (title "Viol Feria V post Dom. I Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-02-27) (class_ ("II cl.")) + (title "Viol FERIA VI QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-02-28) (class_ ("II cl.")) + (title "Viol SABB. QUATTUOR TEMP., De eo,") (te_deum ()) (gloria (false)) + (credo (false)) + (praef + ("Quadr., or. super populum. \226\128\147 Quoad Flectamus genua vide RM 440. Quoad lectiones vide RM 468. I")) + (alt_te_deum ())) + ((date 2026-03-01) (class_ ("I cl.")) + (title "Viol DOM. II QUADRAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Quadr. II")) (alt_te_deum ())) + ((date 2026-03-02) (class_ ("III cl.")) + (title "Viol Feria II post Dom. II Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-03) (class_ ("III cl.")) + (title "Viol Feria III post Dom. II Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-04) (class_ ("III cl.")) + (title "Viol Feria IV post Dom. II Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-05) (class_ ("III cl.")) + (title "Viol Feria V post Dom. II Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-06) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. II Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum. Feria VI prima in mense.")) + (alt_te_deum (true))) + ((date 2026-03-07) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. II Quadragesimae, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum. Sabbatum primum in mense. I")) + (alt_te_deum (true))) + ((date 2026-03-08) (class_ ("I cl.")) + (title "Viol DOM. III QUADRAGESIMAE, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Quadr. II")) (alt_te_deum ())) + ((date 2026-03-09) (class_ ("III cl.")) + (title "Viol Feria II post Dom. III Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum (true))) + ((date 2026-03-10) (class_ ("III cl.")) + (title "Viol Feria III post Dom. III Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-11) (class_ ("III cl.")) + (title "Viol Feria IV post Dom. III Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-12) (class_ ("III cl.")) + (title "Viol Feria V post Dom. III Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum (true))) + ((date 2026-03-13) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. III Quadragesimae, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum.")) + (alt_te_deum ())) + ((date 2026-03-14) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. III Quadragesimae, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("Quadr., or. super populum. I")) + (alt_te_deum ())) + ((date 2026-03-15) (class_ ("I cl.")) + (title "Viol/ DOM. IV QUADRAGESIMAE (LAETARE), De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Quadr. II")) (alt_te_deum ())) + ((date 2026-03-16) (class_ ("III cl.")) + (title "Viol Feria II post Dom. IV Quadragesimae (Laetare), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum.")) (alt_te_deum ())) + ((date 2026-03-17) (class_ ("III cl.")) + (title "Viol Feria III post Dom. IV Quadragesimae (Laetare), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum.")) (alt_te_deum ())) + ((date 2026-03-18) (class_ ("III cl.")) + (title "Viol Feria IV post Dom. IV Quadragesimae (Laetare), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum. I")) (alt_te_deum ())) + ((date 2026-03-19) (class_ ("I cl.")) + (title + "Alb Feria V. S IOSEPH * SPONSI B. MARIAE VIRG., CONF. ET ECCLESIAE UNIVERSAE PATRONI,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de S Iosepho Et te in festivitate. II")) (alt_te_deum ())) + ((date 2026-03-20) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. IV Quadragesimae (Laetare), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum.")) (alt_te_deum ())) + ((date 2026-03-21) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. IV Quadragesimae (Laetare), De eo,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef ("Quadr., or. super populum. I")) (alt_te_deum (true))) + ((date 2026-03-22) (class_ ("I cl.")) + (title "Viol DOM. I PASSIONIS, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("de Sancta Cruce. II")) + (alt_te_deum ())) + ((date 2026-03-23) (class_ ("III cl.")) + (title "Viol Feria II post Dom. I Passionis, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum.")) (alt_te_deum ())) + ((date 2026-03-24) (class_ ("III cl.")) + (title "Viol Feria III post Dom. I Passionis, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum. I")) (alt_te_deum (true))) + ((date 2026-03-25) (class_ ("I cl.")) + (title "Alb Feria IV. IN ANNUNTIATIONE B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("BMV Et te in Annuntiatione \226\128\147 In Missis in cantu, ad verba symboli Et incarnatus est\226\128\166 et homo factus est, omnes genuflectunt versus altare, non tantum cum a celebrante recitantur, sed etiam cum a choro canuntur (RM 518 b). II")) + (alt_te_deum ())) + ((date 2026-03-26) (class_ ("III cl.")) + (title "Viol Feria V post Dom. I Passionis, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum.")) (alt_te_deum ())) + ((date 2026-03-27) (class_ ("III cl.")) + (title "Viol Feria VI post Dom. I Passionis, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum.")) (alt_te_deum ())) + ((date 2026-03-28) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. I Passionis, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum. I")) (alt_te_deum ())) + ((date 2026-03-29) (class_ ("I cl.")) + (title + "Rub in Officio, Rub. ad Bened. ramorum et in Processione, Viol. in Missa. DOM. IN PALMIS, De ea,") + (te_deum (false)) (gloria (false)) (credo (true)) + (praef + ("de Sancta Cruce. \194\171Asperges\194\187 omittitur. \226\128\147 Benedictio palmorum et processio ante missam principalem celebrandae sunt. \226\128\147 Orationes praeparatoriae omittuntur. \226\128\147 Evangelium de passione secundum S Matthiam 26, 36-75; 27,1-60 legitur. Munda cor dicitur, celebrans autem (vel diaconus chronista) signum crucis nec super libro nec super se facit, necque librum osculatur, necque Laus tibi Domine dicit. \226\128\147 Evangelium finale omittitur. \226\128\147 In Missis sine processione, legitur in fine Evangelium Cum appropinquasset de benedictione ramorum. Sacerdotibus plures quam unam missam dicentibus licet Evangelium S Matthi\195\166 27, 45-52 legere potius quam Evangelium Passionis. II")) + (alt_te_deum ())) + ((date 2026-03-30) (class_ ("I cl.")) + (title "Viol FERIA II HEBDOMADAE SANCTAE, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("de Sancta Cruce or. super populum.")) (alt_te_deum ())) + ((date 2026-03-31) (class_ ("I cl.")) + (title "Viol FERIA II HEBDOMADAE SANCTAE, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef + ("de Sancta Cruce or. super populum. Passio secundum S Marcum 14, 32-72; 15,1-46. Munda cor dicitur, celebrans autem (vel diaconus chronista) signum crucis nec super libro nec super se facit, necque librum osculatur, necque Laus tibi Domine dicit.")) + (alt_te_deum ())) + ((date 2026-04-01) (class_ ("I cl.")) + (title "Viol FERIA IV HEBDOMADAE SANCTA, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef + ("de Sancta Cruce or. super populum. Passio secundum S Lucam 22, 39-71; 23, 1-53. Munda cor dicitur, celebrans autem (vel diaconus chronista) signum crucis nec super libro nec super se facit, necque librum osculatur, necque Laus tibi Domine dicit.")) + (alt_te_deum ())) + ((date 2026-04-02) (class_ ("I cl.")) + (title "Viol. in Off., Alb. in Missa. FERIA V IN CENA DOMINI, De ea,") + (te_deum ()) (gloria (true)) (credo (false)) + (praef + ("de Sancta Cruce, Communicantes, Hanc igitur et Qui pridie pr., ad triplex Agnus Dei ter respondetur miserere nobis. Osculum pacis non datur, et omittitur or. Domine Iesu Christe, qui dixisti.")) + (alt_te_deum ())) + ((date 2026-04-03) (class_ ("I cl.")) + (title + "Nig in Actione liturgica usque ad 4am partem, Viol. in S. Communione. FERIA VI IN PASSIONE ET MORTE DOMINI, De ea,") + (te_deum ()) (gloria (true)) (credo (false)) + (praef ("comm. Feria VI prima in mense.")) (alt_te_deum ())) + ((date 2026-04-04) (class_ ("I cl.")) + (title "Viol in Vig. pasch., Alb. in Missa. SABBATUM SANCTUM, De eo,") + (te_deum ()) (gloria ()) (credo ()) (praef ()) (alt_te_deum ())) + ((date 2026-04-05) (class_ ("I cl.")) + (title "Alb DOM. RESURRECTIONIS, De ea,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef + ("Pasch. (in hac potissimum die), Communic. et Hanc igitur pr., ad Ite, missa est additur duplex Alleluia. Hodie prohibentur omnes Missae defunctorum, etiam exsequialis.")) + (alt_te_deum ())) + ((date 2026-04-06) (class_ ("I cl.")) + (title "Alb FERIA II INFRA OCTAVAM PASCHATIS, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia.")) + (alt_te_deum ())) + ((date 2026-04-07) (class_ ("I cl.")) + (title "Alb FERIA III INFRA OCTAVAM PASCHATIS, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia.")) + (alt_te_deum ())) + ((date 2026-04-08) (class_ ("I cl.")) + (title "Alb FERIA IV INFRA OCTAVAM PASCHATIS, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia.")) + (alt_te_deum ())) + ((date 2026-04-09) (class_ ("I cl.")) + (title "Alb FERIA V INFRA OCTAVAM PASCHATIS, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia.")) + (alt_te_deum ())) + ((date 2026-04-10) (class_ ("I cl.")) + (title "Alb FERIA VI INFRA OCTAVAM PASCHATIS, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia.")) + (alt_te_deum ())) + ((date 2026-04-11) (class_ ("I cl.")) + (title "Alb SABBATUM IN ALBIS, De eo,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef + ("etc. ut in festo., ad Ite, missa est additur duplex Alleluia. I")) + (alt_te_deum ())) + ((date 2026-04-12) (class_ ("I cl.")) (title "Alb DOM. IN ALBIS,") + (te_deum (true)) (gloria (true)) (credo (true)) + (praef ("Pasch. \226\128\147 Ite Missa est sine Alleluia. II")) + (alt_te_deum ())) + ((date 2026-04-13) (class_ ("III cl.")) + (title "Rub Feria II. S Hermenegildi Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. vel de Martyribus. Ad")) + (alt_te_deum ())) + ((date 2026-04-14) (class_ ("III cl. (Priv.)")) + (title "Rub Feria III. S Iustini Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-04-15) (class_ ("IV cl.")) + (title "Alb Feria IV Dom. in Albis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (Pasch.)) (alt_te_deum ())) + ((date 2026-04-16) (class_ ("IV cl.")) + (title "Alb Feria V Dom. in Albis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-04-17) (class_ ("IV cl.")) + (title "Alb Feria VI Dom. in Albis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-04-18) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione. I")) (alt_te_deum ())) + ((date 2026-04-19) (class_ ("II cl.")) + (title "Alb DOM. III PASCHATIS, De ea,") (te_deum (true)) (gloria (true)) + (credo (true)) (praef ("Pasch. II")) (alt_te_deum ())) + ((date 2026-04-20) (class_ ("IV cl.")) + (title "Alb Feria II post Dom. III Paschatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (Pasch.)) (alt_te_deum ())) + ((date 2026-04-21) (class_ ("III cl.")) + (title "Alb Feria III. S Anselmi Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("Pasch. Ad")) + (alt_te_deum ())) + ((date 2026-04-22) (class_ ("III cl.")) + (title "Rub Feria IV. SS Soteris et Caii Pp. et Mm.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-04-23) (class_ ("IV cl.")) + (title "Alb Feria V post Dom. III Paschatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-04-24) (class_ ("III cl.")) + (title "Rub Feria VI. S Fidelis de Sigmaringa Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-04-25) (class_ ("II cl.")) + (title "Rub Sabb. LITANIA MAIOR. S MARCI EVANGELISTAE,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-04-26) (class_ ("II cl.")) + (title "Alb DOM. IV PASCHATIS, De ea,") (te_deum (true)) (gloria (true)) + (credo (true)) (praef ("Pasch. II")) (alt_te_deum ())) + ((date 2026-04-27) (class_ ("III cl.")) + (title "Alb Feria II. S Petri Canisii Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("Pasch. Ad")) + (alt_te_deum ())) + ((date 2026-04-28) (class_ ("III cl.")) + (title "Alb Feria III. S Pauli a Cruce Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-04-29) (class_ ("III cl.")) + (title "Rub Feria IV. S Petri Mart.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("Pasch. vel de Martyribus \226\128\147")) + (alt_te_deum ())) + ((date 2026-04-30) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Catharinae Senensis Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. I")) (alt_te_deum ())) + ((date 2026-05-01) (class_ ("I cl.")) + (title + "Alb Feria VI. S IOSEPH * OPIFICIS SPONSI B. MARIAE VIRG., CONF.,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("de S Iosepho Et te in solemnitate \226\128\147 Etiam dici potest Missa Adiutor (cfr. in Missis votivis), cum Alleluia pasch., praef. S Ioseph Et et in solemnitate. Feria VI prima in mense. II")) + (alt_te_deum ())) + ((date 2026-05-02) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Athanasii Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("Pasch. Sabbatum primum in mense. I")) (alt_te_deum ())) + ((date 2026-05-03) (class_ ("II cl.")) + (title "Alb DOM. V PASCHATIS, De ea,") (te_deum (true)) (gloria (true)) + (credo (true)) (praef ("Pasch. II")) (alt_te_deum ())) + ((date 2026-05-04) (class_ ("III cl. (Priv.)")) + (title "Alb Feria II. S Monicae Vid.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef (Pasch.)) (alt_te_deum ())) + ((date 2026-05-05) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Pii V Papae et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. Ad")) (alt_te_deum ())) + ((date 2026-05-06) (class_ ("IV cl.")) + (title "Alb Feria IV post Dom. V Paschatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-05-07) (class_ ("III cl.")) + (title "Rub Feria V. S Stanislai Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-05-08) (class_ ("IV cl.")) + (title "Alb Feria VI post Dom. V Paschatis, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. \226\128\147")) + (alt_te_deum ())) + ((date 2026-05-09) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Gregorii Nazianzeni Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("Pasch. I")) + (alt_te_deum ())) + ((date 2026-05-10) (class_ ("II cl.")) + (title "Alb DOM. VI PASCHATIS, De ea,") (te_deum (true)) (gloria (true)) + (credo (true)) (praef ("Pasch. II")) (alt_te_deum ())) + ((date 2026-05-11) (class_ ("II cl.")) + (title "Rub Feria II. SS PHILIPPI * & IACOBI * APP,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-05-12) (class_ ("III cl.")) + (title + "Rub Feria III. SS Nerei, Achillei, Domitillae Virg., & Pancratii Mm.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("Pasch. vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-05-13) (class_ ("II cl.")) + (title "Alb Feria IV. VIGILIA ASCENSIONIS,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Pasch. I")) (alt_te_deum ())) + ((date 2026-05-14) (class_ ("I cl.")) + (title "Alb Feria V. IN ASCENSIONE DOMINI NOSTRI IESU CHRISTI,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("Ascensionis, Communic pr. In Missa principali post Evangelium exstinguitur cereus paschalis. II")) + (alt_te_deum ())) + ((date 2026-05-15) (class_ ("III cl.")) + (title "Alb Feria VI. S Ioannis Baptistae de la Salle Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("Ascensionis \226\128\147")) (alt_te_deum ())) + ((date 2026-05-16) (class_ ("III cl.")) + (title "Alb Sabb. S Ubaldi Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Ascensionis \226\128\147")) + (alt_te_deum ())) + ((date 2026-05-17) (class_ ("II cl.")) + (title "Alb DOM. POST ASCENSIONEM, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) + (praef + ("Ascensionis. Hodie prohibentur omnes Missae defunctorum, excepta exsequiali.")) + (alt_te_deum ())) + ((date 2026-05-18) (class_ ("III cl.")) + (title "Rub Feria II. S Venantii Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("Ascensionis vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-05-19) (class_ ("III cl.")) + (title "Alb Feria III. S Petri Caelestini Papae et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("Ascensionis \226\128\147")) (alt_te_deum ())) + ((date 2026-05-20) (class_ ("III cl.")) + (title "Alb Feria IV. S Bernardini Senensis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (Ascensionis.)) (alt_te_deum ())) + ((date 2026-05-21) (class_ ("IV cl.")) + (title "Alb Feria V Dom. post Ascensionem, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (Ascensionis.)) (alt_te_deum ())) + ((date 2026-05-22) (class_ ("IV cl.")) + (title "Alb Feria VI Dom. post Ascensionem, De ea,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("Ascensionis \226\128\147")) + (alt_te_deum ())) + ((date 2026-05-23) (class_ ("I cl.")) + (title "Rub Sabb. VIGILIA PENTECOSTES,") (te_deum (true)) (gloria (true)) + (credo (false)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. I")) + (alt_te_deum ())) + ((date 2026-05-24) (class_ ("I cl.")) (title "Rub Dom. PENTECOSTES,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur. II")) + (alt_te_deum ())) + ((date 2026-05-25) (class_ ("I cl.")) + (title "Rub FERIA II INFRA OCTAVAM PENTECOSTES, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur.")) + (alt_te_deum ())) + ((date 2026-05-26) (class_ ("I cl.")) + (title "Rub FERIA III INFRA OCTAVAM PENTECOSTES, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur.")) + (alt_te_deum ())) + ((date 2026-05-27) (class_ ("I cl.")) + (title + "Rub FERIA IV QUATTUOR TEMPORUM INFRA OCTAVAM PENTECOSTES, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur.")) + (alt_te_deum ())) + ((date 2026-05-28) (class_ ("I cl.")) + (title "Rub FERIA V INFRA OCTAVAM PENTECOSTES, De ea,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur.")) + (alt_te_deum ())) + ((date 2026-05-29) (class_ ("I cl.")) + (title + "Rub FERIA VI QUATTUOR TEMPORUM INFRA OCTAVAM PENTECOSTES, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur.")) + (alt_te_deum ())) + ((date 2026-05-30) (class_ ("I cl.")) + (title + "Rub SABBATUM QUATTUOR TEMPORUM II INFRA OCTAVAM PENTECOSTES, De eo,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef + ("de Spirito Sancto hodierna die, Communic pr., Hanc igitur pr. \226\128\147 Genu flectendum est cum Veni Sancte Spiritus in versu Alleluia dicitur (quae in forma Miss\195\166 longiori post sixtam lectionem dicitur). Post Nonam exspirat tempus paschale. Compl de dom., cum antiphona finali de B. V. M. Salve Regina, quae dicitur ad Feriam VI ante Dom. I Adventus inclusive. Hodie prohibentur omnes Missae defunctorum, excepta exsequiali.")) + (alt_te_deum ())) + ((date 2026-05-31) (class_ ("I cl.")) + (title "Alb Dom. I post Pentecosten. IN FESTO SANCTISSIMAE TRINITATIS,") + (te_deum ()) (gloria (true)) (credo (true)) (praef ("Trinit. II")) + (alt_te_deum ())) + ((date 2026-06-01) (class_ ("III cl.")) + (title "Alb Feria II. S Angelae Mericiae Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-06-02) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. I post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-03) (class_ ("IV cl.")) + (title "Vir Feria IV post Dom. I post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef ("comm. I")) + (alt_te_deum ())) + ((date 2026-06-04) (class_ ("I cl.")) + (title "Alb Feria V. CORPORIS CHRISTI,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef + ("comm. vel de Cor Sacratissimo. \226\128\147 Si processio cum benedicto sacramento post missam principalem fit, in Missa Benedicamus Domino dicitur, sed benedictio et evangelium finale omittuntur. II")) + (alt_te_deum ())) + ((date 2026-06-05) (class_ ("III cl. (Priv.)")) + (title "Rub Feria VI. S Bonifatii Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus. Feria VI prima in mense.")) + (alt_te_deum ())) + ((date 2026-06-06) (class_ ("III cl.")) + (title "Alb Sabb. S Norberti Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Sabbatum primum in mense. I")) (alt_te_deum ())) + ((date 2026-06-07) (class_ ("II cl.")) + (title "Vir DOM. II POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-06-08) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. II post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-06-09) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. II post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-10) (class_ ("III cl.")) + (title "Alb Feria IV. S Margaritae Reginae, Vid.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-06-11) (class_ ("III cl. (Priv.)")) + (title "Rub Feria V. S Barnabae Apostoli,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("App. I")) (alt_te_deum ())) + ((date 2026-06-12) (class_ ("I cl.")) + (title "Alb Feria VI. SACRATISSIMI CORDIS IESU,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Ss.mi Corde Iesu. Hodie, in qualibet ecclesia, coram Ss. Sacramento exposito, legatur formula reparationis et cantentur vel recitentur Litani\195\166 Sacratissimi Cordis Iesu (cfr. Enchiridion Indulgentiarum. Preces et pia opera, 1952, n.256, p.163). II")) + (alt_te_deum ())) + ((date 2026-06-13) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Antonii de Padua Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-14) (class_ ("II cl.")) + (title "Vir DOM. III POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-06-15) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. III post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-16) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. III post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-17) (class_ ("III cl.")) + (title "Alb Feria IV. S Gregorii Barbadici Ep. et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-06-18) (class_ ("III cl.")) + (title "Alb Feria V. S Ephraem Syri Diaconi, Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-06-19) (class_ ("III cl.")) + (title "Alb Feria VI. S Iulianae De Falconeriis Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-06-20) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-06-21) (class_ ("II cl.")) + (title "Vir DOM. IV POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-06-22) (class_ ("III cl.")) + (title "Alb Feria II. S Paulini Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-06-23) (class_ ("II cl.")) + (title "Viol Feria III. VIGILIA NATIVITATIS S IOANNIS * BAPTISTAE,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef ("comm. I")) + (alt_te_deum ())) + ((date 2026-06-24) (class_ ("I cl.")) + (title "Alb Feria IV. IN NATIVITATE S IOANNIS * BAPTISTAE,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("comm. vel de S Ioanni Baptista. II")) (alt_te_deum ())) + ((date 2026-06-25) (class_ ("III cl.")) + (title "Alb Feria V. S Gulielmi Abb.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-06-26) (class_ ("III cl.")) + (title "Rub Feria VI. SS Ioannis * et Pauli * Mm.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-06-27) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-06-28) (class_ ("II cl.")) + (title "Vir DOM. V POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. I")) (alt_te_deum ())) + ((date 2026-06-29) (class_ ("I cl.")) + (title "Rub Feria II. SS PETRI * ET PAULI * APP.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("App. II")) (alt_te_deum ())) + ((date 2026-06-30) (class_ ("III cl. (Priv.)")) + (title "Rub Feria III. In Commemoratione S Pauli * Ap.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("App. I")) + (alt_te_deum ())) + ((date 2026-07-01) (class_ ("I cl.")) + (title "Rub Feria IV. PRETIOSISSIMI SANGUINIS D. N. I. C.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("de Sancta Cruce. II")) + (alt_te_deum ())) + ((date 2026-07-02) (class_ ("II cl.")) + (title "Alb Feria V. IN VISITATIONE B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Visitatione. Ad")) + (alt_te_deum ())) + ((date 2026-07-03) (class_ ("III cl.")) + (title "Rub Feria VI. S Iren\195\166i Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus. Feria VI prima in mense.")) + (alt_te_deum ())) + ((date 2026-07-04) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-07-05) (class_ ("II cl.")) + (title "Vir DOM. VI POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-07-06) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. VI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-07) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. SS Cyrilli et Methodii Epp. et Cc.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-07-08) (class_ ("III cl.")) + (title "Alb Feria IV. S Elisabeth Reginae, Vid.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. Ad")) (alt_te_deum ())) + ((date 2026-07-09) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. VI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-10) (class_ ("III cl.")) + (title + "Rub Feria VI. SS Septem Fratrum Mm., Ac SS Rufinae et Secundae Vv. et Mm.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-07-11) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-07-12) (class_ ("II cl.")) + (title "Vir DOM. VII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-07-13) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. VII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-07-14) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Bonaventurae Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-07-15) (class_ ("III cl.")) + (title "Alb Feria IV. S Henrici Imperatoris Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-07-16) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. VII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-17) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. VII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-18) (class_ ("III cl.")) + (title "Alb Sabb. S Camilli de Lellis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-07-19) (class_ ("II cl.")) + (title "Vir DOM. VIII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-07-20) (class_ ("III cl.")) + (title "Alb Feria II. S Hieronymi \211\148miliani Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-21) (class_ ("III cl.")) + (title "Alb Feria III. S Laurentii de Brundusio Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-22) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Mariae Magdalenae P\197\147nitentis,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-07-23) (class_ ("III cl.")) + (title "Rub Feria V. S Apollinaris Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus \226\128\147")) (alt_te_deum ())) + ((date 2026-07-24) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. VIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-25) (class_ ("II cl.")) + (title "Rub Sabb. S IACOBI * APOSTOLI,") (te_deum ()) (gloria (true)) + (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-07-26) (class_ ("II cl.")) + (title "Vir DOM. IX POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-07-27) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. IX post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-28) (class_ ("III cl.")) + (title + "Rub Feria III. SS Nazarii et Celsi, Mm., Victoris I Papae et Mart. ac Inocentii I Papae et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-07-29) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Marthae Virg.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-07-30) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. IX post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-07-31) (class_ ("III cl. (Priv.)")) + (title "Alb Feria VI. S Ignatii Conf.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-01) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione \226\128\147")) + (alt_te_deum ())) + ((date 2026-08-02) (class_ ("II cl.")) + (title "Vir DOM. X POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-08-03) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. X post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-04) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Dominici Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-05) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. In Dedicatione S Mariae ad Nives,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("BMV Et te in Festivitate.")) (alt_te_deum ())) + ((date 2026-08-06) (class_ ("II cl.")) + (title "Alb Feria V. IN TRANSFIGURATIONE D. N. I. C.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("comm. II")) (alt_te_deum ())) + ((date 2026-08-07) (class_ ("III cl.")) + (title "Alb Feria VI. S Caietani Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-08-08) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Ioannis Mariae Vianney Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-08-09) (class_ ("II cl.")) + (title "Vir DOM. XI POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-08-10) (class_ ("II cl.")) + (title "Rub Feria II. S LAURENTII * MART.,") (te_deum ()) (gloria (true)) + (credo (false)) (praef ("comm. vel de Martyribus. II")) (alt_te_deum ())) + ((date 2026-08-11) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. XI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-12) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Clarae Virg.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-13) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-14) (class_ ("II cl.")) + (title "Viol Feria VI. VIGILIA ASSUMPTIONIS B. MARIAE VIRG.,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef ("comm. I")) + (alt_te_deum ())) + ((date 2026-08-15) (class_ ("I cl.")) + (title "Alb Sabb. IN ASSUMPTIONE B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Assumptione. Ad")) + (alt_te_deum ())) + ((date 2026-08-16) (class_ ("II cl.")) + (title "Vir DOM. XII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-08-17) (class_ ("III cl.")) + (title "Alb Feria II. S Hyacinthi Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-18) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. XII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-19) (class_ ("III cl.")) + (title "Alb Feria IV. S Ioannis Eudes Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-20) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Bernardi Abb. et Eccl. Doct.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-08-21) (class_ ("III cl.")) + (title + "Alb Feria VI. S Ioannae Franciscae Fr\195\169miot de Chantal Vid.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-08-22) (class_ ("II cl.")) + (title "Alb Sabb. IMMACULATI CORDIS B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Festivitate. Ad")) + (alt_te_deum ())) + ((date 2026-08-23) (class_ ("II cl.")) + (title "Vir DOM. XIII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-08-24) (class_ ("II cl.")) + (title "Rub Feria II. S BARTHOLOMAEI * AP.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef (App.)) (alt_te_deum ())) + ((date 2026-08-25) (class_ ("III cl.")) + (title "Alb Feria III. S Ludovici Regis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-26) (class_ ("IV cl.")) + (title "Vir Feria IV post Dom. XIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-27) (class_ ("III cl.")) + (title "Alb Feria V. S Iosephi Calasanctii Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-08-28) (class_ ("III cl. (Priv.)")) + (title "Alb Feria VI. S Augustini Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-08-29) (class_ ("III cl. (Priv.)")) + (title "Rub Sabb. In Decollatione S Ioannis * Baptistae,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de S Ioanni Baptista \226\128\147")) (alt_te_deum ())) + ((date 2026-08-30) (class_ ("II cl.")) + (title "Vir DOM. XIV POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-08-31) (class_ ("III cl.")) + (title "Alb Feria II. S Raymundi Nonnati Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-09-01) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. XIV post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-02) (class_ ("III cl.")) + (title "Alb Feria IV. S Stephani Regis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-09-03) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Pii X Papae et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. Ad")) (alt_te_deum ())) + ((date 2026-09-04) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XIV post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-05) (class_ ("III cl.")) + (title "Alb Sabb. S Laurentii Iustiniani Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Sabbatum primum in mense. I")) (alt_te_deum ())) + ((date 2026-09-06) (class_ ("II cl.")) + (title "Vir DOM. XV POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-09-07) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. XV post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-09-08) (class_ ("II cl.")) + (title "Alb Feria III. IN NATIVITATE B. MARIAE VIRG.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Nativitate. Ad")) + (alt_te_deum ())) + ((date 2026-09-09) (class_ ("IV cl.")) + (title "Vir Feria IV post Dom. XV post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-10) (class_ ("III cl.")) + (title "Alb Feria V. S Nicolai de Tolentino Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-09-11) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XV post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-12) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. Sanctissimi Nominis Mariae,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("BMV Et te in Festivitate. I")) + (alt_te_deum ())) + ((date 2026-09-13) (class_ ("II cl.")) + (title "Vir DOM. XVI POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-09-14) (class_ ("II cl.")) + (title "Rub Feria II. IN EXALTATIONE S CRUCIS,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Sancta Cruce. In Epistola ad verba Ut in nomine Iesu usque ad infernorum inclusive genuflectitur, item in Choro ab omnibus in Missa in cantu. II")) + (alt_te_deum ())) + ((date 2026-09-15) (class_ ("II cl.")) + (title "Alb Feria III. SEPTEM DOLORUM B. MARIAE VIRGINIS,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Transfixione. Ad")) + (alt_te_deum ())) + ((date 2026-09-16) (class_ ("III cl. (Priv.)")) + (title "Rub Feria IV. SS Cornelis * Papae et Cypriani * Ep., Mm.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus.")) (alt_te_deum ())) + ((date 2026-09-17) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XVI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-18) (class_ ("III cl.")) + (title "Alb Feria VI. S Iosephi de Cupertino Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-09-19) (class_ ("III cl.")) + (title "Rub Sabb. SS Ianuarii Ep. et Sociorum Mm.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. I")) + (alt_te_deum ())) + ((date 2026-09-20) (class_ ("II cl.")) + (title "Vir DOM. XVII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-09-21) (class_ ("II cl.")) + (title "Rub Feria II. S MATTHAEI * AP. ET EV.,") (te_deum ()) + (gloria (true)) (credo (true)) (praef (App.)) (alt_te_deum ())) + ((date 2026-09-22) (class_ ("III cl.")) + (title "Alb Feria III. S Thomae de Villanova Ep. et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-23) (class_ ("II cl.")) + (title "Viol FERIA IV QUATTUOR TEMP., De ea,") (te_deum (false)) + (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147 Quoad Flectamus genua vide RM 440.")) + (alt_te_deum ())) + ((date 2026-09-24) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XVII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-09-25) (class_ ("II cl.")) + (title "Viol FERIA VI QUATTUOR TEMP., De ea,") (te_deum (false)) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-09-26) (class_ ("II cl.")) + (title "Viol SABB. QUATTUOR TEMP., De eo,") (te_deum (false)) + (gloria (false)) (credo (false)) + (praef + ("comm. \226\128\147 Quoad Flectamus genua vide RM 440. Quoad lectiones vide RM 468. I")) + (alt_te_deum ())) + ((date 2026-09-27) (class_ ("II cl.")) + (title "Vir DOM. XVIII POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-09-28) (class_ ("III cl.")) + (title "Rub Feria II. S Wenceslai Ducis Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. I")) + (alt_te_deum ())) + ((date 2026-09-29) (class_ ("I cl.")) + (title "Alb Feria III. IN DEDICATIONE S MICHA\195\139LIS ARCHANGELI,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("comm. vel de Angelis. II")) (alt_te_deum ())) + ((date 2026-09-30) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Hieronymi Presbyteri, Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef ("comm. Ad")) + (alt_te_deum ())) + ((date 2026-10-01) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XVIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-02) (class_ ("III cl. (Priv.)")) + (title "Alb Feria VI. SS Angelorum Custodum,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef + ("comm. vel de Angelis. Feria VI prima in mense. Vesper\195\166 pr.")) + (alt_te_deum ())) + ((date 2026-10-03) (class_ ("III cl. (Priv.)")) + (title "Alb Sabb. S Teresiae a Iesu Infante Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef + ("comm. Sabbatum primum in mense. I Vesper\195\166 de seq. dom., ut in Psalt. de sabb, ad Magn. ant. Adaperiat (dom. I octobris), or. pr., sine comm. \226\128\147 Compl. de sabb.")) + (alt_te_deum ())) + ((date 2026-10-04) (class_ ("II cl.")) + (title "Vir DOM. XIX POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-10-05) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. XIX post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-06) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Brunonis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Vesper\195\166 de festo. 100")) (alt_te_deum ())) + ((date 2026-10-07) (class_ ("II cl.")) + (title "Alb Feria IV. B. MARIAE VIRG. A ROSARIO,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("BMV Et te in Festivitate. Ad")) + (alt_te_deum ())) + ((date 2026-10-08) (class_ ("III cl.")) + (title "Alb Feria V. S Birgittae Vid.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-09) (class_ ("III cl.")) + (title "Alb Feria VI. S Ioannis Leonardi Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-10-10) (class_ ("III cl.")) + (title "Alb Sabb. S Francisci Borgiae Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef + ("comm. I Vesper\195\166 de seq. dom., ut in Psalt. de sabb, ad Magn. ant. Refulsit sol (dom. II octobris), or. pr., sine comm. \226\128\147 Compl. de sabb.")) + (alt_te_deum ())) + ((date 2026-10-11) (class_ ("II cl.")) + (title "Vir DOM. XX POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-10-12) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. XX post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Vesper\195\166 de feria or. dom. pr\195\166c.")) + (alt_te_deum ())) + ((date 2026-10-13) (class_ ("III cl.")) + (title "Alb Feria III. S Eduardis Regis Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Vesper\195\166 de festo.")) (alt_te_deum ())) + ((date 2026-10-14) (class_ ("III cl. (Priv.)")) + (title "Rub Feria IV. S Callisti I Papae et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus. Vesper\195\166 de festo.")) + (alt_te_deum ())) + ((date 2026-10-15) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Teresiae Virg.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-16) (class_ ("III cl.")) + (title "Alb Feria VI. S Hedwigis Vid.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. Vesper\195\166 de festo.")) + (alt_te_deum ())) + ((date 2026-10-17) (class_ ("III cl.")) + (title "Alb Sabb. S Margaritae Mariae Alacoque Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef + ("comm. I Vesper\195\166 de seq. dom., ut in Psalt. de sabb, ad Magn. ant. Exaudiat Dominus (dom. IV octobris), or. pr., sine comm. \226\128\147 Compl. de sabb.")) + (alt_te_deum ())) + ((date 2026-10-18) (class_ ("II cl.")) + (title "Vir DOM. XXI POST PENTECOSTEN, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-10-19) (class_ ("III cl.")) + (title "Alb Feria II. S Petri de Alcantara Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Vesper\195\166 de festo.")) (alt_te_deum ())) + ((date 2026-10-20) (class_ ("III cl.")) + (title "Alb Feria III. S Ioannis Cantii Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. Vesper\195\166 de festo.")) (alt_te_deum ())) + ((date 2026-10-21) (class_ ("IV cl.")) + (title "Vir Feria IV post Dom. XXI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-22) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XXI post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Vesper\195\166 de feria or. dom. pr\195\166c.")) + (alt_te_deum ())) + ((date 2026-10-23) (class_ ("III cl.")) + (title "Alb Feria VI. S Antonii Mariae Claret Ep. et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-24) (class_ ("III cl.")) + (title "Alb Sabb. S Rapha\195\171lis Archangeli,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef + ("comm. vel de Angelis. I Vesper\195\166 de seq., sine comm. \226\128\147 Compl. de dom. 104")) + (alt_te_deum ())) + ((date 2026-10-25) (class_ ("I cl.")) + (title "Alb Dom. DOMINI NOSTRI JESU CHRISTI REGIS,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("de Domino Nostro Jesu Rege. Hodie, in omnibus ecclesiis, coram Ss.mo Sacramento exposito, recitetur formula consecrationis generis humani Christo Regi, cum Litaniis de eodem Sacro Corde. II Vesper\195\166 pr. Hodie prohibentur omnes Missae defunctorum, etiam exsequialis.")) + (alt_te_deum ())) + ((date 2026-10-26) (class_ ("IV cl.")) + (title "Vir Feria II post Dom. XXII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-10-27) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. XXII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Vesper\195\166 de feria, or. dom. XXII post Pent.")) + (alt_te_deum ())) + ((date 2026-10-28) (class_ ("II cl.")) + (title "Rub Feria IV. SS SIMONIS * ET IUD\195\134 * APP.,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("App. In Canone Miss\195\166, nomen S. Apostoli Iud\195\166 inscribitur cum nomine Thadd\195\166i: ergo inclinatur caput quando dicitur Thadd\195\166i. Vesper\195\166 de Comm. \226\128\147 Compl. de dom. Hodie permittuntur tantum Missae votivae et defunctorum I et II classis.")) + (alt_te_deum ())) + ((date 2026-10-29) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XXII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Vesper\195\166 de feria or. dom. XXII post Pent.")) + (alt_te_deum ())) + ((date 2026-10-30) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XXII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Vesper\195\166 de feria or. dom. XXII post Pent.")) + (alt_te_deum ())) + ((date 2026-10-31) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) + (praef + ("BMV Et te in Veneratione. I Vesper\195\166 de seq. \226\128\147 Compl. de dom. 106")) + (alt_te_deum ())) + ((date 2026-11-01) (class_ ("I cl.")) (title "Alb Dom. OMNIUM SANCTORUM,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("Trinit. vel de Omnibus Sanctis et Patronis. II")) + (alt_te_deum ())) + ((date 2026-11-02) (class_ ("I cl.")) + (title "Nig Feria II. IN COMMEMORATIONE OMNIUM FIDELIUM DEFUNCTORUM,") + (te_deum ()) (gloria (false)) (credo (false)) + (praef + ("defunctorum, unica or. \226\128\147 Benedictio non dicitur. \226\128\147 Si tres Miss\195\166 celebrantur sine intermissione, sequentia dici debet tantum in Missa principali; si minus, dici debet in Missa prima. In aliis Missis, nisi sint in cantu, sequentia omitti potest.")) + (alt_te_deum ())) + ((date 2026-11-03) (class_ ("IV cl.")) + (title "Vir Feria III post Dom. XXIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-11-04) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Caroli Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-11-05) (class_ ("IV cl.")) + (title "Vir Feria V post Dom. XXIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-06) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XXIII post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. Feria VI prima in mense.")) (alt_te_deum ())) + ((date 2026-11-07) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) + (praef ("BMV Et te in Veneratione. Sabbatum primum in mense. I")) + (alt_te_deum ())) + ((date 2026-11-08) (class_ ("II cl.")) + (title "Vir DOM. V QUI SUPERFUIT POST EPIPHANIAM, De ea,") + (te_deum (true)) (gloria (true)) (credo (true)) + (praef + ("Trinit. Dicitur Missa qu\195\166 inscribitur \194\171Dominica. V qui superfuit post Epiphaniam\194\187. Antiphonae ad Introitum, ad Offertorium et ad Communionem, necnon graduale et Alleluia cum suo versu, sumuntur e Dom. XXIII post Pent.; orationes, Epistola et Evangelium, e Dom. V qui superfuit post Epiphaniam. Ad II")) + (alt_te_deum ())) + ((date 2026-11-09) (class_ ("II cl.")) + (title + "Alb Feria II. IN DEDICATIONE ARCHIBASILICAE SANCTISSIMI SALVATORIS,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("comm. vel de Dedicatione ecclesi\195\166.")) (alt_te_deum ())) + ((date 2026-11-10) (class_ ("III cl.")) + (title "Alb Feria III. S Andreae Avellini Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. \226\128\147")) + (alt_te_deum ())) + ((date 2026-11-11) (class_ ("III cl. (Priv.)")) + (title "Alb Feria IV. S Martini Ep. et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-11-12) (class_ ("III cl.")) + (title "Rub Feria V. S Martini I Papae et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-11-13) (class_ ("III cl.")) + (title "Alb Feria VI. S Didaci Conf.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-14) (class_ ("III cl. (Priv.)")) + (title "Rub Sabb. S Iosaphat Ep. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("comm. vel de Martyribus \226\128\147")) (alt_te_deum ())) + ((date 2026-11-15) (class_ ("II cl.")) + (title "Vir DOM. VI QUI SUPERFUIT POST EPIPHANIAM, De ea,") + (te_deum (true)) (gloria (true)) (credo (true)) + (praef + ("Trinit. Dicitur Missa qu\195\166 inscribitur \194\171Dominica. VI qui superfuit post Epiphaniam\194\187. Antiphonae ad Introitum, ad Offertorium et ad Communionem, necnon graduale et Alleluia cum suo versu, sumuntur e Dom. XXIII post Pent.; orationes, Epistola et Evangelium, e Dom. VI qui superfuit post Epiphaniam. Ad II")) + (alt_te_deum ())) + ((date 2026-11-16) (class_ ("III cl.")) + (title "Alb Feria II. S Gertrudis Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-11-17) (class_ ("III cl.")) + (title "Alb Feria III. S Gregorii Thaumaturgi Ep. et Conf.,") + (te_deum (true)) (gloria (true)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-11-18) (class_ ("III cl. (Priv.)")) + (title + "Alb Feria IV. In Dedicatione Basilicarum SS Petri et Pauli App.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. vel de Dedicatione ecclesi\195\166.")) (alt_te_deum ())) + ((date 2026-11-19) (class_ ("III cl.")) + (title "Alb Feria V. S Elisabeth Vid.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-20) (class_ ("III cl.")) + (title "Alb Feria VI. S Felicis de Valois Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-11-21) (class_ ("III cl.")) + (title "Alb Sabb. In Praesentatione B. Mariae Virg.,") (te_deum (true)) + (gloria (true)) (credo (false)) + (praef ("BMV Et te in Pr\195\166sentatione. I")) (alt_te_deum ())) + ((date 2026-11-22) (class_ ("II cl.")) + (title "Vir DOM. XXIV & ULTIMA POST PENTECOSTEN, De ea,") + (te_deum (true)) (gloria (true)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-11-23) (class_ ("III cl. (Priv.)")) + (title "Rub Feria II. S Clementis I * Papae et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. Ad")) + (alt_te_deum ())) + ((date 2026-11-24) (class_ ("III cl. (Priv.)")) + (title "Alb Feria III. S Ioannis a Cruce Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-25) (class_ ("III cl.")) + (title "Rub Feria IV. S Catharinae Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus.")) + (alt_te_deum ())) + ((date 2026-11-26) (class_ ("III cl.")) + (title "Alb Feria V. S Silvestri Abb.,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-27) (class_ ("IV cl.")) + (title "Vir Feria VI post Dom. XXIV & Ultima post Pentecosten, De ea,") + (te_deum (false)) (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-11-28) (class_ ("IV cl.")) + (title "Alb Sancta Maria in Sabbato,") (te_deum (true)) (gloria (true)) + (credo (false)) (praef ("BMV Et te in Veneratione. I")) (alt_te_deum ())) + ((date 2026-11-29) (class_ ("I cl.")) + (title "Viol DOM. I ADVENTUS, De ea,") (te_deum (false)) (gloria (false)) + (credo (true)) (praef ("Trinit. Ad II")) (alt_te_deum ())) + ((date 2026-11-30) (class_ ("II cl.")) + (title "Rub Feria II. S ANDREAE * APOSTOLI,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-12-01) (class_ ("III cl.")) + (title "Viol Feria III post Dom. I Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-02) (class_ ("III cl.")) + (title "Rub Feria IV. S Bibianae Virg. et Mart.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. vel de Martyribus. Ad")) + (alt_te_deum ())) + ((date 2026-12-03) (class_ ("III cl. (Priv.)")) + (title "Alb Feria V. S Francisci Xavierii Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. Ad")) (alt_te_deum ())) + ((date 2026-12-04) (class_ ("III cl.")) + (title "Alb Feria VI. S Petri Chrysologi Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-12-05) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. I Adventus, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("comm. Sabbatum primum in mense. I")) (alt_te_deum ())) + ((date 2026-12-06) (class_ ("I cl.")) + (title "Viol DOM. II ADVENTUS, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-12-07) (class_ ("III cl. (Priv.)")) + (title "Alb Feria II. S Ambrosii Ep., Conf. et Eccl. Doct.,") + (te_deum (true)) (gloria (true)) (credo (false)) + (praef ("comm. \226\128\147")) (alt_te_deum ())) + ((date 2026-12-08) (class_ ("I cl.")) + (title "Alb Feria III. IN CONCEPTIONE IMMACULATA B. MARIAE VIRGINIS,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("BMV Et te in Conceptione Immaculata. Ad")) (alt_te_deum ())) + ((date 2026-12-09) (class_ ("III cl.")) + (title "Viol Feria IV post Dom. II Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-10) (class_ ("III cl.")) + (title "Viol Feria V post Dom. II Adventus, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-11) (class_ ("III cl. (Priv.)")) + (title "Alb Feria VI. S Damasi I Papae et Conf.,") (te_deum (true)) + (gloria (true)) (credo (false)) (praef ("comm. Ad")) (alt_te_deum ())) + ((date 2026-12-12) (class_ ("III cl.")) + (title "Viol Sabb. post Dom. II Adventus, De eo,") (te_deum ()) + (gloria (false)) (credo (false)) (praef ("comm. I")) (alt_te_deum ())) + ((date 2026-12-13) (class_ ("I cl.")) + (title "DOM. III ADVENTUS (GAUDETE), De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-12-14) (class_ ("III cl.")) + (title "Viol Feria II post Dom. III Adventus (Gaudete), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-12-15) (class_ ("III cl.")) + (title "Viol Feria III post Dom. III Adventus (Gaudete), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-12-16) (class_ ("II cl.")) + (title "Viol FERIA IV QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) + (praef ("comm. \226\128\147 Quoad Flectamus genua vide RM 440.")) + (alt_te_deum ())) + ((date 2026-12-17) (class_ ("II cl.")) + (title "Viol FERIA V POST DOM. III ADVENTUS (GAUDETE), De ea,") + (te_deum ()) (gloria (false)) (credo (false)) (praef (comm.)) + (alt_te_deum ())) + ((date 2026-12-18) (class_ ("II cl.")) + (title "Viol FERIA VI QUATTUOR TEMP., De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-19) (class_ ("II cl.")) + (title "Viol SABB. QUATTUOR TEMP., De eo,") (te_deum ()) (gloria (false)) + (credo (false)) + (praef + ("comm. \226\128\147 Quoad Flectamus genua vide RM 440. Quoad lectiones vide RM 468. I")) + (alt_te_deum ())) + ((date 2026-12-20) (class_ ("I cl.")) + (title "Viol DOM. IV ADVENTUS, De ea,") (te_deum (false)) + (gloria (false)) (credo (true)) (praef ("Trinit. Ad II")) + (alt_te_deum ())) + ((date 2026-12-21) (class_ ("II cl.")) + (title "Rub Feria II. S THOM\195\134 * APOSTOLI,") (te_deum ()) + (gloria (true)) (credo (true)) (praef ("App. Ad")) (alt_te_deum ())) + ((date 2026-12-22) (class_ ("II cl.")) + (title "Viol FERIA III POST DOM. IV ADVENTUS, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-23) (class_ ("II cl.")) + (title "Viol FERIA IV POST DOM. IV ADVENTUS, De ea,") (te_deum ()) + (gloria (false)) (credo (false)) (praef (comm.)) (alt_te_deum ())) + ((date 2026-12-24) (class_ ("I cl.")) + (title "Viol Feria V. VIGILIA NATIVITATIS DOMINI,") (te_deum (false)) + (gloria (false)) (credo (false)) (praef ("comm. I")) (alt_te_deum ())) + ((date 2026-12-25) (class_ ("I cl.")) + (title "Alb Feria VI. IN NATIVITATE DOMINI,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef + ("et Communic. pr. per totam oct. \226\128\147 In Communicantes: in 1\194\170 Missa dicitur Noctem sacratissimam celebrantes, qua, in 2\194\170 et 3\194\170 Missa et per octavam Diem sacratissimum celebrantes, quo. \226\128\147 In 2\194\170 Missa (etiam in cantu) fit comm. S. Anastasi\195\166 * M. \226\128\147 In Missis in cantu, ad verba symboli Et incarnatus est\226\128\166 et homo factus est, omnes genuflectunt versus altare, non tantum cum a celebrante recitantur, sed etiam cum a choro canuntur (RM 518 b). II")) + (alt_te_deum ())) + ((date 2026-12-26) (class_ ("II cl.")) + (title "Rub Sabb. S STEPHANI * PROTOMARTYRIS,") (te_deum ()) + (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. Ad")) + (alt_te_deum ())) + ((date 2026-12-27) (class_ ("II cl.")) + (title "Alb DOM. INFRA OCTAVAM NATIVITATIS, De ea,") (te_deum (true)) + (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. Ad II")) + (alt_te_deum ())) + ((date 2026-12-28) (class_ ("II cl.")) + (title "Rub Feria II. SS INNOCENTIUM MM.,") (te_deum ()) (gloria (true)) + (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. Ad")) + (alt_te_deum ())) + ((date 2026-12-29) (class_ ("II cl.")) + (title "Alb FERIA III DOM. INFRA OCTAVAM NATIVITATIS, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum.")) + (alt_te_deum ())) + ((date 2026-12-30) (class_ ("II cl.")) + (title "Alb FERIA IV DOM. INFRA OCTAVAM NATIVITATIS, De ea,") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum.")) + (alt_te_deum ())) + ((date 2026-12-31) (class_ ()) + (title + "Alb FERIA V DOM. INFRA OCTAVAM NATIVITATIS, De ea. \226\128\147 Off. semifestivum. \226\128\147 Ad MAT. invit., hymnus, 9 antt. et 9 pss. cum ultimo V de festo Nativ., Ll. de Scr. occ. cum suis RR (ad 2um additur Gloria Patri)\226\128\147 Ad Laudes antt. de Nativ., pss. de dom., comm. S Silvestri I Papae et Conf. \226\128\147 Ad HORAS ant. et pss. de feria curr., rel ut in festo Nativ. \226\128\147 Ad Primam in R Br. V Qui natus es de Maria Virgine. Missa Puer natus de diebus infra octavam, Gloria, Credo, comm. S Silvestri I Papae et Conf., praef. de Nativ., Communic. de Nativ. diem sacratissimum. I VESPER\195\134 de seq. \226\128\147 Compl. de dom. Hodie ad solemnem recitationem hymni Te Deum, indulgentia plenaria lucrari potest. 126") + (te_deum ()) (gloria (true)) (credo (true)) + (praef ("de Nativ., Communic. de Nativ. diem sacratissimum. I")) + (alt_te_deum ()))) diff --git a/test/fixtures/lms-ordo-2023-2024.sexp b/test/fixtures/lms-ordo-2023-2024.sexp new file mode 100644 index 0000000..c2ee62d --- /dev/null +++ b/test/fixtures/lms-ordo-2023-2024.sexp @@ -0,0 +1,1692 @@ +; /tmp/lms-ordo-2023-2024.sexp -- Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1), +; extending Task 6's single LMS fixture (2024-2025) to three editions of +; the Latin Mass Society's own printed Ordo for England & Wales -- a +; lineage independent of Divinum Officium/missalemeum/lectio (layers 3-4) +; and of the electronic LT.txt transcription (layers 1-2/5): a physically +; printed, professionally-compiled liturgical calendar with its own ISBN. +; +; Generator: tools/extract_lms_ordo.ml -- do not hand-edit; re-run against +; a fresh pdftotext dump and commit the diff instead. +; +; Source: "The Ordo 2023-2024", compiled by Peter Day-Milne, The Latin +; Mass Society, 9 Mallow Street, London EC1Y 8RQ (title page and +; colophon, verified directly against the PDF's own extracted text -- +; ISBN 978-1-7392096-2-9, Copyright (c) The Latin Mass Society, UK 2023). +; PDF metadata: Author "Peter Day-Milne", Producer "LibreOffice 6.4", CreationDate 2023-11-01, 140 pages. +; URL (identified 2026-08-22 via web search matching the PDF's own edition year to the publisher's own hosting path; NOT independently re-downloaded and byte-compared in this session -- recorded honestly rather than presented as verified): +; https://lms.org.uk/sites/default/files/u5374/ordo_2023-2024_2.2_final.pdf +; The local PDF (docs/research/ordo/lms-ordo-2023-2024.pdf) is gitignored +; (CLAUDE.md: "docs/ is gitignored"), so this header, not git, is this +; fixture's only record of where it came from. +; SHA-256 of docs/research/ordo/lms-ordo-2023-2024.pdf: 805a021bab246212c09a91706a04f4834fba052104de091b2fc5ed77c455bbba +; Extracted (UTC): 2026-08-23 +; Exact commands: +; pdftotext -layout docs/research/ordo/lms-ordo-2023-2024.pdf /tmp/lms.txt +; dune exec tools/extract_lms_ordo.exe -- /tmp/lms.txt \ +; docs/research/ordo/lms-ordo-2023-2024.pdf /tmp/lms-ordo-2023-2024.sexp +; +; COVERAGE: 397 day-rows, 2023-12-01 through 2024-12-31 (starting 1 December 2023 (this edition carries NO "End of November" stub section at all -- Advent Sunday 2023 fell on 3 December, so only 2 tail days of the prior liturgical year remained, and the compiler folded them directly into the "December 2023" header instead of giving them their own mini-section; see CHARACTERISATION below), +; through the day before a malformed trailing entry the extractor +; deliberately stops before -- see CHARACTERISATION below). +; +; CHARACTERISATION FINDINGS (Step 1, non-negotiable per the task brief -- +; the extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; every LMS edition, including this one, is probed +; with the same discipline before a single divergence is adjudicated): +; +; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed again for +; THIS edition: it carries many more Gl/Cr pairs than day-rows, because +; every diocesan variant repeats its own "Gl ... Cr ... Pr of ..." +; line). This extractor resolves the day's OWN office by taking the +; FIRST Gl/Cr pair in reading order, which the source's own layout +; guarantees is the universal entry's (diocesan variants are always +; introduced by a colon-terminated diocese-list line that comes AFTER +; the universal block, never before -- checked structurally, not +; assumed, in every sampled block during development, this edition +; included). +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN (not merely copied from a prior +; edition's findings) before a single row of this fixture is trusted -- +; the technique CLAUDE.md records as the one that catches a source +; silently omitting the very thing it is meant to witness. This run's +; own extracted [rows] were checked against every one of the following +; before this header was even written; a failure here is a hard [die], +; not a printed claim: +; 2023-12-03 (Advent Sunday, RG 475(a)) -> TRUE +; 2023-12-04 (St Peter Chrysologus, III class, ordinary Advent day, RG 476(b)/(d)) -> FALSE +; 2023-12-26 (St Stephen, II class, inside the Nativity octave, RG 475(d)) -> TRUE +; 2024-08-15 (the Assumption, I class, RG 475(b)) -> TRUE +; 2024-08-16 (St Joachim, II class, no Lord/BVM/apostle clause applies, RG 476(b)) -> FALSE +; All 5 predictions confirmed, both directions (TRUE and FALSE each +; independently witnessed) -- this edition is discriminating, not a +; constant, on the Creed. +; +; 3. The BVM-Saturday roman numeral (I-V, "Missae de sancta Maria in +; sabbato", RG 309(a)) is anchored by WHOLE-LINE match against the five +; literal strings below, NEVER by substring search: "V Mass of BVM" is +; a substring of "IV Mass of BVM", so a naive `contains` check +; misreads every fourth-Mass day as the fifth (the coordinator's own +; misreading, recorded and retracted in commit 27b07b4 before Task 6 +; existed; the same anchoring logic runs unchanged for every edition). +; +; 4. SCOPE EXCLUDED, quantified, not silently dropped: +; - Diocesan variants: present on 159 of 397 days (40.1%) -- their own +; text is read only far enough to set [has_diocesan_variant], +; never compared, because colitur computes the UNIVERSAL General +; Roman Calendar only, with no diocesan overlay loaded. +; - The single malformed trailing entry ("...The OCTAVE DAY of the +; NATIVITY..." with a bare 4-digit token where a weekday+day-number +; pair belongs) is excluded outright: the extractor's own stop +; marker (a line whose first token is a bare 4-digit token) halts +; the scan before it. CONFIRMED IDENTICAL, word for word, across +; ALL FOUR known editions of this publisher's Ordo (2023-2024, +; 2024-2025, 2025-2026, and the 2024-2025 fixture's own prior +; header) -- always the literal stray year token "2025", regardless +; of which edition or which real trailing year it should read: a +; stale copy-paste leftover the compiler's own master document +; carries forward unedited release to release (even the 2024-2025 +; PDF's own tail page footer nearby still reads "Latin Mass Society +; Ordo 2021-2022"), not something specific to this edition. +; - Front matter, the Abbreviations/Rubrical-Primer/Breviary sections, +; and the "When may I say...?"/Appendix tail are never scanned at +; all (the extractor's own start/stop markers bound it to the Ordo +; proper). +; +; 5. THE "Pr of" (PREFACE) COLUMN (Preface-witnesses task, 2026-08-23) -- +; [row.praef], the RAW text from the FIRST "Pr of ..." / "Common Pr" +; match in the universal block's own reading order (the same +; FIRST-in-reading-order discipline finding 1 above already +; establishes for Gl/Cr). CAPTURED, NOT CLASSIFIED by this tool -- +; classification into {!Colitur_kernel.Preface.t} and the comparison +; against {!Rite_ef.Rubrics_ef.preface} both happen test-side +; (test/test_lms_ordo.ml's own [classify_praef]). +; +; CHARACTERISATION FINDING, non-negotiable per the same discipline as +; finding 2: this Ordo prints OPTION LISTS ("Pr of X or Pr of Y or +; Common Pr"), not always a single value -- and several of the named +; options ("Martyrs", "All Saints and Patron Saints" [diocesan-only, +; every occurrence checked falls strictly after this block's own +; colon boundary], "the Dedication of a Church", "the Most Holy +; Sacrament" [Corpus Christi's own universal entry], "St John the +; Baptist", "the Angels") are genuinely NOT among the fourteen the +; 1962 Missale Romanum's own RG 484-497 enumerate (docs/research/LT.txt, +; lines 3936-4020, checked directly: no "de Martyribus"/"de Angelis"/ +; "de Dedicatione"/"de Ss.mo Sacramento"/"de S. Ioanne Baptista" clause +; exists anywhere in 482-499). Every one of these extras, in every +; instance found in this edition's UNIVERSAL block, is printed +; ALONGSIDE a genuine RG 482 answer (most often "or Common Pr"; on 24 +; March-shaped days, "or Pr of Lent", the live RG 486(b) de-Tempore +; answer) -- never as the row's OWN AND ONLY option. This is why the +; test-side comparison checks colitur's single computed answer is a +; MEMBER of this row's own parsed option set (dropping any unmapped +; extra name from that set first), not string equality against +; whichever option happens to print first -- the same "capture, don't +; force a match invented at extraction time" discipline +; tools/extract_fiuv_ordo.ml's own [row.praef] doc comment already +; states for a different publisher's format. +; +; OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.preface (RG +; 482-499), the SAME discipline as finding 2, applied to this new +; column -- RE-CHECKED BY THIS TOOL RUN before this header was +; written; a failed probe is a hard [die]: +; 2023-12-25 (the Nativity of Our Lord, I class, RG 484(a)) -> "Pr of the Nativity" +; 2024-06-29 (SS Peter & Paul, I class, RG 497) -> "Pr of the Apostles" +; 2024-11-02 (All Souls' Day, I class, RG 499) -> "Pr of the Dead" +; All 3 predictions confirmed -- this column, too, is discriminating, +; not a constant, across three different RG-cited outcomes (Nativity/ +; Apostles/Requiem). +; +; COVERAGE: 1 of 397 rows have no "Pr of"/"Common Pr" text found at +; all -- checked directly against this window's own Good Friday +; (Easter-2): its block carries NO Gl/Cr/Pr line whatsoever in this +; source (the 1955-restored Holy Week's own liturgical action has no +; Mass that day at all -- the SAME structural fact +; {!test_creed_coverage}'s own [window_good_fridays] already asserts +; for Gl/Cr), so [praef] shares that single expected gap rather than +; having a coverage gap of its own. +(((date 2023-12-01) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2023-12-02) (weekday Sat) + (title "St BIBIANA V M III Cl R # IH JCHP") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-03) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2023-12-04) (weekday Mon) + (title "St PETER CHRYSOLOGUS B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2023-12-05) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2023-12-06) (weekday Wed) (title "St NICOLAS B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-07) (weekday Thu) + (title "St AMBROSE B C D III Cl (Priv.) W JCHP*") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-08) (weekday Fri) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant true)) + ((date 2023-12-09) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2023-12-10) (weekday Sun) (title "2nd SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2023-12-11) (weekday Mon) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2023-12-12) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-13) (weekday Wed) (title "St LUCY V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-14) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-15) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-16) (weekday Sat) (title "St EUSEBIUS B M III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-17) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2023-12-18) (weekday Mon) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-19) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-20) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2023-12-21) (weekday Thu) (title "St THOMAS \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2023-12-22) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-23) (weekday Sat) (title "EMBER SATURDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2023-12-24) (weekday Sun) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2023-12-25) (weekday Mon) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at")) + (has_diocesan_variant false)) + ((date 2023-12-26) (weekday Tue) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2023-12-27) (weekday Wed) + (title "St JOHN \194\167 Ap Evangelist II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2023-12-28) (weekday Thu) (title "The HOLY INNOCENTS MM II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2023-12-29) (weekday Fri) + (title "5th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2023-12-30) (weekday Sat) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2023-12-31) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-01-01) (weekday Mon) + (title "The OCTAVE DAY of the NATIVITY of the LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-01-02) (weekday Tue) + (title "The MOST HOLY NAME of JESUS II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2024-01-03) (weekday Wed) (title "FERIA IV Cl W \226\128\160") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant true)) + ((date 2024-01-04) (weekday Thu) (title "FERIA IV Cl W \226\128\160 JCHP") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2024-01-05) (weekday Fri) (title "FERIA IV Cl W \226\128\160 SH") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2024-01-06) (weekday Sat) (title "The EPIPHANY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany Proper Communic")) + (has_diocesan_variant false)) + ((date 2024-01-07) (weekday Sun) + (title "The HOLY FAMILY of JESUS, MARY AND JOSEPH II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant true)) + ((date 2024-01-08) (weekday Mon) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2024-01-09) (weekday Tue) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2024-01-10) (weekday Wed) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2024-01-11) (weekday Thu) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2024-01-12) (weekday Fri) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant true)) + ((date 2024-01-13) (weekday Sat) (title "The BAPTISM of OUR LORD II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2024-01-14) (weekday Sun) + (title "2nd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-01-15) (weekday Mon) + (title "St PAUL the FIRST HERMIT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-01-16) (weekday Tue) (title "St MARCELLUS I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-01-17) (weekday Wed) (title "St ANTHONY Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-18) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-01-19) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-01-20) (weekday Sat) + (title "SS FABIAN P & SEBASTIAN M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-21) (weekday Sun) + (title "3rd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-01-22) (weekday Mon) + (title "SS VINCENT & ANASTASIUS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-23) (weekday Tue) + (title "St RAYMUND of PENAFORT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-01-24) (weekday Wed) (title "St TIMOTHY B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-25) (weekday Thu) + (title "The CONVERSION of St PAUL \194\167 Ap III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-01-26) (weekday Fri) (title "St POLYCARP B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-27) (weekday Sat) + (title "St JOHN CHRYSOSTOM B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-28) (weekday Sun) (title "SEPTUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-01-29) (weekday Mon) + (title "St FRANCIS de SALES B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-30) (weekday Tue) (title "St MARTINA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-01-31) (weekday Wed) (title "St JOHN BOSCO C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-01) (weekday Thu) + (title "St IGNATIUS \194\167 B M III Cl (Priv.) R JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-02-02) (weekday Fri) + (title "The PURIFICATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2024-02-03) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160 IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-02-04) (weekday Sun) (title "SEXAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-02-05) (weekday Mon) + (title "St AGATHA \194\167 V M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-06) (weekday Tue) (title "St TITUS B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-07) (weekday Wed) (title "St ROMUALD Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-08) (weekday Thu) (title "St JOHN of MATHA C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-09) (weekday Fri) + (title "St CYRIL of ALEXANDRIA B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-02-10) (weekday Sat) (title "St SCHOLASTICA V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-02-11) (weekday Sun) (title "QUINQUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-02-12) (weekday Mon) + (title "The SEVEN HOLY FOUNDERS of the ORDER of the SERVANTS of the") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-02-13) (weekday Tue) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Quinquagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-02-14) (weekday Wed) (title "ASH WEDNESDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-15) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-16) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-02-17) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-02-18) (weekday Sun) (title "1st SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-02-19) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-20) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-21) (weekday Wed) (title "EMBER WEDNESDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-22) (weekday Thu) + (title "The CHAIR of St PETER \194\167 Ap II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-02-23) (weekday Fri) (title "EMBER FRIDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-02-24) (weekday Sat) (title "EMBER SATURDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-25) (weekday Sun) (title "2nd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-02-26) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-27) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-02-28) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-02-29) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-01) (weekday Fri) (title "FERIA III Cl V SH") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-02) (weekday Sat) (title "FERIA III Cl V IH JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-03) (weekday Sun) (title "3rd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-03-04) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-05) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-06) (weekday Wed) + (title "SS PERPETUA \194\167 & FELICITY \194\167 MM III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-03-07) (weekday Thu) + (title "St THOMAS AQUINAS C D III Cl (Priv.) W JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-03-08) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-09) (weekday Sat) + (title "St FRANCES of ROME W III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Lent")) + (has_diocesan_variant false)) + ((date 2024-03-10) (weekday Sun) (title "4th SUNDAY in LENT I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2024-03-11) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-12) (weekday Tue) + (title "St GREGORY I P C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Lent")) + (has_diocesan_variant true)) + ((date 2024-03-13) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-14) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-15) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-16) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-17) (weekday Sun) (title "PASSION SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2024-03-18) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-19) (weekday Tue) + (title "St JOSEPH \194\167 SPOUSE of the BVM C, PATRON of the UNIVERSAL") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in festivitate")) + (has_diocesan_variant false)) + ((date 2024-03-20) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant true)) + ((date 2024-03-21) (weekday Thu) (title "St BENEDICT Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2024-03-22) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-23) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-24) (weekday Sun) (title "PALM SUNDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2024-03-25) (weekday Mon) (title "MONDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-26) (weekday Tue) (title "TUESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-27) (weekday Wed) (title "WEDNESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2024-03-28) (weekday Thu) (title "MAUNDY THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Holy Cross. No Judica No Gloria Patri at")) + (has_diocesan_variant false)) + ((date 2024-03-29) (weekday Fri) (title "GOOD FRIDAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria ()) (creed ()) + (praef ()) (has_diocesan_variant false)) + ((date 2024-03-30) (weekday Sat) (title "HOLY SATURDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter (in hac potissimum nocte).")) + (has_diocesan_variant false)) + ((date 2024-03-31) (weekday Sun) (title "EASTER I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter (die) Proper Communic Proper Hanc igitur")) + (has_diocesan_variant false)) + ((date 2024-04-01) (weekday Mon) (title "EASTER MONDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-02) (weekday Tue) (title "EASTER TUESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-03) (weekday Wed) (title "EASTER WEDNESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-04) (weekday Thu) (title "EASTER THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-05) (weekday Fri) (title "EASTER FRIDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-06) (weekday Sat) + (title "EASTER SATURDAY (SABBATO in ALBIS) I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2024-04-07) (weekday Sun) (title "LOW SUNDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-08) (weekday Mon) + (title "The ANNUNCIATION of the BVM I Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Annuntiatione")) + (has_diocesan_variant true)) + ((date 2024-04-09) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-04-10) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-04-11) (weekday Thu) (title "St LEO P C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-12) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-04-13) (weekday Sat) (title "St HERMENEGILD M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-14) (weekday Sun) (title "2nd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-15) (weekday Mon) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-04-16) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-04-17) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-04-18) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-04-19) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-04-20) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("IV Mass of BVM")) (bvm_numeral (IV)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2024-04-21) (weekday Sun) (title "3rd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-04-22) (weekday Mon) + (title "SS SOTER & CAIUS PP MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-04-23) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 3rd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-04-24) (weekday Wed) + (title "St FIDELIS of SIGMARINGEN M III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-04-25) (weekday Thu) + (title "THE GREATER LITANIES. St MARK Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2024-04-26) (weekday Fri) + (title "St CLETUS & MARCELLINUS PP MM III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-27) (weekday Sat) (title "St PETER CANISIUS C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-04-28) (weekday Sun) (title "4th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-04-29) (weekday Mon) (title "St PETER M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-04-30) (weekday Tue) + (title "St CATHERINE of SIENNA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-05-01) (weekday Wed) + (title "St JOSEPH \194\167 the WORKER, SPOUSE of the BVM C I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in solemnitate")) + (has_diocesan_variant false)) + ((date 2024-05-02) (weekday Thu) + (title "St ATHANASIUS B C D III Cl (Priv.) W JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2024-05-03) (weekday Fri) (title "FERIA IV Cl W \226\128\161 SH") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2024-05-04) (weekday Sat) + (title "St MONICA W III Cl (Priv.) W IH JCHP*") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-05-05) (weekday Sun) (title "5th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-05-06) (weekday Mon) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 5th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2024-05-07) (weekday Tue) (title "St STANISLAUS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-05-08) (weekday Wed) (title "VIGIL of The ASCENSION II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2024-05-09) (weekday Thu) (title "The ASCENSION I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension Proper Communic")) + (has_diocesan_variant false)) + ((date 2024-05-10) (weekday Fri) (title "St ANTONINUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2024-05-11) (weekday Sat) + (title "SS PHILIP \194\167 & JAMES \194\167 App II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-05-12) (weekday Sun) + (title "SUNDAY after the ASCENSION II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2024-05-13) (weekday Mon) + (title "St ROBERT BELLARMINE B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2024-05-14) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant true)) + ((date 2024-05-15) (weekday Wed) + (title "St JOHN BAPTIST de la SALLE C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2024-05-16) (weekday Thu) (title "St UBALDUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2024-05-17) (weekday Fri) (title "St PASCHAL BAYLON C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2024-05-18) (weekday Sat) (title "VIGIL of PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef + ("Pr of the Holy Spirit hodierna die Proper Communic Proper Hanc igitur")) + (has_diocesan_variant false)) + ((date 2024-05-19) (weekday Sun) (title "PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-20) (weekday Mon) (title "WHIT MONDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-21) (weekday Tue) (title "WHIT TUESDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-22) (weekday Wed) + (title "WHIT WEDNESDAY (EMBER DAY) I Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-23) (weekday Thu) (title "WHIT THURSDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-24) (weekday Fri) (title "WHIT FRIDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-25) (weekday Sat) (title "WHIT SATURDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2024-05-26) (weekday Sun) (title "The MOST HOLY TRINITY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-05-27) (weekday Mon) + (title "St BEDE the VENERABLE C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-05-28) (weekday Tue) (title "St AUGUSTINE B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-05-29) (weekday Wed) + (title "St MARY MAGDALEN dei PAZZI V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-05-30) (weekday Thu) (title "CORPUS CHRISTI I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Most Holy Sacrament or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-05-31) (weekday Fri) + (title "The BLESSED VIRGIN MARY, QUEEN II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2024-06-01) (weekday Sat) + (title "St ANGELA MERICI V III Cl W # IH JCHP") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-02) (weekday Sun) + (title "2nd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-06-03) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-06-04) (weekday Tue) + (title "St FRANCIS CARACCIOLO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-05) (weekday Wed) (title "St BONIFACE B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-06) (weekday Thu) (title "St NORBERT B C III Cl W # JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-06-07) (weekday Fri) (title "The SACRED HEART of JESUS I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Sacred Heart")) (has_diocesan_variant false)) + ((date 2024-06-08) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-06-09) (weekday Sun) + (title "3rd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-06-10) (weekday Mon) (title "St MARGARET Q W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-06-11) (weekday Tue) (title "St BARNABAS Ap III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-06-12) (weekday Wed) + (title "St JOHN of SAN FACONDO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-06-13) (weekday Thu) + (title "St ANTHONY of PADUA C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-14) (weekday Fri) + (title "St BASIL the GREAT B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-15) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2024-06-16) (weekday Sun) + (title "4th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-06-17) (weekday Mon) + (title "St GREGORY BARBARIGO B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-18) (weekday Tue) + (title "St EPHREM the SYRIAN Deacon C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-06-19) (weekday Wed) + (title "St JULIANA FALCONIERI V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-20) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-21) (weekday Fri) + (title "St ALOYSIUS GONZAGA C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-22) (weekday Sat) (title "St PAULINUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-23) (weekday Sun) + (title "5th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-06-24) (weekday Mon) + (title "The NATIVITY of JOHN the BAPTIST \194\167 I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-06-25) (weekday Tue) (title "St WILLIAM Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-26) (weekday Wed) + (title "SS JOHN & PAUL \194\167 MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-27) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 5th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-06-28) (weekday Fri) + (title "VIGIL of SS PETER \194\167 & PAUL \194\167 App II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-06-29) (weekday Sat) + (title "SS PETER \194\167 & PAUL \194\167 App I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2024-06-30) (weekday Sun) + (title "6th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-07-01) (weekday Mon) + (title "The MOST PRECIOUS BLOOD of OUR LORD JESUS CHRIST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2024-07-02) (weekday Tue) + (title "The VISITATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Visitatione")) + (has_diocesan_variant false)) + ((date 2024-07-03) (weekday Wed) (title "St IRENAEUS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-07-04) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 6th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-05) (weekday Fri) + (title "St ANTHONY MARY ZACCARIA C III Cl W # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-06) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2024-07-07) (weekday Sun) + (title "7th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-07-08) (weekday Mon) (title "St ELIZABETH Q W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-07-09) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-10) (weekday Wed) + (title "The SEVEN HOLY BROTHERS MM & SS RUFINA & SECUNDA VV MM III") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-11) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-12) (weekday Fri) (title "St JOHN GUALBERTI Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-13) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2024-07-14) (weekday Sun) + (title "8th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-07-15) (weekday Mon) (title "St HENRY Emperor C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-07-16) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 8th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-17) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 8th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-18) (weekday Thu) + (title "St CAMILLUS de LELLIS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-19) (weekday Fri) + (title "St VINCENT de PAUL C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-07-20) (weekday Sat) (title "St JEROME EMILIANI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-21) (weekday Sun) + (title "9th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-07-22) (weekday Mon) + (title "St MARY MAGDALEN Penitent III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-07-23) (weekday Tue) (title "St APOLLINARIS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-24) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 9th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-07-25) (weekday Thu) (title "St JAMES \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-07-26) (weekday Fri) + (title "St ANNE MOTHER of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-07-27) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2024-07-28) (weekday Sun) + (title "10th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-07-29) (weekday Mon) (title "St MARTHA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-07-30) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 10th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-07-31) (weekday Wed) (title "St IGNATIUS C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-08-01) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 10th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-08-02) (weekday Fri) + (title "St ALPHONSUS MARIA LIGUORI B C D III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-03) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-08-04) (weekday Sun) + (title "11th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-08-05) (weekday Mon) + (title "The DEDICATION of St MARY of the SNOWS III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2024-08-06) (weekday Tue) + (title "The TRANSFIGURATION of OUR LORD JESUS CHRIST II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-07) (weekday Wed) (title "St CAJETAN C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-08) (weekday Thu) + (title "St JOHN MARY VIANNEY C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-08-09) (weekday Fri) + (title "VIGIL of St LAURENCE \194\167 M III Cl V #") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-10) (weekday Sat) (title "St LAURENCE \194\167 M II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-11) (weekday Sun) + (title "12th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-08-12) (weekday Mon) (title "St CLARE V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-13) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 12th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-08-14) (weekday Wed) + (title "VIGIL of The ASSUMPTION of the BVM II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-15) (weekday Thu) (title "The ASSUMPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Assumptione")) + (has_diocesan_variant false)) + ((date 2024-08-16) (weekday Fri) + (title "St JOACHIM FATHER of the BVM C II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-08-17) (weekday Sat) (title "St HYACINTH C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-08-18) (weekday Sun) + (title "13th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-08-19) (weekday Mon) (title "St JOHN EUDES C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-08-20) (weekday Tue) (title "St BERNARD Ab D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-08-21) (weekday Wed) + (title "St JANE FRANCES FREMIOT de CHANTAL W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-08-22) (weekday Thu) + (title "The IMMACULATE HEART of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2024-08-23) (weekday Fri) (title "St PHILIP BENIZI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-24) (weekday Sat) + (title "St BARTHOLOMEW \194\167 Ap II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-08-25) (weekday Sun) + (title "14th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-08-26) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 14th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-08-27) (weekday Tue) + (title "St JOSEPH CALASANCTIUS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-08-28) (weekday Wed) + (title "St AUGUSTINE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-08-29) (weekday Thu) + (title "The BEHEADING of St JOHN the BAPTIST \194\167 III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-08-30) (weekday Fri) (title "St ROSE of LIMA V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-08-31) (weekday Sat) (title "St RAYMUND NONNATUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-01) (weekday Sun) + (title "15th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-09-02) (weekday Mon) (title "St STEPHEN K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-03) (weekday Tue) (title "St PIUS X P C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-04) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-05) (weekday Thu) + (title "St LAURENCE JUSTINIAN B C III Cl W # JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-06) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-07) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione.")) + (has_diocesan_variant false)) + ((date 2024-09-08) (weekday Sun) + (title "16th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-09-09) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 16th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-09-10) (weekday Tue) + (title "St NICOLAS of TOLENTINO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-09-11) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 16th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-12) (weekday Thu) + (title "The MOST HOLY NAME of MARY III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2024-09-13) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 16th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-14) (weekday Sat) + (title "The EXALTATION of the HOLY CROSS II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2024-09-15) (weekday Sun) + (title "17th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-09-16) (weekday Mon) + (title + "SS CORNELIUS \194\167 P & CYPRIAN \194\167 B MM III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-17) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 17th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-09-18) (weekday Wed) + (title "EMBER WEDNESDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-09-19) (weekday Thu) + (title "St JANUARIUS B & COMPS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-20) (weekday Fri) + (title "EMBER FRIDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-09-21) (weekday Sat) + (title "St MATTHEW \194\167 Ap Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2024-09-22) (weekday Sun) + (title "18th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-09-23) (weekday Mon) (title "St LINUS P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-09-24) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 18th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-25) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 18th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-26) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 18th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-09-27) (weekday Fri) + (title "SS COSMAS \194\167 & DAMIAN \194\167 MM III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-09-28) (weekday Sat) (title "St WENCESLAUS Duke M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-09-29) (weekday Sun) + (title "The DEDICATION of St MICHAEL Archangel I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Angels or Pr of the Trinity")) + (has_diocesan_variant false)) + ((date 2024-09-30) (weekday Mon) + (title "St JEROME Priest C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-01) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 19th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-10-02) (weekday Wed) + (title "The HOLY GUARDIAN ANGELS III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant false)) + ((date 2024-10-03) (weekday Thu) + (title "St TERESA of the CHILD JESUS V III Cl (Priv.) W JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-04) (weekday Fri) + (title "St FRANCIS of ASSISI C III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-05) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-10-06) (weekday Sun) + (title "20th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-10-07) (weekday Mon) (title "The BVM of the ROSARY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2024-10-08) (weekday Tue) (title "St BRIDGET W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-09) (weekday Wed) (title "St JOHN LEONARDI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-10) (weekday Thu) (title "St FRANCIS BORGIA C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-11) (weekday Fri) + (title "The MOTHERHOOD of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2024-10-12) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-10-13) (weekday Sun) + (title "21st SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-10-14) (weekday Mon) + (title "St CALLISTUS I P M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-10-15) (weekday Tue) (title "St TERESA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-16) (weekday Wed) (title "St HEDWIG W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-17) (weekday Thu) + (title "St MARGARET MARY ALACOQUE V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-18) (weekday Fri) (title "St LUKE Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2024-10-19) (weekday Sat) + (title "St PETER of ALCANTARA C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-20) (weekday Sun) + (title "22nd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-10-21) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-22) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-23) (weekday Wed) + (title "St ANTHONY MARY CLARET B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-10-24) (weekday Thu) (title "St RAPHAEL Archangel III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant true)) + ((date 2024-10-25) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-26) (weekday Sat) + (title "CELEBRATION of the BVM IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2024-10-27) (weekday Sun) (title "CHRIST the KING I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Our Lord Jesus Christ the King")) + (has_diocesan_variant false)) + ((date 2024-10-28) (weekday Mon) + (title "SS SIMON \194\167 & JUDE \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2024-10-29) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-30) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-10-31) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-01) (weekday Fri) (title "ALL SAINTS' DAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of All Saints and Patron Saints or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-02) (weekday Sat) (title "ALL SOULS' DAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Dead No Blessing")) (has_diocesan_variant false)) + ((date 2024-11-03) (weekday Sun) + (title "4th SUNDAY remaining after the EPIPHANY II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-11-04) (weekday Mon) (title "St CHARLES B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-05) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday remaining after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-06) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday remaining after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-07) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 4th Sunday remaining after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-08) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday remaining after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-09) (weekday Sat) + (title "The DEDICATION of the ARCHBASILICA of OUR SAVIOUR II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Dedication of a Church or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-10) (weekday Sun) + (title "5th SUNDAY remaining after the EPIPHANY II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-11-11) (weekday Mon) (title "St MARTIN B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-12) (weekday Tue) (title "St MARTIN I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-13) (weekday Wed) (title "St DIDACUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-14) (weekday Thu) (title "St JOSAPHAT B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-11-15) (weekday Fri) + (title "St ALBERT the GREAT B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-16) (weekday Sat) (title "St GERTRUDE V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-11-17) (weekday Sun) + (title "6th SUNDAY remaining after the EPIPHANY II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2024-11-18) (weekday Mon) + (title + "The DEDICATION of the BASILICAS of SS PETER & PAUL III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Dedication of a Church or Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-19) (weekday Tue) (title "St ELIZABETH W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-20) (weekday Wed) (title "St FELIX de VALOIS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2024-11-21) (weekday Thu) + (title "The PRESENTATION of the BVM III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Pr\195\166sentatione")) + (has_diocesan_variant false)) + ((date 2024-11-22) (weekday Fri) + (title "St CECILIA \194\167 V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-11-23) (weekday Sat) + (title "St CLEMENT I \194\167 P M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2024-11-24) (weekday Sun) + (title "24th & LAST SUNDAY After PENTECOST II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-11-25) (weekday Mon) (title "St CATHERINE V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-26) (weekday Tue) (title "St SILVESTER Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-11-27) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-28) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-29) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-30) (weekday Sat) (title "St ANDREW \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-12-01) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-02) (weekday Mon) (title "St BIBIANA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-03) (weekday Tue) + (title "St FRANCIS XAVIER C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-04) (weekday Wed) + (title "St PETER CHRYSOLOGUS B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-05) (weekday Thu) (title "FERIA III Cl V JCHP") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-06) (weekday Fri) + (title "St NICOLAS B C III Cl (Priv.) W SH") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-07) (weekday Sat) + (title "St AMBROSE B C D III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-08) (weekday Sun) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant false)) + ((date 2024-12-09) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-10) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-11) (weekday Wed) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-12) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-13) (weekday Fri) (title "St LUCY V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-14) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-15) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-16) (weekday Mon) (title "St EUSEBIUS B M III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-17) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-18) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-19) (weekday Thu) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-20) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-21) (weekday Sat) (title "St THOMAS \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-12-22) (weekday Sun) (title "4th SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-23) (weekday Mon) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-24) (weekday Tue) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-25) (weekday Wed) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at")) + (has_diocesan_variant false)) + ((date 2024-12-26) (weekday Thu) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-27) (weekday Fri) + (title "St JOHN \194\167 Ap Evangelist II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-28) (weekday Sat) (title "The HOLY INNOCENTS MM II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2024-12-29) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2024-12-30) (weekday Mon) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-31) (weekday Tue) + (title "7th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false))) diff --git a/test/fixtures/lms-ordo-2024-2025.sexp b/test/fixtures/lms-ordo-2024-2025.sexp new file mode 100644 index 0000000..9c717f8 --- /dev/null +++ b/test/fixtures/lms-ordo-2024-2025.sexp @@ -0,0 +1,1719 @@ +; /tmp/lms-ordo-2024-2025.sexp -- Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1), +; extending Task 6's single LMS fixture (2024-2025) to three editions of +; the Latin Mass Society's own printed Ordo for England & Wales -- a +; lineage independent of Divinum Officium/missalemeum/lectio (layers 3-4) +; and of the electronic LT.txt transcription (layers 1-2/5): a physically +; printed, professionally-compiled liturgical calendar with its own ISBN. +; +; Generator: tools/extract_lms_ordo.ml -- do not hand-edit; re-run against +; a fresh pdftotext dump and commit the diff instead. +; +; Source: "The Ordo 2024-2025", compiled by Peter Day-Milne, The Latin +; Mass Society, 9 Mallow Street, London EC1Y 8RQ (title page and +; colophon, verified directly against the PDF's own extracted text -- +; ISBN 9781739209636, Copyright (c) The Latin Mass Society, UK 2024). +; PDF metadata: Author "Peter Day-Milne", Producer "LibreOffice 7.4", CreationDate 2024-11-06, 140 pages. +; URL (identified via web search matching the PDF's own version number and filename to the publisher's own hosting path (product page: https://lms.org.uk/product/latin-mass-society-ordo-2024-25); NOT independently re-downloaded and byte-compared in this session -- recorded honestly rather than presented as verified): +; https://lms.org.uk/sites/default/files/u5374/ordo_2.21_2024-2025.pdf +; The local PDF (docs/research/ordo/lms-ordo-2024-2025.pdf) is gitignored +; (CLAUDE.md: "docs/ is gitignored"), so this header, not git, is this +; fixture's only record of where it came from. +; SHA-256 of docs/research/ordo/lms-ordo-2024-2025.pdf: 7c482684d177b2e1aa7498e302405bf37ee15042f892c65f7a6091fd5d169f7d +; Extracted (UTC): 2026-08-23 +; Exact commands: +; pdftotext -layout docs/research/ordo/lms-ordo-2024-2025.pdf /tmp/lms.txt +; dune exec tools/extract_lms_ordo.exe -- /tmp/lms.txt \ +; docs/research/ordo/lms-ordo-2024-2025.pdf /tmp/lms-ordo-2024-2025.sexp +; +; COVERAGE: 400 day-rows, 2024-11-27 through 2025-12-31 (starting 27 November 2024 ("End of November 2024", the same shape as the 2025-2026 edition -- Advent Sunday 2024 fell on 1 December, so 4 tail days remained (27-30 November)), +; through the day before a malformed trailing entry the extractor +; deliberately stops before -- see CHARACTERISATION below). +; +; CHARACTERISATION FINDINGS (Step 1, non-negotiable per the task brief -- +; the extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; every LMS edition, including this one, is probed +; with the same discipline before a single divergence is adjudicated): +; +; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed again for +; THIS edition: it carries many more Gl/Cr pairs than day-rows, because +; every diocesan variant repeats its own "Gl ... Cr ... Pr of ..." +; line). This extractor resolves the day's OWN office by taking the +; FIRST Gl/Cr pair in reading order, which the source's own layout +; guarantees is the universal entry's (diocesan variants are always +; introduced by a colon-terminated diocese-list line that comes AFTER +; the universal block, never before -- checked structurally, not +; assumed, in every sampled block during development, this edition +; included). +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN (not merely copied from a prior +; edition's findings) before a single row of this fixture is trusted -- +; the technique CLAUDE.md records as the one that catches a source +; silently omitting the very thing it is meant to witness. This run's +; own extracted [rows] were checked against every one of the following +; before this header was even written; a failure here is a hard [die], +; not a printed claim: +; 2024-12-01 (Advent Sunday, RG 475(a)) -> TRUE +; 2024-12-02 (ordinary Advent feria, RG 476(b)/(d)) -> FALSE +; 2024-12-26 (St Stephen, II class, inside the Nativity octave, RG 475(d)) -> TRUE +; 2025-08-15 (the Assumption, I class, RG 475(b)) -> TRUE +; 2025-08-16 (St Joachim, II class, no Lord/BVM/apostle clause applies, RG 476(b)) -> FALSE +; All 5 predictions confirmed, both directions (TRUE and FALSE each +; independently witnessed) -- this edition is discriminating, not a +; constant, on the Creed. +; +; 3. The BVM-Saturday roman numeral (I-V, "Missae de sancta Maria in +; sabbato", RG 309(a)) is anchored by WHOLE-LINE match against the five +; literal strings below, NEVER by substring search: "V Mass of BVM" is +; a substring of "IV Mass of BVM", so a naive `contains` check +; misreads every fourth-Mass day as the fifth (the coordinator's own +; misreading, recorded and retracted in commit 27b07b4 before Task 6 +; existed; the same anchoring logic runs unchanged for every edition). +; +; 4. SCOPE EXCLUDED, quantified, not silently dropped: +; - Diocesan variants: present on 156 of 400 days (39.0%) -- their own +; text is read only far enough to set [has_diocesan_variant], +; never compared, because colitur computes the UNIVERSAL General +; Roman Calendar only, with no diocesan overlay loaded. +; - The single malformed trailing entry ("...The OCTAVE DAY of the +; NATIVITY..." with a bare 4-digit token where a weekday+day-number +; pair belongs) is excluded outright: the extractor's own stop +; marker (a line whose first token is a bare 4-digit token) halts +; the scan before it. CONFIRMED IDENTICAL, word for word, across +; ALL FOUR known editions of this publisher's Ordo (2023-2024, +; 2024-2025, 2025-2026, and the 2024-2025 fixture's own prior +; header) -- always the literal stray year token "2025", regardless +; of which edition or which real trailing year it should read: a +; stale copy-paste leftover the compiler's own master document +; carries forward unedited release to release (even the 2024-2025 +; PDF's own tail page footer nearby still reads "Latin Mass Society +; Ordo 2021-2022"), not something specific to this edition. +; - Front matter, the Abbreviations/Rubrical-Primer/Breviary sections, +; and the "When may I say...?"/Appendix tail are never scanned at +; all (the extractor's own start/stop markers bound it to the Ordo +; proper). +; +; 5. THE "Pr of" (PREFACE) COLUMN (Preface-witnesses task, 2026-08-23) -- +; [row.praef], the RAW text from the FIRST "Pr of ..." / "Common Pr" +; match in the universal block's own reading order (the same +; FIRST-in-reading-order discipline finding 1 above already +; establishes for Gl/Cr). CAPTURED, NOT CLASSIFIED by this tool -- +; classification into {!Colitur_kernel.Preface.t} and the comparison +; against {!Rite_ef.Rubrics_ef.preface} both happen test-side +; (test/test_lms_ordo.ml's own [classify_praef]). +; +; CHARACTERISATION FINDING, non-negotiable per the same discipline as +; finding 2: this Ordo prints OPTION LISTS ("Pr of X or Pr of Y or +; Common Pr"), not always a single value -- and several of the named +; options ("Martyrs", "All Saints and Patron Saints" [diocesan-only, +; every occurrence checked falls strictly after this block's own +; colon boundary], "the Dedication of a Church", "the Most Holy +; Sacrament" [Corpus Christi's own universal entry], "St John the +; Baptist", "the Angels") are genuinely NOT among the fourteen the +; 1962 Missale Romanum's own RG 484-497 enumerate (docs/research/LT.txt, +; lines 3936-4020, checked directly: no "de Martyribus"/"de Angelis"/ +; "de Dedicatione"/"de Ss.mo Sacramento"/"de S. Ioanne Baptista" clause +; exists anywhere in 482-499). Every one of these extras, in every +; instance found in this edition's UNIVERSAL block, is printed +; ALONGSIDE a genuine RG 482 answer (most often "or Common Pr"; on 24 +; March-shaped days, "or Pr of Lent", the live RG 486(b) de-Tempore +; answer) -- never as the row's OWN AND ONLY option. This is why the +; test-side comparison checks colitur's single computed answer is a +; MEMBER of this row's own parsed option set (dropping any unmapped +; extra name from that set first), not string equality against +; whichever option happens to print first -- the same "capture, don't +; force a match invented at extraction time" discipline +; tools/extract_fiuv_ordo.ml's own [row.praef] doc comment already +; states for a different publisher's format. +; +; OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.preface (RG +; 482-499), the SAME discipline as finding 2, applied to this new +; column -- RE-CHECKED BY THIS TOOL RUN before this header was +; written; a failed probe is a hard [die]: +; 2024-12-25 (the Nativity of Our Lord, I class, RG 484(a)) -> "Pr of the Nativity" +; 2025-06-29 (SS Peter & Paul, I class, RG 497) -> "Pr of the Apostles" +; 2025-11-03 (All Souls' Day, I class, RG 499 -- TRANSFERRED from 2 November, a Sunday in this edition's own calendar) -> "Pr of the Dead" +; All 3 predictions confirmed -- this column, too, is discriminating, +; not a constant, across three different RG-cited outcomes (Nativity/ +; Apostles/Requiem). +; +; COVERAGE: 1 of 400 rows have no "Pr of"/"Common Pr" text found at +; all -- checked directly against this window's own Good Friday +; (Easter-2): its block carries NO Gl/Cr/Pr line whatsoever in this +; source (the 1955-restored Holy Week's own liturgical action has no +; Mass that day at all -- the SAME structural fact +; {!test_creed_coverage}'s own [window_good_fridays] already asserts +; for Gl/Cr), so [praef] shares that single expected gap rather than +; having a coverage gap of its own. +(((date 2024-11-27) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-28) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-11-29) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-11-30) (weekday Sat) (title "St ANDREW \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-12-01) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-02) (weekday Mon) (title "St BIBIANA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-03) (weekday Tue) + (title "St FRANCIS XAVIER C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-04) (weekday Wed) + (title "St PETER CHRYSOLOGUS B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-05) (weekday Thu) (title "FERIA III Cl V JCHP") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-06) (weekday Fri) + (title "St NICOLAS B C III Cl (Priv.) W SH") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-07) (weekday Sat) + (title "St AMBROSE B C D III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-08) (weekday Sun) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant false)) + ((date 2024-12-09) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-10) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-11) (weekday Wed) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2024-12-12) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-13) (weekday Fri) (title "St LUCY V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-14) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-15) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-16) (weekday Mon) (title "St EUSEBIUS B M III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-17) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-18) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-19) (weekday Thu) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-20) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-21) (weekday Sat) (title "St THOMAS \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2024-12-22) (weekday Sun) (title "4th SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2024-12-23) (weekday Mon) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2024-12-24) (weekday Tue) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2024-12-25) (weekday Wed) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at other")) + (has_diocesan_variant false)) + ((date 2024-12-26) (weekday Thu) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-27) (weekday Fri) + (title "St JOHN \194\167 Ap Evangelist II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-28) (weekday Sat) (title "The HOLY INNOCENTS MM II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2024-12-29) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2024-12-30) (weekday Mon) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2024-12-31) (weekday Tue) + (title "7th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-01-01) (weekday Wed) + (title "The OCTAVE DAY of the NATIVITY of the LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-01-02) (weekday Thu) (title "FERIA IV Cl W \226\128\160 JCHP") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2025-01-03) (weekday Fri) (title "FERIA IV Cl W \226\128\160 SH") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant true)) + ((date 2025-01-04) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("II Mass of BVM")) (bvm_numeral (II)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-01-05) (weekday Sun) + (title "The MOST HOLY NAME of JESUS II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant true)) + ((date 2025-01-06) (weekday Mon) (title "The EPIPHANY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany Proper Communic")) + (has_diocesan_variant false)) + ((date 2025-01-07) (weekday Tue) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2025-01-08) (weekday Wed) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2025-01-09) (weekday Thu) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2025-01-10) (weekday Fri) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2025-01-11) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("II Mass of BVM")) (bvm_numeral (II)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-01-12) (weekday Sun) + (title "The HOLY FAMILY of JESUS, MARY AND JOSEPH II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2025-01-13) (weekday Mon) (title "The BAPTISM of OUR LORD II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2025-01-14) (weekday Tue) (title "St HILARY B C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-01-15) (weekday Wed) + (title "St PAUL the FIRST HERMIT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-01-16) (weekday Thu) (title "St MARCELLUS I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-01-17) (weekday Fri) (title "St ANTHONY Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-18) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("II Mass of BVM")) (bvm_numeral (II)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-01-19) (weekday Sun) + (title "2nd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-01-20) (weekday Mon) + (title "SS FABIAN P & SEBASTIAN M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-21) (weekday Tue) + (title "St AGNES \194\167 V M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-22) (weekday Wed) + (title "SS VINCENT & ANASTASIUS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-23) (weekday Thu) + (title "St RAYMUND of PENAFORT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-01-24) (weekday Fri) (title "St TIMOTHY B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-25) (weekday Sat) + (title "The CONVERSION of St PAUL \194\167 Ap III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2025-01-26) (weekday Sun) + (title "3rd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-01-27) (weekday Mon) + (title "St JOHN CHRYSOSTOM B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-28) (weekday Tue) (title "St PETER NOLASCO C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-29) (weekday Wed) + (title "St FRANCIS de SALES B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-30) (weekday Thu) (title "St MARTINA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-01-31) (weekday Fri) (title "St JOHN BOSCO C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-01) (weekday Sat) + (title "St IGNATIUS \194\167 B M III Cl (Priv.) R IH JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-02-02) (weekday Sun) + (title "The PURIFICATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2025-02-03) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-02-04) (weekday Tue) (title "St ANDREW CORSINI B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-02-05) (weekday Wed) + (title "St AGATHA \194\167 V M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-06) (weekday Thu) + (title "St TITUS B C III Cl (Priv.) W JCHP*") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-07) (weekday Fri) (title "St ROMUALD Ab III Cl W # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-08) (weekday Sat) (title "St JOHN of MATHA C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-09) (weekday Sun) + (title "5th SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-02-10) (weekday Mon) (title "St SCHOLASTICA V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-02-11) (weekday Tue) + (title "The APPARITION of the BVM IMMACULATE III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant true)) + ((date 2025-02-12) (weekday Wed) + (title "The SEVEN HOLY FOUNDERS of the ORDER of the SERVANTS of the") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-13) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 5th Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-02-14) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 5th Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-15) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("III Mass of BVM")) (bvm_numeral (III)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-02-16) (weekday Sun) (title "SEPTUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-02-17) (weekday Mon) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-02-18) (weekday Tue) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-19) (weekday Wed) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-20) (weekday Thu) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-21) (weekday Fri) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-02-22) (weekday Sat) + (title "The CHAIR of St PETER \194\167 Ap II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2025-02-23) (weekday Sun) (title "SEXAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-02-24) (weekday Mon) (title "St MATTHIAS Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2025-02-25) (weekday Tue) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Sexagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-02-26) (weekday Wed) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Sexagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-02-27) (weekday Thu) + (title "St GABRIEL of OUR LADY of SORROWS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-02-28) (weekday Fri) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Sexagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-03-01) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP") + (formulary_override ("III Mass of BVM")) (bvm_numeral (III)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-03-02) (weekday Sun) (title "QUINQUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-03-03) (weekday Mon) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Quinquagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-03-04) (weekday Tue) (title "St CASIMIR C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-03-05) (weekday Wed) (title "ASH WEDNESDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-06) (weekday Thu) + (title + "SS PERPETUA \194\167 & FELICITY \194\167 MM III Cl (Priv.) R JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-07) (weekday Fri) + (title "St THOMAS AQUINAS C D III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-08) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-09) (weekday Sun) (title "1st SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-10) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-11) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-12) (weekday Wed) (title "EMBER WEDNESDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-13) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-14) (weekday Fri) (title "EMBER FRIDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-15) (weekday Sat) (title "EMBER SATURDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-16) (weekday Sun) (title "2nd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-17) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-18) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-19) (weekday Wed) + (title "St JOSEPH \194\167 SPOUSE of the BVM C, PATRON of the UNIVERSAL") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in festivitate")) + (has_diocesan_variant false)) + ((date 2025-03-20) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-21) (weekday Fri) (title "St BENEDICT Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-22) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-23) (weekday Sun) (title "3rd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-24) (weekday Mon) + (title "St GABRIEL Archangel III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-25) (weekday Tue) + (title "The ANNUNCIATION of the BVM I Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Annuntiatione")) + (has_diocesan_variant false)) + ((date 2025-03-26) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-27) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-03-28) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-29) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-03-30) (weekday Sun) (title "4th SUNDAY in LENT I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2025-03-31) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-01) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-02) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-04-03) (weekday Thu) (title "FERIA III Cl V JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2025-04-04) (weekday Fri) (title "FERIA III Cl V SH") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-05) (weekday Sat) (title "FERIA III Cl V IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-06) (weekday Sun) (title "PASSION SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2025-04-07) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-08) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-09) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-10) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-11) (weekday Fri) (title "St LEO P C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2025-04-12) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-13) (weekday Sun) (title "PALM SUNDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2025-04-14) (weekday Mon) (title "MONDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-15) (weekday Tue) (title "TUESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-16) (weekday Wed) (title "WEDNESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2025-04-17) (weekday Thu) (title "MAUNDY THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Holy Cross. No Judica No Gloria Patri at")) + (has_diocesan_variant false)) + ((date 2025-04-18) (weekday Fri) (title "GOOD FRIDAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria ()) (creed ()) + (praef ()) (has_diocesan_variant false)) + ((date 2025-04-19) (weekday Sat) (title "HOLY SATURDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter (in hac potissimum nocte).")) + (has_diocesan_variant false)) + ((date 2025-04-20) (weekday Sun) (title "EASTER I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter (die) Proper Communic Proper Hanc igitur")) + (has_diocesan_variant true)) + ((date 2025-04-21) (weekday Mon) (title "EASTER MONDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-22) (weekday Tue) (title "EASTER TUESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-23) (weekday Wed) (title "EASTER WEDNESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-24) (weekday Thu) (title "EASTER THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-25) (weekday Fri) + (title "THE GREATER LITANIES. EASTER FRIDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-26) (weekday Sat) + (title "EASTER SATURDAY (SABBATO in ALBIS) I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2025-04-27) (weekday Sun) (title "LOW SUNDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-04-28) (weekday Mon) + (title "St PAUL of the CROSS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-04-29) (weekday Tue) (title "St PETER M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-04-30) (weekday Wed) + (title "St CATHERINE of SIENNA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-01) (weekday Thu) + (title "St JOSEPH \194\167 the WORKER, SPOUSE of the BVM C I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in solemnitate")) + (has_diocesan_variant false)) + ((date 2025-05-02) (weekday Fri) + (title "St ATHANASIUS B C D III Cl (Priv.) W SH") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2025-05-03) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP") + (formulary_override ("IV Mass of BVM")) (bvm_numeral (IV)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-05-04) (weekday Sun) (title "2nd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-05) (weekday Mon) (title "St PIUS V P C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-06) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-07) (weekday Wed) (title "St STANISLAUS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-08) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2025-05-09) (weekday Fri) + (title "St GREGORY NAZIANZEN B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-10) (weekday Sat) (title "St ANTONINUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-11) (weekday Sun) (title "3rd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-12) (weekday Mon) + (title "SS NEREUS, ACHILLEUS, DOMITILLA V, & PANCRAS MM III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-13) (weekday Tue) + (title "St ROBERT BELLARMINE B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-14) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 3rd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-15) (weekday Thu) + (title "St JOHN BAPTIST de la SALLE C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-16) (weekday Fri) (title "St UBALDUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-17) (weekday Sat) (title "St PASCHAL BAYLON C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-18) (weekday Sun) (title "4th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-19) (weekday Mon) + (title "St PETER CELESTINE P C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-20) (weekday Tue) + (title "St BERNARD of SIENNA C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-21) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-22) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2025-05-23) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-24) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("IV Mass of BVM")) (bvm_numeral (IV)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-05-25) (weekday Sun) (title "5th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2025-05-26) (weekday Mon) + (title "St PHILIP NERI C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-27) (weekday Tue) + (title "St BEDE the VENERABLE C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2025-05-28) (weekday Wed) (title "VIGIL of The ASCENSION II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2025-05-29) (weekday Thu) (title "The ASCENSION I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension Proper Communic")) + (has_diocesan_variant false)) + ((date 2025-05-30) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant true)) + ((date 2025-05-31) (weekday Sat) + (title "The BLESSED VIRGIN MARY, QUEEN II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2025-06-01) (weekday Sun) + (title "SUNDAY after the ASCENSION II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2025-06-02) (weekday Mon) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant false)) + ((date 2025-06-03) (weekday Tue) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant false)) + ((date 2025-06-04) (weekday Wed) + (title "St FRANCIS CARACCIOLO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2025-06-05) (weekday Thu) + (title "St BONIFACE B M III Cl (Priv.) R JCHP") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of the Ascension")) + (has_diocesan_variant true)) + ((date 2025-06-06) (weekday Fri) (title "St NORBERT B C III Cl W # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2025-06-07) (weekday Sat) (title "VIGIL of PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef + ("Pr of the Holy Spirit hodierna die Proper Communic Proper Hanc igitur")) + (has_diocesan_variant false)) + ((date 2025-06-08) (weekday Sun) (title "PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-09) (weekday Mon) (title "WHIT MONDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-10) (weekday Tue) (title "WHIT TUESDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-11) (weekday Wed) + (title "WHIT WEDNESDAY (EMBER DAY) I Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-12) (weekday Thu) (title "WHIT THURSDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-13) (weekday Fri) (title "WHIT FRIDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-14) (weekday Sat) (title "WHIT SATURDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2025-06-15) (weekday Sun) (title "The MOST HOLY TRINITY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-06-16) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 1st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-06-17) (weekday Tue) + (title "St GREGORY BARBARIGO B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-06-18) (weekday Wed) + (title "St EPHREM the SYRIAN Deacon C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-06-19) (weekday Thu) (title "CORPUS CHRISTI I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Most Holy Sacrament or Common Pr")) + (has_diocesan_variant false)) + ((date 2025-06-20) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 1st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-06-21) (weekday Sat) + (title "St ALOYSIUS GONZAGA C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-06-22) (weekday Sun) + (title "2nd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-06-23) (weekday Mon) + (title "VIGIL of The NATIVITY of JOHN the BAPTIST \194\167 II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-06-24) (weekday Tue) + (title "The NATIVITY of JOHN the BAPTIST \194\167 I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2025-06-25) (weekday Wed) (title "St WILLIAM Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-06-26) (weekday Thu) + (title "SS JOHN & PAUL \194\167 MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-06-27) (weekday Fri) (title "The SACRED HEART of JESUS I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Sacred Heart")) (has_diocesan_variant true)) + ((date 2025-06-28) (weekday Sat) + (title "VIGIL of SS PETER \194\167 & PAUL \194\167 App II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-06-29) (weekday Sun) + (title "SS PETER \194\167 & PAUL \194\167 App I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2025-06-30) (weekday Mon) + (title "The COMMEMORATION of St PAUL \194\167 Ap III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2025-07-01) (weekday Tue) + (title "The MOST PRECIOUS BLOOD of OUR LORD JESUS CHRIST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2025-07-02) (weekday Wed) + (title "The VISITATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Visitatione")) + (has_diocesan_variant false)) + ((date 2025-07-03) (weekday Thu) (title "St IRENAEUS B M III Cl R # JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-04) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 3rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-05) (weekday Sat) + (title "St ANTHONY MARY ZACCARIA C III Cl W # IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-07-06) (weekday Sun) + (title "4th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-07-07) (weekday Mon) + (title "SS CYRIL & METHODIUS BB CC III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-08) (weekday Tue) (title "St ELIZABETH Q W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-09) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-10) (weekday Thu) + (title "The SEVEN HOLY BROTHERS MM & SS RUFINA & SECUNDA VV MM") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-07-11) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 4th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-12) (weekday Sat) (title "St JOHN GUALBERTI Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-07-13) (weekday Sun) + (title "5th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-07-14) (weekday Mon) + (title "St BONAVENTURE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-07-15) (weekday Tue) (title "St HENRY Emperor C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-16) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 5th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-17) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 5th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-18) (weekday Fri) + (title "St CAMILLUS de LELLIS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-19) (weekday Sat) + (title "St VINCENT de PAUL C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-07-20) (weekday Sun) + (title "6th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-07-21) (weekday Mon) + (title "St LAURENCE of BRINDISI C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-22) (weekday Tue) + (title "St MARY MAGDALEN Penitent III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-23) (weekday Wed) (title "St APOLLINARIS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-07-24) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 6th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-07-25) (weekday Fri) (title "St JAMES \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2025-07-26) (weekday Sat) + (title "St ANNE MOTHER of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-07-27) (weekday Sun) + (title "7th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-07-28) (weekday Mon) + (title "SS NAZARIUS & CELSUS MM & VICTOR I P M & INNOCENT I P C III Cl") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-07-29) (weekday Tue) (title "St MARTHA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-07-30) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-07-31) (weekday Thu) (title "St IGNATIUS C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-08-01) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-08-02) (weekday Sat) + (title "St ALPHONSUS MARIA LIGUORI B C D III Cl (Priv.) W IH JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-03) (weekday Sun) + (title "8th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-08-04) (weekday Mon) (title "St DOMINIC C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-05) (weekday Tue) + (title "The DEDICATION of St MARY of the SNOWS III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2025-08-06) (weekday Wed) + (title "The TRANSFIGURATION of OUR LORD JESUS CHRIST II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-07) (weekday Thu) (title "St CAJETAN C III Cl W # JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-08) (weekday Fri) + (title "St JOHN MARY VIANNEY C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-08-09) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-08-10) (weekday Sun) + (title "9th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-08-11) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 9th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-08-12) (weekday Tue) (title "St CLARE V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-13) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 9th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-08-14) (weekday Thu) + (title "VIGIL of The ASSUMPTION of the BVM II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-15) (weekday Fri) (title "The ASSUMPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Assumptione")) + (has_diocesan_variant false)) + ((date 2025-08-16) (weekday Sat) + (title "St JOACHIM FATHER of the BVM C II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-08-17) (weekday Sun) + (title "10th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-08-18) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 10th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-08-19) (weekday Tue) (title "St JOHN EUDES C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-08-20) (weekday Wed) (title "St BERNARD Ab D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-08-21) (weekday Thu) + (title "St JANE FRANCES FR\195\137MIOT de CHANTAL W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-08-22) (weekday Fri) + (title "The IMMACULATE HEART of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2025-08-23) (weekday Sat) (title "St PHILIP BENIZI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-24) (weekday Sun) + (title "11th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-08-25) (weekday Mon) (title "St LOUIS K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-26) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 11th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-08-27) (weekday Wed) + (title "St JOSEPH CALASANCTIUS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-08-28) (weekday Thu) + (title "St AUGUSTINE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-08-29) (weekday Fri) + (title "The BEHEADING of St JOHN the BAPTIST \194\167 III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2025-08-30) (weekday Sat) (title "St ROSE of LIMA V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-08-31) (weekday Sun) + (title "12th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-09-01) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 12th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-02) (weekday Tue) (title "St STEPHEN K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-09-03) (weekday Wed) (title "St PIUS X P C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-09-04) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 12th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-05) (weekday Fri) + (title "St LAURENCE JUSTINIAN B C III Cl W # SH") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-06) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-09-07) (weekday Sun) + (title "13th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-09-08) (weekday Mon) (title "The NATIVITY of the BVM II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Nativitate")) + (has_diocesan_variant false)) + ((date 2025-09-09) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 13th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-09-10) (weekday Wed) + (title "St NICOLAS of TOLENTINO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-09-11) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 13th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-12) (weekday Fri) + (title "The MOST HOLY NAME of MARY III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2025-09-13) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-09-14) (weekday Sun) + (title "The EXALTATION of the HOLY CROSS II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2025-09-15) (weekday Mon) + (title "The SEVEN SORROWS of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Transfixione")) + (has_diocesan_variant false)) + ((date 2025-09-16) (weekday Tue) + (title + "SS CORNELIUS \194\167 P & CYPRIAN \194\167 B MM III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-09-17) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 14th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-09-18) (weekday Thu) + (title "St JOSEPH of CUPERTINO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-09-19) (weekday Fri) + (title "St JANUARIUS B & COMPS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-09-20) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-09-21) (weekday Sun) + (title "15th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-09-22) (weekday Mon) + (title "St THOMAS of VILLANOVA B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-23) (weekday Tue) (title "St LINUS P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-09-24) (weekday Wed) + (title "EMBER WEDNESDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-25) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-26) (weekday Fri) + (title "EMBER FRIDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-09-27) (weekday Sat) + (title "EMBER SATURDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-09-28) (weekday Sun) + (title "16th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-09-29) (weekday Mon) + (title "The DEDICATION of St MICHAEL Archangel I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant false)) + ((date 2025-09-30) (weekday Tue) + (title "St JEROME Priest C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-01) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 16th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-10-02) (weekday Thu) + (title "The HOLY GUARDIAN ANGELS III Cl (Priv.) W JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant false)) + ((date 2025-10-03) (weekday Fri) + (title "St TERESA of the CHILD JESUS V III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-04) (weekday Sat) + (title "St FRANCIS of ASSISI C III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-05) (weekday Sun) + (title "17th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-10-06) (weekday Mon) (title "St BRUNO C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-10-07) (weekday Tue) (title "OUR LADY of the ROSARY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2025-10-08) (weekday Wed) (title "St BRIDGET W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-09) (weekday Thu) (title "St JOHN LEONARDI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-10) (weekday Fri) (title "St FRANCIS BORGIA C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-11) (weekday Sat) + (title "The MOTHERHOOD of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2025-10-12) (weekday Sun) + (title "18th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-10-13) (weekday Mon) (title "St EDWARD K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-14) (weekday Tue) + (title "St CALLISTUS I P M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-10-15) (weekday Wed) (title "St TERESA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-16) (weekday Thu) (title "St HEDWIG W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-17) (weekday Fri) + (title "St MARGARET MARY ALACOQUE V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-18) (weekday Sat) (title "St LUKE Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2025-10-19) (weekday Sun) + (title "19th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-10-20) (weekday Mon) (title "St JOHN CANTIUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-10-21) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 19th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-22) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 19th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-23) (weekday Thu) + (title "St ANTHONY MARY CLARET B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-10-24) (weekday Fri) (title "St RAPHAEL Archangel III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant true)) + ((date 2025-10-25) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-10-26) (weekday Sun) (title "CHRIST the KING I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Our Lord Jesus Christ the King")) + (has_diocesan_variant false)) + ((date 2025-10-27) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 20th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-10-28) (weekday Tue) + (title "SS SIMON \194\167 & JUDE \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2025-10-29) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 20th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-30) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 20th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-10-31) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 20th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-11-01) (weekday Sat) (title "ALL SAINTS' DAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of All Saints and Patron Saints or Common Pr")) + (has_diocesan_variant false)) + ((date 2025-11-02) (weekday Sun) + (title "21st SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-11-03) (weekday Mon) (title "ALL SOULS' DAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Dead No Blessing")) (has_diocesan_variant false)) + ((date 2025-11-04) (weekday Tue) (title "St CHARLES B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-05) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 21st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-06) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 21st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-07) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 21st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-08) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2025-11-09) (weekday Sun) + (title "The DEDICATION of the ARCHBASILICA of OUR SAVIOUR II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Dedication of a Church or Pr of the Trinity")) + (has_diocesan_variant false)) + ((date 2025-11-10) (weekday Mon) (title "St ANDREW AVELLINO C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-11-11) (weekday Tue) (title "St MARTIN B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-12) (weekday Wed) (title "St MARTIN I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-13) (weekday Thu) (title "St DIDACUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-14) (weekday Fri) (title "St JOSAPHAT B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-11-15) (weekday Sat) + (title "St ALBERT the GREAT B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-16) (weekday Sun) + (title "23rd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-11-17) (weekday Mon) + (title "St GREGORY THAUMATURGUS B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-18) (weekday Tue) + (title + "The DEDICATION of the BASILICAS of SS PETER & PAUL III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Dedication of a Church or Common Pr")) + (has_diocesan_variant false)) + ((date 2025-11-19) (weekday Wed) (title "St ELIZABETH W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-20) (weekday Thu) (title "St FELIX de VALOIS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-11-21) (weekday Fri) + (title "The PRESENTATION of the BVM III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Pr\195\166sentatione")) + (has_diocesan_variant false)) + ((date 2025-11-22) (weekday Sat) + (title "St CECILIA \194\167 V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2025-11-23) (weekday Sun) + (title "24th & LAST SUNDAY After PENTECOST II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2025-11-24) (weekday Mon) + (title "St JOHN of the CROSS C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-25) (weekday Tue) (title "St CATHERINE V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-26) (weekday Wed) (title "St SILVESTER Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-11-27) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-11-28) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-11-29) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-11-30) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-01) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-02) (weekday Tue) (title "St BIBIANA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-03) (weekday Wed) + (title "St FRANCIS XAVIER C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-04) (weekday Thu) + (title "St PETER CHRYSOLOGUS B C D III Cl W # JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-12-05) (weekday Fri) (title "FERIA III Cl V SH") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-06) (weekday Sat) + (title "St NICOLAS B C III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-07) (weekday Sun) (title "2nd SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-08) (weekday Mon) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant true)) + ((date 2025-12-09) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-10) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-11) (weekday Thu) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-12) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-13) (weekday Sat) (title "St LUCY V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-14) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-15) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-16) (weekday Tue) (title "St EUSEBIUS B M III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-17) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-18) (weekday Thu) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-19) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-20) (weekday Sat) (title "EMBER SATURDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-21) (weekday Sun) (title "4th SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-22) (weekday Mon) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-23) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-24) (weekday Wed) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-25) (weekday Thu) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at")) + (has_diocesan_variant false)) + ((date 2025-12-26) (weekday Fri) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-27) (weekday Sat) + (title "St JOHN \194\167 Ap Evangelist II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-28) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2025-12-29) (weekday Mon) + (title "5th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2025-12-30) (weekday Tue) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-31) (weekday Wed) + (title "7th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false))) diff --git a/test/fixtures/lms-ordo-2025-2026.sexp b/test/fixtures/lms-ordo-2025-2026.sexp new file mode 100644 index 0000000..13b1d11 --- /dev/null +++ b/test/fixtures/lms-ordo-2025-2026.sexp @@ -0,0 +1,1706 @@ +; /tmp/lms-ordo-2025-2026.sexp -- Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1), +; extending Task 6's single LMS fixture (2024-2025) to three editions of +; the Latin Mass Society's own printed Ordo for England & Wales -- a +; lineage independent of Divinum Officium/missalemeum/lectio (layers 3-4) +; and of the electronic LT.txt transcription (layers 1-2/5): a physically +; printed, professionally-compiled liturgical calendar with its own ISBN. +; +; Generator: tools/extract_lms_ordo.ml -- do not hand-edit; re-run against +; a fresh pdftotext dump and commit the diff instead. +; +; Source: "The Ordo 2025-2026", compiled by Peter Day-Milne, The Latin +; Mass Society, 9 Mallow Street, London EC1Y 8RQ (title page and +; colophon, verified directly against the PDF's own extracted text -- +; ISBN 978-1-7392096-5-0, Copyright (c) The Latin Mass Society, UK 2025). +; PDF metadata: Author "Peter Day-Milne", Producer "LibreOffice 25.2.6.2 (X86_64) / LibreOffice Community", CreationDate 2025-10-23, 146 pages. +; URL (NOT found by URL-pattern web search this session (unlike the 2023-2024 and 2024-2025 editions, no exact download link matching this PDF's own filename/version turned up under lms.org.uk/sites/default/files/u5374/; several near-miss candidates were checked and rejected -- none matched this PDF's own metadata) -- left honestly blank rather than guessed; the file was supplied locally to this session, not fetched by this tool): +; (not found -- see the note on this line) +; The local PDF (docs/research/ordo/lms-ordo-2025-2026.pdf) is gitignored +; (CLAUDE.md: "docs/ is gitignored"), so this header, not git, is this +; fixture's only record of where it came from. +; SHA-256 of docs/research/ordo/lms-ordo-2025-2026.pdf: 3d71ad56af3fc8d9c1b37515bf9d946025961f8ef415c3b92520b9de7661f8a3 +; Extracted (UTC): 2026-08-23 +; Exact commands: +; pdftotext -layout docs/research/ordo/lms-ordo-2025-2026.pdf /tmp/lms.txt +; dune exec tools/extract_lms_ordo.exe -- /tmp/lms.txt \ +; docs/research/ordo/lms-ordo-2025-2026.pdf /tmp/lms-ordo-2025-2026.sexp +; +; COVERAGE: 399 day-rows, 2025-11-28 through 2026-12-31 (starting 28 November 2025 ("End of November 2025", the same shape as the 2024-2025 edition -- Advent Sunday 2025 fell on 30 November, so only 3 tail days remained; note this excludes 27 November 2025, which the PRECEDING edition's own window (2024-2025, through 2025-12-31) already covers -- a one-day-short overlap between consecutive editions' own windows, not a gap or a bug in either extraction, +; through the day before a malformed trailing entry the extractor +; deliberately stops before -- see CHARACTERISATION below). +; +; CHARACTERISATION FINDINGS (Step 1, non-negotiable per the task brief -- +; the extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; every LMS edition, including this one, is probed +; with the same discipline before a single divergence is adjudicated): +; +; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed again for +; THIS edition: it carries many more Gl/Cr pairs than day-rows, because +; every diocesan variant repeats its own "Gl ... Cr ... Pr of ..." +; line). This extractor resolves the day's OWN office by taking the +; FIRST Gl/Cr pair in reading order, which the source's own layout +; guarantees is the universal entry's (diocesan variants are always +; introduced by a colon-terminated diocese-list line that comes AFTER +; the universal block, never before -- checked structurally, not +; assumed, in every sampled block during development, this edition +; included). +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN (not merely copied from a prior +; edition's findings) before a single row of this fixture is trusted -- +; the technique CLAUDE.md records as the one that catches a source +; silently omitting the very thing it is meant to witness. This run's +; own extracted [rows] were checked against every one of the following +; before this header was even written; a failure here is a hard [die], +; not a printed claim: +; 2025-11-30 (Advent Sunday, RG 475(a)) -> TRUE +; 2025-12-01 (ordinary Advent feria, RG 476(b)/(d)) -> FALSE +; 2025-12-26 (St Stephen, II class, inside the Nativity octave, RG 475(d)) -> TRUE +; 2026-08-10 (St Laurence, II class martyr, no Lord/BVM/apostle clause applies, RG 476(b) -- St Joachim (16 August) is IMPEDED by a Sunday in this edition's own calendar (12th Sunday after Pentecost), so this edition needed a DIFFERENT sharp non-octave II-class pairing than the 2023-2024/2024-2025 editions used; a real, edition-specific finding, not an extraction quirk) -> FALSE +; 2026-08-15 (the Assumption, I class, RG 475(b)) -> TRUE +; All 5 predictions confirmed, both directions (TRUE and FALSE each +; independently witnessed) -- this edition is discriminating, not a +; constant, on the Creed. +; +; 3. The BVM-Saturday roman numeral (I-V, "Missae de sancta Maria in +; sabbato", RG 309(a)) is anchored by WHOLE-LINE match against the five +; literal strings below, NEVER by substring search: "V Mass of BVM" is +; a substring of "IV Mass of BVM", so a naive `contains` check +; misreads every fourth-Mass day as the fifth (the coordinator's own +; misreading, recorded and retracted in commit 27b07b4 before Task 6 +; existed; the same anchoring logic runs unchanged for every edition). +; +; 4. SCOPE EXCLUDED, quantified, not silently dropped: +; - Diocesan variants: present on 163 of 399 days (40.9%) -- their own +; text is read only far enough to set [has_diocesan_variant], +; never compared, because colitur computes the UNIVERSAL General +; Roman Calendar only, with no diocesan overlay loaded. +; - The single malformed trailing entry ("...The OCTAVE DAY of the +; NATIVITY..." with a bare 4-digit token where a weekday+day-number +; pair belongs) is excluded outright: the extractor's own stop +; marker (a line whose first token is a bare 4-digit token) halts +; the scan before it. CONFIRMED IDENTICAL, word for word, across +; ALL FOUR known editions of this publisher's Ordo (2023-2024, +; 2024-2025, 2025-2026, and the 2024-2025 fixture's own prior +; header) -- always the literal stray year token "2025", regardless +; of which edition or which real trailing year it should read: a +; stale copy-paste leftover the compiler's own master document +; carries forward unedited release to release (even the 2024-2025 +; PDF's own tail page footer nearby still reads "Latin Mass Society +; Ordo 2021-2022"), not something specific to this edition. +; - Front matter, the Abbreviations/Rubrical-Primer/Breviary sections, +; and the "When may I say...?"/Appendix tail are never scanned at +; all (the extractor's own start/stop markers bound it to the Ordo +; proper). +; +; 5. THE "Pr of" (PREFACE) COLUMN (Preface-witnesses task, 2026-08-23) -- +; [row.praef], the RAW text from the FIRST "Pr of ..." / "Common Pr" +; match in the universal block's own reading order (the same +; FIRST-in-reading-order discipline finding 1 above already +; establishes for Gl/Cr). CAPTURED, NOT CLASSIFIED by this tool -- +; classification into {!Colitur_kernel.Preface.t} and the comparison +; against {!Rite_ef.Rubrics_ef.preface} both happen test-side +; (test/test_lms_ordo.ml's own [classify_praef]). +; +; CHARACTERISATION FINDING, non-negotiable per the same discipline as +; finding 2: this Ordo prints OPTION LISTS ("Pr of X or Pr of Y or +; Common Pr"), not always a single value -- and several of the named +; options ("Martyrs", "All Saints and Patron Saints" [diocesan-only, +; every occurrence checked falls strictly after this block's own +; colon boundary], "the Dedication of a Church", "the Most Holy +; Sacrament" [Corpus Christi's own universal entry], "St John the +; Baptist", "the Angels") are genuinely NOT among the fourteen the +; 1962 Missale Romanum's own RG 484-497 enumerate (docs/research/LT.txt, +; lines 3936-4020, checked directly: no "de Martyribus"/"de Angelis"/ +; "de Dedicatione"/"de Ss.mo Sacramento"/"de S. Ioanne Baptista" clause +; exists anywhere in 482-499). Every one of these extras, in every +; instance found in this edition's UNIVERSAL block, is printed +; ALONGSIDE a genuine RG 482 answer (most often "or Common Pr"; on 24 +; March-shaped days, "or Pr of Lent", the live RG 486(b) de-Tempore +; answer) -- never as the row's OWN AND ONLY option. This is why the +; test-side comparison checks colitur's single computed answer is a +; MEMBER of this row's own parsed option set (dropping any unmapped +; extra name from that set first), not string equality against +; whichever option happens to print first -- the same "capture, don't +; force a match invented at extraction time" discipline +; tools/extract_fiuv_ordo.ml's own [row.praef] doc comment already +; states for a different publisher's format. +; +; OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.preface (RG +; 482-499), the SAME discipline as finding 2, applied to this new +; column -- RE-CHECKED BY THIS TOOL RUN before this header was +; written; a failed probe is a hard [die]: +; 2025-12-25 (the Nativity of Our Lord, I class, RG 484(a)) -> "Pr of the Nativity" +; 2026-06-29 (SS Peter & Paul, I class, RG 497) -> "Pr of the Apostles" +; 2026-11-02 (All Souls' Day, I class, RG 499) -> "Pr of the Dead" +; All 3 predictions confirmed -- this column, too, is discriminating, +; not a constant, across three different RG-cited outcomes (Nativity/ +; Apostles/Requiem). +; +; COVERAGE: 1 of 399 rows have no "Pr of"/"Common Pr" text found at +; all -- checked directly against this window's own Good Friday +; (Easter-2): its block carries NO Gl/Cr/Pr line whatsoever in this +; source (the 1955-restored Holy Week's own liturgical action has no +; Mass that day at all -- the SAME structural fact +; {!test_creed_coverage}'s own [window_good_fridays] already asserts +; for Gl/Cr), so [praef] shares that single expected gap rather than +; having a coverage gap of its own. +(((date 2025-11-28) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-11-29) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2025-11-30) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-01) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-02) (weekday Tue) (title "St BIBIANA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-03) (weekday Wed) + (title "St FRANCIS XAVIER C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-04) (weekday Thu) + (title "St PETER CHRYSOLOGUS B C D III Cl W # JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2025-12-05) (weekday Fri) (title "FERIA III Cl V SH") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-06) (weekday Sat) + (title "St NICOLAS B C III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-07) (weekday Sun) (title "2nd SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-08) (weekday Mon) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant true)) + ((date 2025-12-09) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-10) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-11) (weekday Thu) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2025-12-12) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-13) (weekday Sat) (title "St LUCY V M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-14) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-15) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-16) (weekday Tue) (title "St EUSEBIUS B M III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-17) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-18) (weekday Thu) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-19) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-20) (weekday Sat) (title "EMBER SATURDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-21) (weekday Sun) (title "4th SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2025-12-22) (weekday Mon) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-23) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2025-12-24) (weekday Wed) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2025-12-25) (weekday Thu) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at")) + (has_diocesan_variant false)) + ((date 2025-12-26) (weekday Fri) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-27) (weekday Sat) + (title "St JOHN \194\167 Ap Evangelist II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-28) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2025-12-29) (weekday Mon) + (title "5th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2025-12-30) (weekday Tue) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2025-12-31) (weekday Wed) + (title "7th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2026-01-01) (weekday Thu) + (title "The OCTAVE DAY of the NATIVITY of the LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2026-01-02) (weekday Fri) (title "FERIA IV Cl W \226\128\160 SH") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2026-01-03) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP") + (formulary_override ("II Mass of BVM")) (bvm_numeral (II)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-01-04) (weekday Sun) + (title "The MOST HOLY NAME of JESUS II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2026-01-05) (weekday Mon) (title "FERIA IV Cl W \226\128\160") + (formulary_override + ("Mass of the Octave Day of the Nativity of the Lord")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2026-01-06) (weekday Tue) (title "The EPIPHANY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany Proper Communic")) + (has_diocesan_variant false)) + ((date 2026-01-07) (weekday Wed) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2026-01-08) (weekday Thu) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2026-01-09) (weekday Fri) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of the Epiphany")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Epiphany")) + (has_diocesan_variant false)) + ((date 2026-01-10) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("II Mass of BVM")) (bvm_numeral (II)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-01-11) (weekday Sun) + (title "The HOLY FAMILY of JESUS, MARY AND JOSEPH II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2026-01-12) (weekday Mon) (title "FERIA IV Cl W \226\128\160") + (formulary_override ("Mass of 1st Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant true)) + ((date 2026-01-13) (weekday Tue) (title "The BAPTISM of OUR LORD II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Epiphany")) (has_diocesan_variant false)) + ((date 2026-01-14) (weekday Wed) (title "St HILARY B C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-01-15) (weekday Thu) + (title "St PAUL the FIRST HERMIT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-01-16) (weekday Fri) (title "St MARCELLUS I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-01-17) (weekday Sat) (title "St ANTHONY Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-18) (weekday Sun) + (title "2nd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-01-19) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after the Epiphany")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-01-20) (weekday Tue) + (title "SS FABIAN P & SEBASTIAN M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-21) (weekday Wed) + (title "St AGNES \194\167 V M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-22) (weekday Thu) + (title "SS VINCENT & ANASTASIUS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-23) (weekday Fri) + (title "St RAYMUND of PENAFORT C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-01-24) (weekday Sat) (title "St TIMOTHY B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-25) (weekday Sun) + (title "3rd SUNDAY after the EPIPHANY II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-01-26) (weekday Mon) (title "St POLYCARP B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-27) (weekday Tue) + (title "St JOHN CHRYSOSTOM B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-28) (weekday Wed) (title "St PETER NOLASCO C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-29) (weekday Thu) + (title "St FRANCIS de SALES B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-30) (weekday Fri) (title "St MARTINA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-01-31) (weekday Sat) (title "St JOHN BOSCO C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-02-01) (weekday Sun) (title "SEPTUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-02-02) (weekday Mon) + (title "The PURIFICATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity")) (has_diocesan_variant false)) + ((date 2026-02-03) (weekday Tue) + (title + "Today may be given the special blessing of candles; the special blessing of throats; and") + (formulary_override ("Mass of Septuagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-02-04) (weekday Wed) (title "St ANDREW CORSINI B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-02-05) (weekday Thu) + (title "St AGATHA \194\167 V M III Cl (Priv.) R JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-02-06) (weekday Fri) (title "St TITUS B C III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-02-07) (weekday Sat) + (title "St ROMUALD Ab III Cl W # IH JCHP*") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-02-08) (weekday Sun) (title "SEXAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-02-09) (weekday Mon) + (title "St CYRIL of ALEXANDRIA B C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-02-10) (weekday Tue) (title "St SCHOLASTICA V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-02-11) (weekday Wed) + (title "The APPARITION of the BVM IMMACULATE III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant true)) + ((date 2026-02-12) (weekday Thu) + (title "The SEVEN HOLY FOUNDERS of the ORDER of the SERVANTS of the") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-02-13) (weekday Fri) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Sexagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-02-14) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("III Mass of BVM")) (bvm_numeral (III)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-02-15) (weekday Sun) (title "QUINQUAGESIMA SUNDAY II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-02-16) (weekday Mon) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Quinquagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-02-17) (weekday Tue) (title "FERIA IV Cl V \226\128\161") + (formulary_override ("Mass of Quinquagesima Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-02-18) (weekday Wed) (title "ASH WEDNESDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-02-19) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-02-20) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-02-21) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-02-22) (weekday Sun) (title "1st SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-02-23) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-02-24) (weekday Tue) (title "St MATTHIAS Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-02-25) (weekday Wed) (title "EMBER WEDNESDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-02-26) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-02-27) (weekday Fri) (title "EMBER FRIDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-02-28) (weekday Sat) (title "EMBER SATURDAY of LENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-01) (weekday Sun) (title "2nd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant true)) + ((date 2026-03-02) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-03) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-04) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-05) (weekday Thu) (title "FERIA III Cl V JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-06) (weekday Fri) + (title "SS PERPETUA \194\167 & FELICITY \194\167 MM III Cl (Priv.) R SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-03-07) (weekday Sat) + (title "St THOMAS AQUINAS C D III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-03-08) (weekday Sun) (title "3rd SUNDAY in LENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-03-09) (weekday Mon) + (title "St FRANCES of ROME W III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Lent")) + (has_diocesan_variant false)) + ((date 2026-03-10) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-11) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-12) (weekday Thu) + (title "St GREGORY I P C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Lent")) + (has_diocesan_variant true)) + ((date 2026-03-13) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-14) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-15) (weekday Sun) (title "4th SUNDAY in LENT I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-03-16) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-17) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-18) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-19) (weekday Thu) + (title "St JOSEPH \194\167 SPOUSE of the BVM C, PATRON of the UNIVERSAL") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in festivitate")) + (has_diocesan_variant false)) + ((date 2026-03-20) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of Lent Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-21) (weekday Sat) (title "St BENEDICT Ab III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Lent")) (has_diocesan_variant false)) + ((date 2026-03-22) (weekday Sun) (title "PASSION SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2026-03-23) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-24) (weekday Tue) + (title "St GABRIEL Archangel III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Pr of the Holy Cross")) + (has_diocesan_variant false)) + ((date 2026-03-25) (weekday Wed) + (title "The ANNUNCIATION of the BVM I Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Annuntiatione")) + (has_diocesan_variant false)) + ((date 2026-03-26) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-27) (weekday Fri) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-28) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant true)) + ((date 2026-03-29) (weekday Sun) (title "PALM SUNDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2026-03-30) (weekday Mon) (title "MONDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-03-31) (weekday Tue) (title "TUESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-04-01) (weekday Wed) (title "WEDNESDAY of HOLY WEEK I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Holy Cross Prayer over the People")) + (has_diocesan_variant false)) + ((date 2026-04-02) (weekday Thu) (title "MAUNDY THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Holy Cross. No Judica No Gloria Patri at")) + (has_diocesan_variant false)) + ((date 2026-04-03) (weekday Fri) (title "GOOD FRIDAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria ()) (creed ()) + (praef ()) (has_diocesan_variant false)) + ((date 2026-04-04) (weekday Sat) (title "HOLY SATURDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter (in hac potissimum nocte).")) + (has_diocesan_variant false)) + ((date 2026-04-05) (weekday Sun) (title "EASTER I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter (die) Proper Communic Proper Hanc igitur")) + (has_diocesan_variant false)) + ((date 2026-04-06) (weekday Mon) (title "EASTER MONDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-07) (weekday Tue) (title "EASTER TUESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-08) (weekday Wed) (title "EASTER WEDNESDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-09) (weekday Thu) (title "EASTER THURSDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-10) (weekday Fri) (title "EASTER FRIDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-11) (weekday Sat) + (title "EASTER SATURDAY (SABBATO in ALBIS) I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of Easter (in hac potissimum die) Proper Communic Proper Hanc")) + (has_diocesan_variant false)) + ((date 2026-04-12) (weekday Sun) (title "LOW SUNDAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-04-13) (weekday Mon) (title "St HERMENEGILD M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-04-14) (weekday Tue) (title "St JUSTIN M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-04-15) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2026-04-16) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2026-04-17) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of Low Sunday")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2026-04-18) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("IV Mass of BVM")) (bvm_numeral (IV)) + (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-04-19) (weekday Sun) (title "2nd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-04-20) (weekday Mon) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2026-04-21) (weekday Tue) (title "St ANSELM B C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-04-22) (weekday Wed) + (title "SS SOTER & CAIUS PP MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-04-23) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2026-04-24) (weekday Fri) + (title "St FIDELIS of SIGMARINGEN M III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-04-25) (weekday Sat) + (title "THE GREATER LITANIES. St MARK Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2026-04-26) (weekday Sun) (title "3rd SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-04-27) (weekday Mon) (title "St PETER CANISIUS C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-04-28) (weekday Tue) + (title "St PAUL of the CROSS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2026-04-29) (weekday Wed) (title "St PETER M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-04-30) (weekday Thu) + (title "St CATHERINE of SIENA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-05-01) (weekday Fri) + (title "St JOSEPH \194\167 the WORKER, SPOUSE of the BVM C I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St Joseph Et te in solemnitate")) + (has_diocesan_variant false)) + ((date 2026-05-02) (weekday Sat) + (title "St ATHANASIUS B C D III Cl (Priv.) W IH JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-05-03) (weekday Sun) (title "4th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-05-04) (weekday Mon) (title "St MONICA W III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-05-05) (weekday Tue) (title "St PIUS V P C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-05-06) (weekday Wed) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant true)) + ((date 2026-05-07) (weekday Thu) + (title "St STANISLAUS B M III Cl R # JCHP*") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-05-08) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of 4th Sunday after Easter")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of Easter")) + (has_diocesan_variant false)) + ((date 2026-05-09) (weekday Sat) + (title "St GREGORY NAZIANZEN B C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-05-10) (weekday Sun) (title "5th SUNDAY after EASTER II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Easter")) (has_diocesan_variant false)) + ((date 2026-05-11) (weekday Mon) + (title "SS PHILIP \194\167 & JAMES \194\167 App II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2026-05-12) (weekday Tue) + (title "SS NEREUS, ACHILLEUS, DOMITILLA V, & PANCRAS MM III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-05-13) (weekday Wed) (title "VIGIL of The ASCENSION II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Easter")) (has_diocesan_variant true)) + ((date 2026-05-14) (weekday Thu) (title "The ASCENSION I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension Proper Communic")) + (has_diocesan_variant false)) + ((date 2026-05-15) (weekday Fri) + (title "St JOHN BAPTIST de la SALLE C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2026-05-16) (weekday Sat) (title "St UBALDUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2026-05-17) (weekday Sun) + (title "SUNDAY after the ASCENSION II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Ascension")) (has_diocesan_variant false)) + ((date 2026-05-18) (weekday Mon) (title "St VENANTIUS M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Pr of the Ascension")) + (has_diocesan_variant false)) + ((date 2026-05-19) (weekday Tue) + (title "St PETER CELESTINE P C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2026-05-20) (weekday Wed) + (title "St BERNARDINE of SIENA C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Ascension")) (has_diocesan_variant true)) + ((date 2026-05-21) (weekday Thu) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant true)) + ((date 2026-05-22) (weekday Fri) (title "FERIA IV Cl W \226\128\161") + (formulary_override ("Mass of the Ascension")) (bvm_numeral ()) + (gloria (true)) (creed (false)) (praef ("Pr of the Ascension")) + (has_diocesan_variant false)) + ((date 2026-05-23) (weekday Sat) (title "VIGIL of PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef + ("Pr of the Holy Spirit hodierna die Proper Communic Proper Hanc igitur")) + (has_diocesan_variant false)) + ((date 2026-05-24) (weekday Sun) (title "PENTECOST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-25) (weekday Mon) (title "WHIT MONDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-26) (weekday Tue) (title "WHIT TUESDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-27) (weekday Wed) + (title "WHIT WEDNESDAY (EMBER DAY) I Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-28) (weekday Thu) (title "WHIT THURSDAY I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-29) (weekday Fri) (title "WHIT FRIDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-30) (weekday Sat) (title "WHIT SATURDAY (EMBER DAY) I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Spirit hodierna die")) + (has_diocesan_variant false)) + ((date 2026-05-31) (weekday Sun) (title "The MOST HOLY TRINITY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-06-01) (weekday Mon) (title "St ANGELA MERICI V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-02) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 1st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-03) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 1st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-06-04) (weekday Thu) (title "CORPUS CHRISTI I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Most Holy Sacrament or Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-05) (weekday Fri) + (title "St BONIFACE B M III Cl (Priv.) R SH") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-06) (weekday Sat) + (title "St NORBERT B C III Cl W # IH JCHP") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-06-07) (weekday Sun) + (title "2nd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-06-08) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-09) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 2nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-10) (weekday Wed) (title "St MARGARET Q W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-06-11) (weekday Thu) (title "St BARNABAS Ap III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-06-12) (weekday Fri) (title "The SACRED HEART of JESUS I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Sacred Heart")) (has_diocesan_variant false)) + ((date 2026-06-13) (weekday Sat) + (title "St ANTHONY of PADUA C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-14) (weekday Sun) + (title "3rd SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-06-15) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 3rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-06-16) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 3rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-06-17) (weekday Wed) + (title "St GREGORY BARBARIGO B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-18) (weekday Thu) + (title "St EPHREM the SYRIAN Deacon C D III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-06-19) (weekday Fri) + (title "St JULIANA FALCONIERI V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-06-20) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-06-21) (weekday Sun) + (title "4th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-06-22) (weekday Mon) (title "St PAULINUS B C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-23) (weekday Tue) + (title "VIGIL of The NATIVITY of JOHN the BAPTIST \194\167 II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-06-24) (weekday Wed) + (title "The NATIVITY of JOHN the BAPTIST \194\167 I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2026-06-25) (weekday Thu) (title "St WILLIAM Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-26) (weekday Fri) + (title "SS JOHN & PAUL \194\167 MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-06-27) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-06-28) (weekday Sun) + (title "5th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-06-29) (weekday Mon) + (title "SS PETER \194\167 & PAUL \194\167 App I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2026-06-30) (weekday Tue) + (title "The COMMEMORATION of St PAUL \194\167 Ap III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2026-07-01) (weekday Wed) + (title "The MOST PRECIOUS BLOOD of OUR LORD JESUS CHRIST I Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2026-07-02) (weekday Thu) + (title "The VISITATION of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Visitatione")) + (has_diocesan_variant false)) + ((date 2026-07-03) (weekday Fri) (title "St IRENAEUS B M III Cl R # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-04) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-07-05) (weekday Sun) + (title "6th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-07-06) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 6th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-07-07) (weekday Tue) + (title "SS CYRIL & METHODIUS BB CC III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-08) (weekday Wed) (title "St ELIZABETH Q W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-09) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 6th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-10) (weekday Fri) + (title "The SEVEN HOLY BROTHERS MM & SS RUFINA & SECUNDA VV MM") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-07-11) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-07-12) (weekday Sun) + (title "7th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-07-13) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-07-14) (weekday Tue) + (title "St BONAVENTURE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-07-15) (weekday Wed) (title "St HENRY Emperor C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-16) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-17) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 7th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-18) (weekday Sat) + (title "St CAMILLUS de LELLIS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-19) (weekday Sun) + (title "8th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-07-20) (weekday Mon) (title "St JEROME EMILIANI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-07-21) (weekday Tue) + (title "St LAURENCE of BRINDISI C D III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-22) (weekday Wed) + (title "St MARY MAGDALEN Penitent III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-23) (weekday Thu) (title "St APOLLINARIS B M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-07-24) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 8th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-07-25) (weekday Sat) (title "St JAMES \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-07-26) (weekday Sun) + (title "9th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-07-27) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 9th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-07-28) (weekday Tue) + (title "SS NAZARIUS & CELSUS MM & VICTOR I P M & INNOCENT I P C III Cl") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-07-29) (weekday Wed) (title "St MARTHA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-07-30) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 9th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-07-31) (weekday Fri) (title "St IGNATIUS C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-08-01) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-08-02) (weekday Sun) + (title "10th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-08-03) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 10th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-04) (weekday Tue) (title "St DOMINIC C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-05) (weekday Wed) + (title "The DEDICATION of St MARY of the SNOWS III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2026-08-06) (weekday Thu) + (title "The TRANSFIGURATION of OUR LORD JESUS CHRIST II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-07) (weekday Fri) (title "St CAJETAN C III Cl W # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-08) (weekday Sat) + (title "St JOHN MARY VIANNEY C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-08-09) (weekday Sun) + (title "11th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-08-10) (weekday Mon) (title "St LAURENCE \194\167 M II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-11) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 11th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-12) (weekday Wed) (title "St CLARE V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-13) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 11th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-14) (weekday Fri) + (title "VIGIL of The ASSUMPTION of the BVM II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-15) (weekday Sat) (title "The ASSUMPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Assumptione")) + (has_diocesan_variant false)) + ((date 2026-08-16) (weekday Sun) + (title "12th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-08-17) (weekday Mon) (title "St HYACINTH C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-08-18) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 12th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-19) (weekday Wed) (title "St JOHN EUDES C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-08-20) (weekday Thu) (title "St BERNARD Ab D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-08-21) (weekday Fri) + (title "St JANE FRANCES FR\195\137MIOT de CHANTAL W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-08-22) (weekday Sat) + (title "The IMMACULATE HEART of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2026-08-23) (weekday Sun) + (title "13th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-08-24) (weekday Mon) + (title "St BARTHOLOMEW \194\167 Ap II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-08-25) (weekday Tue) (title "St LOUIS K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-08-26) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 13th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-27) (weekday Thu) + (title "St JOSEPH CALASANCTIUS C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-08-28) (weekday Fri) + (title "St AUGUSTINE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-08-29) (weekday Sat) + (title "The BEHEADING of St JOHN the BAPTIST \194\167 III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of St John the Baptist or Common Pr")) + (has_diocesan_variant false)) + ((date 2026-08-30) (weekday Sun) + (title "14th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-08-31) (weekday Mon) (title "St RAYMUND NONNATUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-09-01) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 14th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-02) (weekday Wed) (title "St STEPHEN K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-09-03) (weekday Thu) + (title "St PIUS X P C III Cl (Priv.) W JCHP") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-04) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 14th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-05) (weekday Sat) + (title "St LAURENCE JUSTINIAN B C III Cl W # IH JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-09-06) (weekday Sun) + (title "15th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-09-07) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-09-08) (weekday Tue) (title "The NATIVITY of the BVM II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Nativitate")) + (has_diocesan_variant false)) + ((date 2026-09-09) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-09-10) (weekday Thu) + (title "St NICOLAS of TOLENTINO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-09-11) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 15th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-12) (weekday Sat) + (title "The MOST HOLY NAME of MARY III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant true)) + ((date 2026-09-13) (weekday Sun) + (title "16th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-09-14) (weekday Mon) + (title "The EXALTATION of the HOLY CROSS II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Holy Cross")) (has_diocesan_variant false)) + ((date 2026-09-15) (weekday Tue) + (title "The SEVEN SORROWS of the BVM II Cl W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Transfixione")) + (has_diocesan_variant false)) + ((date 2026-09-16) (weekday Wed) + (title + "SS CORNELIUS \194\167 P & CYPRIAN \194\167 B MM III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-09-17) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 16th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-09-18) (weekday Fri) + (title "St JOSEPH of CUPERTINO C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-09-19) (weekday Sat) + (title "St JANUARIUS B & COMPS MM III Cl R #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-09-20) (weekday Sun) + (title "17th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-09-21) (weekday Mon) + (title "St MATTHEW \194\167 Ap Evangelist II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant true)) + ((date 2026-09-22) (weekday Tue) + (title "St THOMAS of VILLANOVA B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-23) (weekday Wed) + (title "EMBER WEDNESDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-24) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 17th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-25) (weekday Fri) + (title "EMBER FRIDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-26) (weekday Sat) + (title "EMBER SATURDAY of SEPTEMBER II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-09-27) (weekday Sun) + (title "18th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-09-28) (weekday Mon) (title "St WENCESLAUS Duke M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-09-29) (weekday Tue) + (title "The DEDICATION of St MICHAEL Archangel I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant false)) + ((date 2026-09-30) (weekday Wed) + (title "St JEROME Priest C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-01) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 18th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-10-02) (weekday Fri) + (title "The HOLY GUARDIAN ANGELS III Cl (Priv.) W SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant false)) + ((date 2026-10-03) (weekday Sat) + (title "St TERESA of the CHILD JESUS V III Cl (Priv.) W IH JCHP*") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-04) (weekday Sun) + (title "19th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-10-05) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 19th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-06) (weekday Tue) (title "St BRUNO C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-10-07) (weekday Wed) (title "OUR LADY of the ROSARY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Festivitate")) + (has_diocesan_variant false)) + ((date 2026-10-08) (weekday Thu) (title "St BRIDGET W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-09) (weekday Fri) (title "St JOHN LEONARDI C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-10) (weekday Sat) (title "St FRANCIS BORGIA C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-11) (weekday Sun) + (title "20th SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-10-12) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 20th Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-13) (weekday Tue) (title "St EDWARD K C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-14) (weekday Wed) + (title "St CALLISTUS I P M III Cl (Priv.) R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-10-15) (weekday Thu) (title "St TERESA V III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-16) (weekday Fri) (title "St HEDWIG W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-17) (weekday Sat) + (title "St MARGARET MARY ALACOQUE V III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-18) (weekday Sun) + (title "21st SUNDAY after PENTECOST II Cl G") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-10-19) (weekday Mon) + (title "St PETER of ALCANTARA C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-20) (weekday Tue) (title "St JOHN CANTIUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-10-21) (weekday Wed) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 21st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-22) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 21st Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-23) (weekday Fri) + (title "St ANTHONY MARY CLARET B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-10-24) (weekday Sat) (title "St RAPHAEL Archangel III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Angels or Common Pr")) (has_diocesan_variant true)) + ((date 2026-10-25) (weekday Sun) (title "CHRIST the KING I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of Our Lord Jesus Christ the King")) + (has_diocesan_variant false)) + ((date 2026-10-26) (weekday Mon) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-27) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-10-28) (weekday Wed) + (title "SS SIMON \194\167 & JUDE \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-10-29) (weekday Thu) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-30) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 22nd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-10-31) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-11-01) (weekday Sun) (title "ALL SAINTS' DAY I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of All Saints and Patron Saints or Pr of the Trinity")) + (has_diocesan_variant false)) + ((date 2026-11-02) (weekday Mon) (title "ALL SOULS' DAY I Cl B") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Pr of the Dead No Blessing")) (has_diocesan_variant false)) + ((date 2026-11-03) (weekday Tue) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-11-04) (weekday Wed) (title "St CHARLES B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-05) (weekday Thu) (title "FERIA IV Cl G \226\128\161 JCHP") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-11-06) (weekday Fri) (title "FERIA IV Cl G \226\128\161 SH") + (formulary_override ("Mass of 23rd Sunday after Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-11-07) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160 IH JCHP*") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant true)) + ((date 2026-11-08) (weekday Sun) + (title "5th SUNDAY remaining after the EPIPHANY II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-11-09) (weekday Mon) + (title "The DEDICATION of the ARCHBASILICA of OUR SAVIOUR II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Dedication of a Church or Common Pr")) + (has_diocesan_variant false)) + ((date 2026-11-10) (weekday Tue) (title "St ANDREW AVELLINO C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-11-11) (weekday Wed) (title "St MARTIN B C III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-12) (weekday Thu) (title "St MARTIN I P M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-13) (weekday Fri) (title "St DIDACUS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-14) (weekday Sat) (title "St JOSAPHAT B M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-11-15) (weekday Sun) + (title "6th SUNDAY remaining after the EPIPHANY II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-11-16) (weekday Mon) (title "St GERTRUDE V III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-11-17) (weekday Tue) + (title "St GREGORY THAUMATURGUS B C III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-11-18) (weekday Wed) + (title + "The DEDICATION of the BASILICAS of SS PETER & PAUL III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the Dedication of a Church or Common Pr")) + (has_diocesan_variant false)) + ((date 2026-11-19) (weekday Thu) (title "St ELIZABETH W III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-20) (weekday Fri) (title "St FELIX de VALOIS C III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-11-21) (weekday Sat) + (title "The PRESENTATION of the BVM III Cl W #") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of the BVM Et te in Pr\195\166sentatione")) + (has_diocesan_variant false)) + ((date 2026-11-22) (weekday Sun) + (title "24th & LAST SUNDAY After PENTECOST II Cl G") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant true)) + ((date 2026-11-23) (weekday Mon) + (title "St CLEMENT I \194\167 P M III Cl (Priv.) R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant true)) + ((date 2026-11-24) (weekday Tue) + (title "St JOHN of the CROSS C D III Cl (Priv.) W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-25) (weekday Wed) (title "St CATHERINE V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-26) (weekday Thu) (title "St SILVESTER Ab III Cl W #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-11-27) (weekday Fri) (title "FERIA IV Cl G \226\128\161") + (formulary_override ("Mass of 24th & Last Sunday After Pentecost")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-11-28) (weekday Sat) + (title "OUR LADY on SATURDAY IV Cl W \226\128\160") + (formulary_override ("V Mass of BVM")) (bvm_numeral (V)) (gloria (true)) + (creed (false)) (praef ("Pr of the BVM Et te in Veneratione")) + (has_diocesan_variant false)) + ((date 2026-11-29) (weekday Sun) (title "ADVENT SUNDAY I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-11-30) (weekday Mon) (title "St ANDREW \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-12-01) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-12-02) (weekday Wed) (title "St BIBIANA V M III Cl R #") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Pr of Martyrs or Common Pr")) (has_diocesan_variant false)) + ((date 2026-12-03) (weekday Thu) + (title "St FRANCIS XAVIER C III Cl (Priv.) W JCHP") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-12-04) (weekday Fri) + (title "St PETER CHRYSOLOGUS B C D III Cl W # SH") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant true)) + ((date 2026-12-05) (weekday Sat) (title "FERIA III Cl V IH JCHP*") + (formulary_override ("Mass of Advent Sunday")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-12-06) (weekday Sun) (title "2nd SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-12-07) (weekday Mon) + (title "St AMBROSE B C D III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-12-08) (weekday Tue) + (title "The IMMACULATE CONCEPTION of the BVM I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the BVM Et te in Conceptione Immaculata")) + (has_diocesan_variant false)) + ((date 2026-12-09) (weekday Wed) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-10) (weekday Thu) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-12-11) (weekday Fri) + (title "St DAMASUS I P C III Cl (Priv.) W") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant true)) + ((date 2026-12-12) (weekday Sat) (title "FERIA III Cl V") + (formulary_override ("Mass of 2nd Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-13) (weekday Sun) + (title "3rd SUNDAY of ADVENT (GAUDETE SUNDAY) I Cl V/Rose") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-12-14) (weekday Mon) (title "FERIA III Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-15) (weekday Tue) (title "FERIA III Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-16) (weekday Wed) + (title "EMBER WEDNESDAY of ADVENT II Cl V") (formulary_override ()) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-17) (weekday Thu) (title "FERIA II Cl V") + (formulary_override ("Mass of 3rd Sunday of Advent (Gaudete Sunday)")) + (bvm_numeral ()) (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-18) (weekday Fri) (title "EMBER FRIDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-12-19) (weekday Sat) (title "EMBER SATURDAY of ADVENT II Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-12-20) (weekday Sun) (title "4th SUNDAY of ADVENT I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true)) + (praef ("Pr of the Trinity")) (has_diocesan_variant false)) + ((date 2026-12-21) (weekday Mon) (title "St THOMAS \194\167 Ap II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Apostles")) (has_diocesan_variant false)) + ((date 2026-12-22) (weekday Tue) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-23) (weekday Wed) (title "FERIA II Cl V") + (formulary_override ("Mass of 4th Sunday of Advent")) (bvm_numeral ()) + (gloria (false)) (creed (false)) (praef ("Common Pr")) + (has_diocesan_variant false)) + ((date 2026-12-24) (weekday Thu) + (title "VIGIL of The NATIVITY of OUR LORD I Cl V") + (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false)) + (praef ("Common Pr")) (has_diocesan_variant false)) + ((date 2026-12-25) (weekday Fri) (title "The NATIVITY of OUR LORD I Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef + ("Pr of the Nativity Proper Communic at Midnight noctem sacratissimam at")) + (has_diocesan_variant false)) + ((date 2026-12-26) (weekday Sat) + (title "St STEPHEN \194\167 Protomartyr II Cl R") (formulary_override ()) + (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2026-12-27) (weekday Sun) + (title "SUNDAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2026-12-28) (weekday Mon) (title "The HOLY INNOCENTS MM II Cl R") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2026-12-29) (weekday Tue) + (title "5th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant true)) + ((date 2026-12-30) (weekday Wed) + (title "6th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false)) + ((date 2026-12-31) (weekday Thu) + (title "7th DAY within the OCTAVE of the NATIVITY II Cl W") + (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true)) + (praef ("Pr of the Nativity Proper Communic diem sacratissimum")) + (has_diocesan_variant false))) diff --git a/test/golden/grid-2027.html b/test/golden/grid-2027.html index daa6ba5..92a73ec 100644 --- a/test/golden/grid-2027.html +++ b/test/golden/grid-2027.html @@ -131,10 +131,10 @@ <td class="pad"></td><td class="pad"></td><td class="pad"></td><td class="pad"></td><td class="pad"></td><td class="pad"></td><td class="white"><span class="dom">1</span>St. Joseph the Workman<span class="sigla">Col 3:14-15, 17, 23-24 · Matt 13:54-58</span></td> </tr> <tr> - <td class="white"><span class="dom">2</span>5th Sunday after Easter<span class="sigla">Jas 1:22-27 · John 16:23-30</span></td><td class="violet"><span class="dom">3</span>Rogation Monday<span class="sigla">Jas 1:22-27 · John 16:23-30</span></td><td class="white"><span class="dom">4</span>St. Monica<span class="sigla">1 Tim 5:3-10 · Luke 7:11-16</span></td><td class="white"><span class="dom">5</span>Vigil of the Ascension<span class="sigla">Eph 4:7-13 · John 17:1-11</span></td><td class="white"><span class="dom">6</span>The Ascension of Our Lord<span class="sigla">Acts 1:1-11 · Mark 16:14-20</span></td><td class="red"><span class="dom">7</span>St. Stanislaus<span class="sigla">Wis 5:1-5 · John 15:1-7</span></td><td class="white"><span class="dom">8</span>Our Lady's Saturday Office<span class="sigla">Ecclus 24:14-16 · John 19:25-27</span></td> + <td class="white"><span class="dom">2</span>5th Sunday after Easter<span class="sigla">Jas 1:22-27 · John 16:23-30</span></td><td class="white"><span class="dom">3</span>Rogation Monday<span class="sigla">Jas 1:22-27 · John 16:23-30</span></td><td class="white"><span class="dom">4</span>St. Monica<span class="sigla">1 Tim 5:3-10 · Luke 7:11-16</span></td><td class="white"><span class="dom">5</span>Vigil of the Ascension<span class="sigla">Eph 4:7-13 · John 17:1-11</span></td><td class="white"><span class="dom">6</span>The Ascension of Our Lord<span class="sigla">Acts 1:1-11 · Mark 16:14-20</span></td><td class="red"><span class="dom">7</span>St. Stanislaus<span class="sigla">Wis 5:1-5 · John 15:1-7</span></td><td class="white"><span class="dom">8</span>Our Lady's Saturday Office<span class="sigla">Ecclus 24:14-16 · John 19:25-27</span></td> </tr> <tr> - <td class="white"><span class="dom">9</span>Sunday after the Ascension<span class="sigla">1 Pet 4:7-11 · John 15:26-27; 16:1-4</span></td><td class="white"><span class="dom">10</span>St. Antoninus<span class="sigla">Ecclus 44:16-27; 45:3-20 · Matt 25:14-23</span></td><td class="red"><span class="dom">11</span>Sts. Philip & James<span class="sigla">Wis 5:1-5 · John 14:1-13</span></td><td class="red"><span class="dom">12</span>Sts. Nereus, Achilleus, Domitilla, & Pancras<span class="sigla">Wis 5:1-5 · John 4:46-53</span></td><td class="white"><span class="dom">13</span>St. Robert Bellarmine<span class="sigla">Wis 7:7-14 · Matt 5:13-19</span></td><td class="white"><span class="dom">14</span>Friday of the 7th Week of Eastertide<span class="sigla">1 Pet 4:7-11 · John 15:26-27; 16:1-4</span></td><td class="red"><span class="dom">15</span>Vigil of Pentecost<span class="sigla">Acts 19:1-8 · John 14:15-21</span></td> + <td class="white"><span class="dom">9</span>Sunday after the Ascension<span class="sigla">1 Pet 4:7-11 · John 15:26-27; 16:1-4</span></td><td class="white"><span class="dom">10</span>St. Antoninus<span class="sigla">Ecclus 44:16-27; 45:3-20 · Matt 25:14-23</span></td><td class="red"><span class="dom">11</span>Sts. Philip & James<span class="sigla">Wis 5:1-5 · John 14:1-13</span></td><td class="red"><span class="dom">12</span>Sts. Nereus, Achilleus, Domitilla, & Pancras<span class="sigla">Wis 5:1-5 · John 4:46-53</span></td><td class="white"><span class="dom">13</span>St. Robert Bellarmine<span class="sigla">Wis 7:7-14 · Matt 5:13-19</span></td><td class="white"><span class="dom">14</span>Friday of the 7th Week of Eastertide<span class="sigla">Acts 1:1-11 · Mark 16:14-20</span></td><td class="red"><span class="dom">15</span>Vigil of Pentecost<span class="sigla">Acts 19:1-8 · John 14:15-21</span></td> </tr> <tr> <td class="red"><span class="dom">16</span>Pentecost Sunday (Whitsunday)<span class="sigla">Acts 2:1-11 · John 14:23-31</span></td><td class="red"><span class="dom">17</span>Monday of Pentecost Week<span class="sigla">Acts 10:34, 42-48 · John 3:16-21</span></td><td class="red"><span class="dom">18</span>Tuesday of Pentecost Week<span class="sigla">Acts 8:14-17 · John 10:1-10</span></td><td class="red"><span class="dom">19</span>Pentecost Ember Wednesday<span class="sigla">Acts 5:12-16 · John 6:44-52</span></td><td class="red"><span class="dom">20</span>Thursday of Pentecost Week<span class="sigla">Acts 8:5-8 · Luke 9:1-6</span></td><td class="red"><span class="dom">21</span>Pentecost Ember Friday<span class="sigla">Joel 2:23-24; 2:26-27 · Luke 5:17-26</span></td><td class="red"><span class="dom">22</span>Pentecost Ember Saturday<span class="sigla">Rom 5:1-5 · Luke 4:38-44</span></td> diff --git a/test/golden/grid-2027.ms b/test/golden/grid-2027.ms index 4f71416..3432d8f 100644 --- a/test/golden/grid-2027.ms +++ b/test/golden/grid-2027.ms @@ -767,7 +767,7 @@ T} T{ T} T{ \fB14\fP \s-2Friday of the 7th Week of Eastertide\s+2 .br -\s-21 Pet 4:7-11 \(bu John 15:26-27; 16:1-4\s+2 +\s-2Acts 1:1-11 \(bu Mark 16:14-20\s+2 T} T{ \fB15\fP \s-2Vigil of Pentecost\s+2 .br diff --git a/test/golden/grid-2027.tex b/test/golden/grid-2027.tex index 674b9c4..1585bda 100644 --- a/test/golden/grid-2027.tex +++ b/test/golden/grid-2027.tex @@ -151,8 +151,8 @@ \begin{tabular}{|*{7}{p{\cellw}|}}\hline \textbf{ Sunday } & \textbf{ Monday } & \textbf{ Tuesday } & \textbf{ Wednesday } & \textbf{ Thursday } & \textbf{ Friday } & \textbf{ Saturday } \\ \hline & & & & & & \cellcolor{cwhite}\daycell{ 1 }{ St. Joseph the Workman }{ 1st Class }{ Col 3:14-15, 17, 23-24\ \textperiodcentered\ Matt 13:54-58 } \\ \hline -\cellcolor{cwhite}\daycell{ 2 }{ 5th Sunday after Easter }{ 2nd Class }{ Jas 1:22-27\ \textperiodcentered\ John 16:23-30 } & \cellcolor{cviolet}\daycell{ 3 }{ Rogation Monday }{ 4th Class }{ Jas 1:22-27\ \textperiodcentered\ John 16:23-30 } & \cellcolor{cwhite}\daycell{ 4 }{ St. Monica }{ 3rd Class }{ 1 Tim 5:3-10\ \textperiodcentered\ Luke 7:11-16 } & \cellcolor{cwhite}\daycell{ 5 }{ Vigil of the Ascension }{ 2nd Class }{ Eph 4:7-13\ \textperiodcentered\ John 17:1-11 } & \cellcolor{cwhite}\daycell{ 6 }{ The Ascension of Our Lord }{ 1st Class }{ Acts 1:1-11\ \textperiodcentered\ Mark 16:14-20 } & \cellcolor{cred}\daycell{ 7 }{ St. Stanislaus }{ 3rd Class }{ Wis 5:1-5\ \textperiodcentered\ John 15:1-7 } & \cellcolor{cwhite}\daycell{ 8 }{ Our Lady's Saturday Office }{ 4th Class }{ Ecclus 24:14-16\ \textperiodcentered\ John 19:25-27 } \\ \hline -\cellcolor{cwhite}\daycell{ 9 }{ Sunday after the Ascension }{ 2nd Class }{ 1 Pet 4:7-11\ \textperiodcentered\ John 15:26-27; 16:1-4 } & \cellcolor{cwhite}\daycell{ 10 }{ St. Antoninus }{ 3rd Class }{ Ecclus 44:16-27; 45:3-20\ \textperiodcentered\ Matt 25:14-23 } & \cellcolor{cred}\daycell{ 11 }{ Sts. Philip \& James }{ 2nd Class }{ Wis 5:1-5\ \textperiodcentered\ John 14:1-13 } & \cellcolor{cred}\daycell{ 12 }{ Sts. Nereus, Achilleus, Domitilla, \& Pancras }{ 3rd Class }{ Wis 5:1-5\ \textperiodcentered\ John 4:46-53 } & \cellcolor{cwhite}\daycell{ 13 }{ St. Robert Bellarmine }{ 3rd Class }{ Wis 7:7-14\ \textperiodcentered\ Matt 5:13-19 } & \cellcolor{cwhite}\daycell{ 14 }{ Friday of the 7th Week of Eastertide }{ 4th Class }{ 1 Pet 4:7-11\ \textperiodcentered\ John 15:26-27; 16:1-4 } & \cellcolor{cred}\daycell{ 15 }{ Vigil of Pentecost }{ 1st Class }{ Acts 19:1-8\ \textperiodcentered\ John 14:15-21 } \\ \hline +\cellcolor{cwhite}\daycell{ 2 }{ 5th Sunday after Easter }{ 2nd Class }{ Jas 1:22-27\ \textperiodcentered\ John 16:23-30 } & \cellcolor{cwhite}\daycell{ 3 }{ Rogation Monday }{ 4th Class }{ Jas 1:22-27\ \textperiodcentered\ John 16:23-30 } & \cellcolor{cwhite}\daycell{ 4 }{ St. Monica }{ 3rd Class }{ 1 Tim 5:3-10\ \textperiodcentered\ Luke 7:11-16 } & \cellcolor{cwhite}\daycell{ 5 }{ Vigil of the Ascension }{ 2nd Class }{ Eph 4:7-13\ \textperiodcentered\ John 17:1-11 } & \cellcolor{cwhite}\daycell{ 6 }{ The Ascension of Our Lord }{ 1st Class }{ Acts 1:1-11\ \textperiodcentered\ Mark 16:14-20 } & \cellcolor{cred}\daycell{ 7 }{ St. Stanislaus }{ 3rd Class }{ Wis 5:1-5\ \textperiodcentered\ John 15:1-7 } & \cellcolor{cwhite}\daycell{ 8 }{ Our Lady's Saturday Office }{ 4th Class }{ Ecclus 24:14-16\ \textperiodcentered\ John 19:25-27 } \\ \hline +\cellcolor{cwhite}\daycell{ 9 }{ Sunday after the Ascension }{ 2nd Class }{ 1 Pet 4:7-11\ \textperiodcentered\ John 15:26-27; 16:1-4 } & \cellcolor{cwhite}\daycell{ 10 }{ St. Antoninus }{ 3rd Class }{ Ecclus 44:16-27; 45:3-20\ \textperiodcentered\ Matt 25:14-23 } & \cellcolor{cred}\daycell{ 11 }{ Sts. Philip \& James }{ 2nd Class }{ Wis 5:1-5\ \textperiodcentered\ John 14:1-13 } & \cellcolor{cred}\daycell{ 12 }{ Sts. Nereus, Achilleus, Domitilla, \& Pancras }{ 3rd Class }{ Wis 5:1-5\ \textperiodcentered\ John 4:46-53 } & \cellcolor{cwhite}\daycell{ 13 }{ St. Robert Bellarmine }{ 3rd Class }{ Wis 7:7-14\ \textperiodcentered\ Matt 5:13-19 } & \cellcolor{cwhite}\daycell{ 14 }{ Friday of the 7th Week of Eastertide }{ 4th Class }{ Acts 1:1-11\ \textperiodcentered\ Mark 16:14-20 } & \cellcolor{cred}\daycell{ 15 }{ Vigil of Pentecost }{ 1st Class }{ Acts 19:1-8\ \textperiodcentered\ John 14:15-21 } \\ \hline \cellcolor{cred}\daycell{ 16 }{ Pentecost Sunday (Whitsunday) }{ 1st Class }{ Acts 2:1-11\ \textperiodcentered\ John 14:23-31 } & \cellcolor{cred}\daycell{ 17 }{ Monday of Pentecost Week }{ 1st Class }{ Acts 10:34, 42-48\ \textperiodcentered\ John 3:16-21 } & \cellcolor{cred}\daycell{ 18 }{ Tuesday of Pentecost Week }{ 1st Class }{ Acts 8:14-17\ \textperiodcentered\ John 10:1-10 } & \cellcolor{cred}\daycell{ 19 }{ Pentecost Ember Wednesday }{ 1st Class }{ Acts 5:12-16\ \textperiodcentered\ John 6:44-52 } & \cellcolor{cred}\daycell{ 20 }{ Thursday of Pentecost Week }{ 1st Class }{ Acts 8:5-8\ \textperiodcentered\ Luke 9:1-6 } & \cellcolor{cred}\daycell{ 21 }{ Pentecost Ember Friday }{ 1st Class }{ Joel 2:23-24; 2:26-27\ \textperiodcentered\ Luke 5:17-26 } & \cellcolor{cred}\daycell{ 22 }{ Pentecost Ember Saturday }{ 1st Class }{ Rom 5:1-5\ \textperiodcentered\ Luke 4:38-44 } \\ \hline \cellcolor{cwhite}\daycell{ 23 }{ Trinity Sunday }{ 1st Class }{ Rom 11:33-36\ \textperiodcentered\ Matt 28:18-20 } & \cellcolor{cgreen}\daycell{ 24 }{ Monday of the 1st Week of the Time after Pentecost }{ 4th Class }{ 1 John 4:8-21\ \textperiodcentered\ Luke 6:36-42 } & \cellcolor{cwhite}\daycell{ 25 }{ St. Gregory VII }{ 3rd Class }{ 1 Pet 5:1-4; 5:10-11\ \textperiodcentered\ Matt 16:13-19 } & \cellcolor{cwhite}\daycell{ 26 }{ St. Philip Neri }{ 3rd Class }{ Wis 7:7-14\ \textperiodcentered\ Luke 12:35-40 } & \cellcolor{cwhite}\daycell{ 27 }{ Corpus Christi }{ 1st Class }{ 1 Cor 11:23-29\ \textperiodcentered\ John 6:56-59 } & \cellcolor{cwhite}\daycell{ 28 }{ St. Augustine of Canterbury }{ 3rd Class }{ 1 Thess 2:2-9\ \textperiodcentered\ Luke 10:1-9 } & \cellcolor{cwhite}\daycell{ 29 }{ St. Mary Magdalene de Pazzi }{ 3rd Class }{ 2 Cor 10:17-18; 11:1-2\ \textperiodcentered\ Matt 25:1-13 } \\ \hline \cellcolor{cgreen}\daycell{ 30 }{ 2nd Sunday after Pentecost }{ 2nd Class }{ 1 John 3:13-18\ \textperiodcentered\ Luke 14:16-24 } & \cellcolor{cwhite}\daycell{ 31 }{ Queenship of the Blessed Virgin Mary }{ 2nd Class }{ Ecclus 24:5; 14:7; 14:9-11; 24:30-31\ \textperiodcentered\ Luke 1:26-33 } & & & & & \\ \hline diff --git a/test/golden/grid-2027.typ b/test/golden/grid-2027.typ index 800edf9..cc4d440 100644 --- a/test/golden/grid-2027.typ +++ b/test/golden/grid-2027.typ @@ -2056,7 +2056,7 @@ - table.cell(fill: cgrid.at("violet"))[ + table.cell(fill: cgrid.at("white"))[ #block(height: cellh - 2 * cellinset, clip: true)[ #set par(leading: 0.3em) #text(weight: "bold")[3] #text(size: 6.5pt)[Rogation Monday] @@ -2207,7 +2207,7 @@ #text(weight: "bold")[14] #text(size: 6.5pt)[Friday of the 7th Week of Eastertide] #v(1fr) #text(size: 6pt)[4th Class] \ - #text(size: 6pt)[1 Pet 4:7\-11 #sym.dot.c John 15:26\-27; 16:1\-4] + #text(size: 6pt)[Acts 1:1\-11 #sym.dot.c Mark 16:14\-20] ] ], diff --git a/test/golden/ordo-2027.adoc b/test/golden/ordo-2027.adoc index 39e5ae4..93a233d 100644 --- a/test/golden/ordo-2027.adoc +++ b/test/golden/ordo-2027.adoc @@ -879,7 +879,7 @@ Epistle Jas 1:22-27 Gospel John 16:23-30 *3* Rogation Monday + -class-4 · violet + +class-4 · white + Epistle Jas 1:22-27 Gospel John 16:23-30 + Commemoration Sts. Alexander & Companions @@ -952,7 +952,7 @@ Epistle Wis 7:7-14 Gospel Matt 5:13-19 *14* Friday of the 7th Week of Eastertide + class-4 · white + -Epistle 1 Pet 4:7-11 Gospel John 15:26-27; 16:1-4 +Epistle Acts 1:1-11 Gospel Mark 16:14-20 + Commemoration St. Boniface diff --git a/test/golden/ordo-2027.html b/test/golden/ordo-2027.html index 8513909..2a3f5e1 100644 --- a/test/golden/ordo-2027.html +++ b/test/golden/ordo-2027.html @@ -672,9 +672,9 @@ <div class="meta">class-2 · white · Epistle Jas 1:22-27 · Gospel John 16:23-30</div> </div> -<div class="day violet"> +<div class="day white"> <span class="dom">3</span>Rogation Monday - <div class="meta">class-4 · violet · Epistle Jas 1:22-27 · Gospel John 16:23-30</div> + <div class="meta">class-4 · white · Epistle Jas 1:22-27 · Gospel John 16:23-30</div> <div class="meta">Commemoration Sts. Alexander & Companions</div> </div> <div class="day white"> @@ -730,7 +730,7 @@ </div> <div class="day white"> <span class="dom">14</span>Friday of the 7th Week of Eastertide - <div class="meta">class-4 · white · Epistle 1 Pet 4:7-11 · Gospel John 15:26-27; 16:1-4</div> + <div class="meta">class-4 · white · Epistle Acts 1:1-11 · Gospel Mark 16:14-20</div> <div class="meta">Commemoration St. Boniface</div> </div> <div class="day red"> diff --git a/test/golden/ordo-2027.md b/test/golden/ordo-2027.md index 3d96240..c90b65e 100644 --- a/test/golden/ordo-2027.md +++ b/test/golden/ordo-2027.md @@ -789,7 +789,7 @@ **3** Rogation Monday -`class-4` · violet · Epistle Jas 1:22-27 · Gospel John 16:23-30 +`class-4` · white · Epistle Jas 1:22-27 · Gospel John 16:23-30 - Commemoration Sts. Alexander & Companions @@ -853,7 +853,7 @@ **14** Friday of the 7th Week of Eastertide -`class-4` · white · Epistle 1 Pet 4:7-11 · Gospel John 15:26-27; 16:1-4 +`class-4` · white · Epistle Acts 1:1-11 · Gospel Mark 16:14-20 - Commemoration St. Boniface diff --git a/test/golden/ordo-2027.ms b/test/golden/ordo-2027.ms index e029a76..c9e6f5e 100644 --- a/test/golden/ordo-2027.ms +++ b/test/golden/ordo-2027.ms @@ -1354,7 +1354,7 @@ May .IP "3" 4 \fBRogation Monday\fR .br -\s74th Class \(bu Violet\s9 +\s74th Class \(bu White\s9 .br \s7Epistle Jas 1:22-27\s9 .br @@ -1464,9 +1464,9 @@ May .br \s74th Class \(bu White\s9 .br -\s7Epistle 1 Pet 4:7-11\s9 +\s7Epistle Acts 1:1-11\s9 .br -\s7Gospel John 15:26-27; 16:1-4\s9 +\s7Gospel Mark 16:14-20\s9 .br \s7Commemoration St. Boniface\s9 .sp 0.25v diff --git a/test/golden/ordo-2027.tex b/test/golden/ordo-2027.tex index 0db4121..0debd17 100644 --- a/test/golden/ordo-2027.tex +++ b/test/golden/ordo-2027.tex @@ -1548,9 +1548,9 @@ \begin{tcolorbox}[colback=white,colframe=black!35,boxrule=0.3pt,sharp corners,boxsep=0mm,left=1.6mm,right=1.6mm,top=0.4mm,bottom=0.4mm,before skip=0.3mm,after skip=0mm] -\fontsize{9}{9}\selectfont\bfseries 3 \fontsize{7}{9}\selectfont\mdseries\;Monday\hfill\swatch{licolviolet}\\ +\fontsize{9}{9}\selectfont\bfseries 3 \fontsize{7}{9}\selectfont\mdseries\;Monday\hfill\swatch{licolwhite}\\ \fontsize{9}{9.7}\selectfont\bfseries Rogation Monday\\ -\fontsize{6.5}{7.4}\selectfont\mdseries 4th Class \textperiodcentered\ Violet \quad Epistle\ Jas 1:22-27 \quad Gospel\ John 16:23-30 \\ +\fontsize{6.5}{7.4}\selectfont\mdseries 4th Class \textperiodcentered\ White \quad Epistle\ Jas 1:22-27 \quad Gospel\ John 16:23-30 \\ \fontsize{6.5}{7.4}\selectfont\mdseries Commemoration\ Sts. Alexander \& Companions \end{tcolorbox} @@ -1648,7 +1648,7 @@ \begin{tcolorbox}[colback=white,colframe=black!35,boxrule=0.3pt,sharp corners,boxsep=0mm,left=1.6mm,right=1.6mm,top=0.4mm,bottom=0.4mm,before skip=0.3mm,after skip=0mm] \fontsize{9}{9}\selectfont\bfseries 14 \fontsize{7}{9}\selectfont\mdseries\;Friday\hfill\swatch{licolwhite}\\ \fontsize{9}{9.7}\selectfont\bfseries Friday of the 7th Week of Eastertide\\ -\fontsize{6.5}{7.4}\selectfont\mdseries 4th Class \textperiodcentered\ White \quad Epistle\ 1 Pet 4:7-11 \quad Gospel\ John 15:26-27; 16:1-4 \\ +\fontsize{6.5}{7.4}\selectfont\mdseries 4th Class \textperiodcentered\ White \quad Epistle\ Acts 1:1-11 \quad Gospel\ Mark 16:14-20 \\ \fontsize{6.5}{7.4}\selectfont\mdseries Commemoration\ St. Boniface \end{tcolorbox} diff --git a/test/golden/ordo-2027.txt b/test/golden/ordo-2027.txt index 0af67b3..b2c68a3 100644 --- a/test/golden/ordo-2027.txt +++ b/test/golden/ordo-2027.txt @@ -728,7 +728,7 @@ May 2027 Gospel John 16:23-30 3 Rogation Monday - class-4 · violet + class-4 · white Epistle Jas 1:22-27 Gospel John 16:23-30 Commemoration Sts. Alexander & Companions @@ -790,8 +790,8 @@ May 2027 14 Friday of the 7th Week of Eastertide class-4 · white - Epistle 1 Pet 4:7-11 - Gospel John 15:26-27; 16:1-4 + Epistle Acts 1:1-11 + Gospel Mark 16:14-20 Commemoration St. Boniface 15 Vigil of Pentecost diff --git a/test/golden/ordo-2027.typ b/test/golden/ordo-2027.typ index 0d87f04..23afb88 100644 --- a/test/golden/ordo-2027.typ +++ b/test/golden/ordo-2027.typ @@ -1480,9 +1480,9 @@ #block(width: 100%, above: 0.4mm, below: 0mm, breakable: false, stroke: 0.4pt + luma(160), inset: (x: 1.6mm, y: 0.4mm))[ #set par(leading: 0.36em) - #text(weight: "bold")[3] #h(2mm) #text(size: 7pt)[Monday] #h(1fr) #swatch("violet") \ + #text(weight: "bold")[3] #h(2mm) #text(size: 7pt)[Monday] #h(1fr) #swatch("white") \ #text(weight: "bold")[Rogation Monday] \ - #text(size: 6.5pt)[4th Class #sym.dot.c Violet #h(2mm) Epistle Jas 1:22\-27 #h(2mm) Gospel John 16:23\-30] \ + #text(size: 6.5pt)[4th Class #sym.dot.c White #h(2mm) Epistle Jas 1:22\-27 #h(2mm) Gospel John 16:23\-30] \ #text(size: 6.5pt)[Commemoration Sts. Alexander & Companions] ] @@ -1589,7 +1589,7 @@ #set par(leading: 0.36em) #text(weight: "bold")[14] #h(2mm) #text(size: 7pt)[Friday] #h(1fr) #swatch("white") \ #text(weight: "bold")[Friday of the 7th Week of Eastertide] \ - #text(size: 6.5pt)[4th Class #sym.dot.c White #h(2mm) Epistle 1 Pet 4:7\-11 #h(2mm) Gospel John 15:26\-27; 16:1\-4] \ + #text(size: 6.5pt)[4th Class #sym.dot.c White #h(2mm) Epistle Acts 1:1\-11 #h(2mm) Gospel Mark 16:14\-20] \ #text(size: 6.5pt)[Commemoration St. Boniface] ] diff --git a/test/test_calendar.ml b/test/test_calendar.ml index 132a466..9059574 100644 --- a/test/test_calendar.ml +++ b/test/test_calendar.ml @@ -99,9 +99,18 @@ module Fixture = struct let rec search d = if (occupant d).Cel.rank = Lo then d else search (D.add_days d 1) in search (D.add_days origin 1) - (* No fixture here exercises citations -- readings is a harmless constant - [], the same role [empty_layer] plays for the sanctoral side. *) - let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = [] + (* No fixture here exercises citations or the formulary -- readings is a + harmless constant [(None, [])], the same role [empty_layer] plays for + the sanctoral side. *) + let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = (None, []) + + (* No fixture here exercises the Creed, Gloria or preface rubrics either + -- a rite that has not implemented them returns [false]/[None] + explicitly, {!Rite.t.creed}/{!Rite.t.gloria}/{!Rite.t.preface}'s own + documented default. *) + let creed ~temporal:_ ~observed:_ ~date:_ = false + let gloria ~temporal:_ ~observed:_ ~date:_ = false + let preface ~temporal:_ ~observed:_ ~date:_ = None let rite : (season, rank) Rite.t = { Rite.id = "synthetic-calendar"; vocab; year_start; temporal; anchors = (fun _ -> []); @@ -110,7 +119,10 @@ module Fixture = struct any for a fixture; nothing here is Easter-relative, so the value is never actually read. *) easter = Colitur_kernel.Computus.gregorian_easter; - rules; season_runs = [ A; B ]; transfer_target; readings } + (* Not a Roman rite either, so no bissextile-doubling convention: + identity, {!Rite.t.fixed_key}'s own documented default. *) + fixed_key = (fun d -> Some (D.month d, D.day d)); + rules; season_runs = [ A; B ]; transfer_target; readings; creed; gloria; preface } let entry ~month ~day ~slug ~rank = { Layer.date = (match Date_spec.fixed ~month ~day with Ok d -> d | Error e -> failwith e); diff --git a/test/test_colitur.ml b/test/test_colitur.ml index c873945..9eefecd 100644 --- a/test/test_colitur.ml +++ b/test/test_colitur.ml @@ -1,7 +1,8 @@ (* Aggregating test runner. Per-module suites live in test_<module>.ml. *) let () = Alcotest.run "colitur" - [ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_names.suite; + [ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_mass_formulary.suite; + Test_names.suite; Test_lang.suite; Test_lang_coverage.suite; Test_citation_coverage.suite; @@ -12,7 +13,13 @@ let () = Test_config.suite; Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite; Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite; - Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; Test_golden.suite; + Test_rubrics_ef.suite; + Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; + Test_lms_ordo.suite_2023_2024; Test_lms_ordo.suite_2024_2025; Test_lms_ordo.suite_2025_2026; + Test_lms_ordo.suite_allow_list; Test_fiuv_ordo.suite; + Test_efdotorg_ordo.suite_2024_2025; Test_efdotorg_ordo.suite_2025_2026; Test_efdotorg_ordo.suite_2026_2027; + Test_efdotorg_ordo.suite_allow_list; + Test_golden.suite; ("lectionary", Test_lectionary.suite); ("lectionary-ef", Test_lectionary_ef.suite); Test_escape.suite; diff --git a/test/test_differential.ml b/test/test_differential.ml index 8c1dd8d..222328b 100644 --- a/test/test_differential.ml +++ b/test/test_differential.ml @@ -550,6 +550,17 @@ let jan_6_13_slug slug = let nativity_octave_day_slugs = [ "ef-nativity-octave-day-5"; "ef-nativity-octave-day-6"; "ef-nativity-octave-day-7" ] +(* C41 (celebrant-rubrics-phase1, Bug 2, 2026-08-22): the six ferias + between the Ascension and the Friday before the Vigil of Pentecost that + repeat the Ascension's own Mass (data/ef/lectionary.sexp's own + [ascension_week_entries], bootstrap_lectionary.ml). The window's two + Saturdays are excluded here too, for the identical reason they carry no + lectionary entry: RG 78's votive Office of Our Lady wins first. *) +let ascension_week_slugs = + [ "ef-easter-6-friday"; "ef-easter-7-monday"; "ef-easter-7-tuesday"; "ef-easter-7-wednesday"; + "ef-easter-7-thursday"; "ef-easter-7-friday" + ] + (* C18 (ef-sanctoral-audit, 2026-08-14): the closed set of colitur [status = Feast] sanctoral slugs whose bootstrapped [colour] was corrected against RG 124 (data/ef/adjustments.sexp's own audit-block @@ -1096,6 +1107,36 @@ let rg33_vigil_slugs = [ "vigil-of-st-lawrence"; "vigil-of-the-nativity-of-st-john-the-baptist"; "vigil-of-sts-peter-paul" ] +(* C40 -- the calendarium's own bissextile (leap-year) footnote (February, + docs/research/LT.txt:5011-5014; see rite_ef/temporal_ef.ml's + [bissextile_fixed_key] for the full citation and mechanism), implemented + 2026-08-22. lectio builds no such shift at all (confirmed directly + against the fixture: Matthias sits at 24 February and Gabriel of Our Lady + of Sorrows at 27 February in EVERY leap year the 2005-2050 fixture + covers, 11 of them), so every leap year now diverges on the two shifted + civil days: colitur vacates 24/27 February (Matthias/Gabriel move away) + and occupies 25/28 February instead, while lectio keeps the pre-shift + assignment on both. + + Four shapes, one mechanism -- OLD position vacated (colitur no longer + matches lectio's still-there Matthias/Gabriel) and NEW position occupied + (colitur now shows a saint lectio's own unmoved date does not) -- each + checked by NAME on both sides, the same identity discipline C39 and + C6/C14 already apply, not merely a diff-set shape: a coincidental + same-shape diff on an unrelated 24/25/27/28 February slug would not match + any of the four literal-slug conjuncts below. *) +let is_bissextile_shift_row (l : row) (c : row) ~month ~day = + month = 2 + && Date.is_leap (year_of_date c.date) + && ((day = 24 && String.equal l.slug "matthias" && not (String.equal c.slug "matthias")) + || (day = 25 && String.equal c.slug "matthias" && not (String.equal l.slug "matthias")) + || (day = 27 + && String.equal l.slug "gabriel-of-our-lady-of-sorrows" + && not (String.equal c.slug "gabriel-of-our-lady-of-sorrows")) + || (day = 28 + && String.equal c.slug "gabriel-of-our-lady-of-sorrows" + && not (String.equal l.slug "gabriel-of-our-lady-of-sorrows"))) + let layer_c_reason (l : row) (c : row) diffs = let m = month_of_date l.date and d = day_of_date l.date in if diffs = [] then None @@ -1158,6 +1199,15 @@ let layer_c_reason (l : row) (c : row) diffs = && (not (List.mem c.slug rg33_vigil_slugs)) && subset diffs [ Slug_f; Rank; Colour_f; First_f; Gospel_f ] then Some "C39" + else if is_bissextile_shift_row l c ~month:m ~day:d && subset diffs [ Slug_f; Rank; Colour_f; First_f; Gospel_f ] + then Some "C40" + (* C41 -- the Ascension-repeat rubric (see [ascension_week_slugs]'s own + citation above). SAME slug both sides ([Slug_f] never diffs here: the + six slugs already exist in lectio's own EF walkback, only their + resolved TEXT differs), rank/season/colour agree (both an ordinary + Class4 Paschaltide feria), and only the citation itself changes. *) + else if List.mem c.slug ascension_week_slugs && subset diffs [ First_f; Gospel_f ] + then Some "C41" (* C25 -- CLOSED, BVM Saturday Mass (2026-08-17), predicate removed: 0 rows. Its days are unoccupied IV-class Saturdays, so they carry RG 78's office and now RG 309(a)'s Mass for it, which answers before step 3's walkback diff --git a/test/test_efdotorg_ordo.ml b/test/test_efdotorg_ordo.ml new file mode 100644 index 0000000..6200cd9 --- /dev/null +++ b/test/test_efdotorg_ordo.ml @@ -0,0 +1,403 @@ +(* efdotorg-preface task (2026-08-24-colitur-celebrant-rubrics-phase1): the + THIRD independent preface witness, extraordinaryform.org's own three + annual Ordo editions (2024-2025, 2025-2026, 2026-2027). A prior task + (2026-08-21-colitur-celebrant-rubrics-phase1, see + .superpowers/sdd/2026-08-21-colitur-celebrant-rubrics-phase1/preface- + witnesses-report.md) DECLINED to wire this source in, for two reasons: + an unexplained "Advent" label in the preface column, and this corpus's + own known Vigil-of-St-Lawrence gap. Both are now characterisation work, + not blockers -- see tools/extract_efdotorg_ordo.py's own header for the + full account this file's own comparator relies on. + + WHY THIS LAYER IS DIFFERENT FROM test_fiuv_ordo.ml/test_lms_ordo.ml: + this source prints ONE preface value per day (unlike the LMS Ordo's own + option lists), already reduced to the day's own real OFFICE by the + menu-trap filter baked into the generator (see that script's own + header, finding 1) -- so the comparison here is a single equality + check per day, not a membership check. It is also the only one of the + three witnesses whose own JSON, not a fresh pdftotext dump, is the + input -- the JSON is already fidelity-audited + (.superpowers/ordo-fidelity-report.md, 1091/1091 against an + independently-written parser) and is treated as the source; this file + does not re-parse the PDFs. + + SCOPE: preface only (RG 482-499, {!Rite_ef.Rubrics_ef.preface}) -- this + source carries no Creed/Gloria/Te Deum data at all + (docs/research/ordo/PROVENANCE-ordo-corpus.md: "The extraordinaryform.org + editions carry NO Gloria or Creed"), so there is nothing else to + compare it against. *) + +module Cal = Colitur_kernel.Calendar +module Layer = Colitur_kernel.Layer +module Overlay = Colitur_kernel.Overlay +module LD = Colitur_kernel.Liturgical_day +module Date = Colitur_kernel.Date +module V = Rite_ef.Vocab_ef +module Preface = Colitur_kernel.Preface + +let sanctoral_path = "../data/ef/sanctoral.sexp" +let adjustments_path = "../data/ef/adjustments.sexp" + +(* Duplicated, not shared -- test_fiuv_ordo.ml/test_lms_ordo.ml's own + identical function carries the same "no shared .mli" reasoning. *) +let sha256_of_file path = + let tmp = Filename.temp_file "colitur_efdotorg_ordo_sha256" ".txt" in + Fun.protect + ~finally:(fun () -> try Sys.remove tmp with Sys_error _ -> ()) + (fun () -> + let cmd = Printf.sprintf "sha256sum %s > %s" (Filename.quote path) (Filename.quote tmp) in + let rc = Sys.command cmd in + if rc <> 0 then Alcotest.failf "sha256sum exited %d for %s (is it on PATH?)" rc path; + let ic = open_in tmp in + let line = + try input_line ic + with End_of_file -> + close_in ic; + Alcotest.failf "sha256sum produced no output for %s" path + in + close_in ic; + match String.index_opt line ' ' with + | Some i -> String.sub line 0 i + | None -> Alcotest.failf "unexpected sha256sum output for %s: %S" path line) + +let real_layer () = + let layer = + match Layer.load V.rank_of_sexp sanctoral_path with + | Ok l -> l + | Error e -> Alcotest.failf "%s: failed to load: %s" sanctoral_path e + in + let overlay = + match Overlay.load V.rank_of_sexp adjustments_path with + | Ok o -> o + | Error e -> Alcotest.failf "%s: failed to load: %s" adjustments_path e + in + let layer, diagnostics = Overlay.apply layer overlay in + Alcotest.(check (list string)) "the committed overlay applies cleanly, no diagnostics" [] + (List.map Overlay.diagnostic_to_string diagnostics); + layer + +let real_lectionary () = + match Colitur_kernel.Lectionary.load "../data/ef/lectionary.sexp" with + | Ok l -> l + | Error e -> Alcotest.failf "../data/ef/lectionary.sexp: failed to load: %s" e + +let real_commons () = + match Rite_ef.Lectionary_ef.Commons.load "../data/ef/commons.sexp" with + | Ok c -> c + | Error e -> Alcotest.failf "../data/ef/commons.sexp: failed to load: %s" e + +(* ---------------------------------------------------------------------- *) +(* The Ordo side: the sexp row, mirrored from tools/extract_efdotorg_ordo.py's *) +(* own row shape. *) +(* ---------------------------------------------------------------------- *) + +open Sexplib0.Sexp_conv + +type ordo_row = { date : string; mass : string option; cls : int option; colour : string option; praef : string option } +[@@deriving sexp] + +let ordo_rows fixture_path = + let sexp = + try Sexplib.Sexp.load_sexp fixture_path + with e -> Alcotest.failf "%s: failed to load: %s" fixture_path (Printexc.to_string e) + in + list_of_sexp ordo_row_of_sexp sexp + +(* ---------------------------------------------------------------------- *) +(* The colitur side, over the same window -- mirrors test_fiuv_ordo.ml's *) +(* own [colitur_rows]. *) +(* ---------------------------------------------------------------------- *) + +type colitur_row = { c_date : string; c_weekday : Date.weekday; c_preface : Preface.t option } + +let colitur_rows ~year_lo ~year_hi ~window_first ~window_last = + let layer = real_layer () in + let rite = Rite_ef.context ~lectionary:(real_lectionary ()) ~commons:(real_commons ()) in + let by_rata : (int, (V.season, V.rank) LD.t) Hashtbl.t = Hashtbl.create 800 in + for y = year_lo to year_hi do + let days = Cal.year rite layer y in + Array.iter (fun (d : (V.season, V.rank) LD.t) -> Hashtbl.replace by_rata (Date.to_rata d.LD.date) d) days + done; + let mk s = match Date.of_iso8601 s with Ok d -> d | Error e -> Alcotest.failf "%s: %s" s e in + let rows = ref [] in + let d = ref (mk window_first) in + let stop = mk window_last in + while Date.compare !d stop <= 0 do + (match Hashtbl.find_opt by_rata (Date.to_rata !d) with + | Some day -> + rows := + { c_date = Date.to_iso8601 day.LD.date; c_weekday = Date.weekday day.LD.date; c_preface = day.LD.preface } + :: !rows + | None -> Alcotest.failf "no colitur day resolved for %s" (Date.to_iso8601 !d)); + d := Date.add_days !d 1 + done; + List.rev !rows + +(* ---------------------------------------------------------------------- *) +(* Classification -- see tools/extract_efdotorg_ordo.py's own header, *) +(* finding 3, for why "Advent" needs the day's own weekday rather than a *) +(* static table entry: RG 494(b) grants the TRINITY preface on every *) +(* Advent SUNDAY, RG 498 the residual COMMON on every Advent FERIA, and *) +(* this source's own "Advent" label does not distinguish the two. Every *) +(* other raw value maps 1:1 onto exactly one {!Preface.t} constructor -- *) +(* verified exhaustive over the whole 1091-day office-selected population *) +(* while building this comparison (16 distinct raw values: these 14 fixed *) +(* mappings, "Advent" itself, and [None]) -- unlike the FIUV/LMS sources, *) +(* nothing here is genuinely unclassifiable. *) +(* ---------------------------------------------------------------------- *) + +let classify_praef ~(weekday : Date.weekday) (raw : string) : Preface.t option = + match raw with + | "Common" -> Some Preface.Common + | "For the Dead" -> Some Preface.Requiem + | "Easter" -> Some Preface.Easter + | "Lent" -> Some Preface.Lent + | "BVM" -> Some Preface.Bvm + | "Holy Trinity" -> Some Preface.Trinity + | "Holy Cross" -> Some Preface.Holy_cross + | "Nativity" -> Some Preface.Nativity + | "Apostles" -> Some Preface.Apostles + | "Ascension" -> Some Preface.Ascension + | "Holy Spirit" -> Some Preface.Holy_spirit + | "Epiphany" -> Some Preface.Epiphany + | "St. Joseph" -> Some Preface.St_joseph + | "Sacred Heart" -> Some Preface.Sacred_heart + | "Christ the King" -> Some Preface.Christ_the_king + | "Advent" -> Some (if weekday = Date.Sun then Preface.Trinity else Preface.Common) + | _ -> None + +(* ---------------------------------------------------------------------- *) +(* data/ef/expected-divergences-efdotorg.sexp -- same shape as the other *) +(* Ordo allow-lists' own [allow_entry]. A SEPARATE file: this Ordo is a *) +(* FIFTH lineage (lectio/missalemeum, LMS, FIUV, and now this one), a *) +(* different publisher and a different compiler from all three others. *) +(* ---------------------------------------------------------------------- *) + +type allow_entry = { id : string; citation : string; verdict : string; note : string; expected_rows : int } +[@@deriving sexp] + +let load_allow_list allow_list_path = + let sexps = + try Sexplib.Sexp.load_sexps allow_list_path + with e -> Alcotest.failf "%s: failed to load: %s" allow_list_path (Printexc.to_string e) + in + List.map allow_entry_of_sexp sexps + +let allow_list_path = "../data/ef/expected-divergences-efdotorg.sexp" + +(* ---------------------------------------------------------------------- *) +(* [make_suite]: one edition's worth of tests, parameterised -- mirrors *) +(* test_lms_ordo.ml's own shape. *) +(* ---------------------------------------------------------------------- *) + +let make_suite ~label ~fixture_path ~fixture_sha256 ~window_first ~window_last ~year_lo ~year_hi ~expected_rows + ~expected_no_data ~allow_list_id_for_date = + let test_fixture_checksum () = + Alcotest.(check string) "fixture SHA-256 matches its provenance note" fixture_sha256 + (sha256_of_file fixture_path) + in + let test_dates_align () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + Alcotest.(check int) (Printf.sprintf "the Ordo fixture has %d rows (%s..%s)" expected_rows window_first window_last) + expected_rows (List.length ordo); + Alcotest.(check int) "colitur resolved the same number of days" (List.length ordo) (List.length colitur); + (match ordo with o :: _ -> Alcotest.(check string) "first date" window_first o.date | [] -> Alcotest.fail "empty"); + (match List.rev ordo with + | o :: _ -> Alcotest.(check string) "last date" window_last o.date + | [] -> Alcotest.fail "empty"); + let mismatched = + List.filter_map + (fun (o, c) -> if String.equal o.date c.c_date then None else Some (o.date, c.c_date)) + (List.combine ordo colitur) + in + Alcotest.(check (list (pair string string))) "no misaligned dates" [] mismatched + in + (* This window's own Good Friday(s), RE-DERIVED from + {!Colitur_kernel.Computus.gregorian_easter} for every civil year the + window touches (never hardcoded), plus this edition's own share of + the single known SOURCE GAP (2027-03-03) -- the only two shapes a row + can have no [praef] at all for (see tools/extract_efdotorg_ordo.py's + own header, findings 2 and 5). *) + let window_no_praef () = + let first_year = int_of_string (String.sub window_first 0 4) in + let last_year = int_of_string (String.sub window_last 0 4) in + let good_fridays = + List.map + (fun y -> Date.to_iso8601 (Date.add_days (Colitur_kernel.Computus.gregorian_easter y) (-2))) + (List.init (last_year - first_year + 1) (fun i -> first_year + i)) + in + let candidates = good_fridays @ [ "2027-03-03" ] in + List.filter (fun d -> String.compare d window_first >= 0 && String.compare d window_last <= 0) candidates + |> List.sort_uniq String.compare + in + let test_praef_coverage () = + let ordo = ordo_rows fixture_path in + let no_praef = List.filter (fun o -> o.praef = None) ordo in + let expected = window_no_praef () in + Alcotest.(check int) "the no-praef population matches this window's own Good-Friday-plus-source-gap count" + expected_no_data (List.length no_praef); + Alcotest.(check (list string)) "every no-praef row is either this window's own Good Friday or the known source gap" + expected (List.map (fun o -> o.date) no_praef) + in + let describe_praef_mismatch (o : ordo_row) (c : colitur_row) (expected : Preface.t) = + Printf.sprintf "%s %S: colitur preface=%s, %s praef=%S (classified %s, weekday %s)" o.date + (Option.value o.mass ~default:"?") + (match c.c_preface with Some p -> Preface.to_string p | None -> "NONE") + label (Option.get o.praef) (Preface.to_string expected) (Date.weekday_to_string c.c_weekday) + in + let test_praef_matches_or_is_explained () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let allow_list = load_allow_list allow_list_path in + let by_id = List.map (fun e -> (e.id, e)) allow_list in + let unexplained = ref [] in + let unclassifiable = ref [] in + let explained_counts = Hashtbl.create 8 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.praef with + | None -> () + | Some raw -> ( + match classify_praef ~weekday:c.c_weekday raw with + | None -> unclassifiable := o.date :: !unclassifiable + | Some expected -> + if c.c_preface = Some expected then () + else + match allow_list_id_for_date o.date with + | Some id -> + Hashtbl.replace explained_counts id (1 + try Hashtbl.find explained_counts id with Not_found -> 0) + | None -> unexplained := describe_praef_mismatch o c expected :: !unexplained)) + ordo colitur; + Alcotest.(check (list string)) + (Printf.sprintf "[%s] every preface mismatch is named in the allow-list -- none unexplained" label) + [] (List.rev !unexplained); + Alcotest.(check (list string)) + (Printf.sprintf "[%s] every raw praef value classifies -- none dropped" label) + [] (List.rev !unclassifiable); + Hashtbl.iter + (fun id n -> + match List.assoc_opt id by_id with + | None -> Alcotest.failf "allow-list entry %s used by the comparator but not declared in %s" id allow_list_path + | Some e -> Alcotest.(check int) (Printf.sprintf "%s: expected_rows matches the actual count" id) e.expected_rows n) + explained_counts + in + (* The known Vigil-of-St-Lawrence corpus gap (tools/extract_efdotorg_ordo.py's + own header, finding 4; docs/research/ordo/PROVENANCE-ordo-corpus.md; + .superpowers/ordo-class-report.md) is RECONFIRMED present, but its + effect on THIS axis now differs by year -- checked per date, not + assumed uniform, because colitur's own CURRENT behaviour (RG 33's + third trigger, which landed after the reports above were written -- + CLAUDE.md's own warning that `day`/`readings` output is not stable + across commits is exactly this) already omits the vigil in SOME of + these years for its own, entirely independent reason: + - 2025-08-09 (Saturday): colitur's own RG33-third-trigger ALSO + omits the vigil this year (RG 78's BVM Saturday Office wins + outright), and Rule A (this generator's own finding 6) picks the + SAME office from the corpus's own listing -- a full, direct + match (office identity AND preface), not a lucky coincidence + limited to preface alone. + - 2027-08-09 (Monday): colitur's own vigil IS genuinely observed + this year (RG33's trigger does not fire); the corpus still shows + no trace of it at all -- STILL the known gap, reconfirmed, naming + St Romanus instead -- but both the true Vigil (Class3, no + title-preface trigger) and the corpus's own substitute fall + through RG 482's chain to the identical Common preface, so the + identity error stays invisible to this one axis. Asserted + POSITIVELY (not merely "no failure occurred") so a future change + giving either office a real trigger would surface here. + - 2026-08-09 (Sunday): the vigil is impeded on every source (a + Sunday outranks a Class3 vigil outright); no special case is + needed and none is asserted here. *) + let test_known_vigil_of_st_lawrence_shape () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let by_date = List.combine ordo colitur in + let find d = List.find_opt (fun ((o : ordo_row), _) -> String.equal o.date d) by_date in + let in_window d = String.compare d window_first >= 0 && String.compare d window_last <= 0 in + (match find "2025-08-09" with + | Some (o, c) when in_window "2025-08-09" -> + Alcotest.(check (option string)) "2025-08-09: Rule A selects the BVM Saturday Office directly" (Some "BVM") + o.praef; + Alcotest.(check (option string)) + "2025-08-09: colitur's own answer is the same office (RG33 3rd trigger + RG78)" (Some "bvm") + (Option.map Preface.to_string c.c_preface) + | _ -> ()); + match find "2027-08-09" with + | Some (o, c) when in_window "2027-08-09" -> + Alcotest.(check (option string)) + "2027-08-09: the known gap is reconfirmed -- the corpus still shows no Vigil of St Lawrence" + (Some "Common") o.praef; + Alcotest.(check (option string)) + "2027-08-09: colitur's own real Vigil office also reads Common -- the identity error stays invisible here" + (Some "common") (Option.map Preface.to_string c.c_preface) + | _ -> () + in + ( label, + [ Alcotest.test_case "fixture SHA-256 matches its provenance note" `Quick test_fixture_checksum; + Alcotest.test_case "streams are N rows each, dates aligned 1:1" `Quick test_dates_align; + Alcotest.test_case "no-praef population matches Good Friday plus the known source gap" `Quick + test_praef_coverage; + Alcotest.test_case "every preface mismatch is named in the allow-list -- none unexplained" `Quick + test_praef_matches_or_is_explained; + Alcotest.test_case "the known Vigil-of-St-Lawrence gap: reconfirmed in 2027, resolved by Rule A in 2025" `Quick + test_known_vigil_of_st_lawrence_shape + ] ) + +(* The seven adjudicated root causes behind this comparison's own 11 row- + level divergences (three editions combined) -- see + data/ef/expected-divergences-efdotorg.sexp for the full citation of + each. Date-keyed, the same discipline test_lms_ordo.ml's own + [allow_list_id_for_date] and test_fiuv_ordo.ml's own + [fiuv_allow_list_id_for_date] use, and for the identical reason: an + entry that starts firing on an unexpected new date must be visible as + a real change, not silently absorbed. Shared across all three editions + (unlike the LMS file's per-window function) because every id here is + adjudicated against colitur's own DATA or RULES, not against a single + edition's own printing quirk -- E1/E3/E4 each recur, unchanged, in + more than one edition. *) +let allow_list_id_for_date = function + | "2025-07-16" | "2026-07-16" | "2027-07-16" -> Some "E1" + | "2026-09-24" -> Some "E2" + | "2025-11-27" | "2026-11-27" -> Some "E3" + | "2025-05-06" | "2026-05-06" -> Some "E4" + | "2025-09-29" -> Some "E5" + | "2026-11-01" -> Some "E6" + | "2025-11-29" -> Some "E7" + | _ -> None + +let suite_2024_2025 = + make_suite ~label:"efdotorg-ordo-2024-2025" ~fixture_path:"fixtures/efdotorg-ordo-2024-2025.sexp" + ~fixture_sha256:"7de633e292fdb85415dd3ad87fcf9414fbb8f34c42772663b78e107e68c6e571" ~window_first:"2024-12-01" + ~window_last:"2025-11-29" ~year_lo:2023 ~year_hi:2026 ~expected_rows:364 ~expected_no_data:1 + ~allow_list_id_for_date + +let suite_2025_2026 = + make_suite ~label:"efdotorg-ordo-2025-2026" ~fixture_path:"fixtures/efdotorg-ordo-2025-2026.sexp" + ~fixture_sha256:"c810ec437cae9fde785f6b3453f77e667644fb82f465b3652040bb2a3b888b9b" ~window_first:"2025-11-30" + ~window_last:"2026-11-28" ~year_lo:2024 ~year_hi:2027 ~expected_rows:364 ~expected_no_data:1 + ~allow_list_id_for_date + +let suite_2026_2027 = + make_suite ~label:"efdotorg-ordo-2026-2027" ~fixture_path:"fixtures/efdotorg-ordo-2026-2027.sexp" + ~fixture_sha256:"19c35b45d7964dd357f92a871e81423af8217dff6c40178f3a95d3ec9c4091ea" ~window_first:"2026-11-29" + ~window_last:"2027-11-27" ~year_lo:2025 ~year_hi:2028 ~expected_rows:364 ~expected_no_data:2 + ~allow_list_id_for_date + +(* Guards against a stale allow-list entry, the same discipline + test_lms_ordo.ml's own [test_allow_list_ids_are_exactly_l4] uses: a + STATIC check that the sexp file's own declared ids are exactly this + set -- not a cross-edition "did every id actually fire" proof (neither + test_lms_ordo.ml nor test_fiuv_ordo.ml's own analogous guard attempts + that either; each edition's own [test_praef_matches_or_is_explained] + already fails loudly if an id fires the WRONG number of times, or if a + real divergence names an id that does not exist at all). *) +let test_allow_list_ids_are_exactly_e1_to_e7 () = + let ids = List.sort String.compare (List.map (fun e -> e.id) (load_allow_list allow_list_path)) in + Alcotest.(check (list string)) "the efdotorg allow-list declares exactly E1..E7" + [ "E1"; "E2"; "E3"; "E4"; "E5"; "E6"; "E7" ] ids + +let suite_allow_list = + ( "efdotorg-ordo-allow-list", + [ Alcotest.test_case "declares exactly E1..E7" `Quick test_allow_list_ids_are_exactly_e1_to_e7 ] ) diff --git a/test/test_fiuv_ordo.ml b/test/test_fiuv_ordo.ml new file mode 100644 index 0000000..3bfed68 --- /dev/null +++ b/test/test_fiuv_ordo.ml @@ -0,0 +1,595 @@ +(* Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1): the + SEVENTH validation layer, and the first UNIVERSAL, SECOND-COMPILER + witness -- the FIUV (Foederatio Internationalis Una Voce) Ordo for + 2025-2026, compiled by Joseph Shaw, independent of the Latin Mass + Society's own three editions (test_lms_ordo.ml) except for sharing a + publisher/host (see test/fixtures/fiuv-ordo-2025-2026.sexp's own + provenance header, and docs/research/ordo/PROVENANCE-ordo-corpus.md, + for the full account of what independence this source does and does + not buy). + + WHY THIS LAYER IS MORE VALUABLE THAN THE LMS ONE, per the task brief's + own four reasons: (1) UNIVERSAL -- no diocesan variants to exclude at + all, so this fixture's own [row] carries no [has_diocesan_variant] + field, unlike the LMS one; (2) IN LATIN, the rubrics' own vocabulary; + (3) BOTH DIRECTIONS EXPLICIT ("Gloria"/"sine Gloria", "Credo"/"sine + Credo") -- used here exactly as with the LMS source; (4) RECORDS THE + TE DEUM, the hinge of RG 431(a)'s own Mass-Gloria rule (deferred to + Phase 2, Breviary nn. 237-238) -- captured into the fixture, NOT + compared here (no colitur-side Te Deum predicate exists yet). + + SCOPE: the CREED (RG 475-476, {!Rite_ef.Rubrics_ef.creed}) is the ONE + axis compared against colitur, per the task brief. [praef] and + [te_deum] are captured into the fixture (a genuinely useful data set + for Phase 2/3's still-unbuilt Gloria and preface rules) but + deliberately NOT validated here -- there is nothing on colitur's own + side yet to compare either against. [class_] (raw, including the FIUV + ordo's own explicit "III cl." vs "III cl. (Priv.)" Cum Sanctissima + convention, stated on its own title page) is likewise captured but not + compared: colitur's core is strictly the 1962 Missal with Cum + Sanctissima/Quo Magis modelled only as an OVERLAY, never core + (CLAUDE.md's own binding decision #2), so colitur's UNOVERLAID output + has no Cum-Sanctissima-aware notion of "III cl." vs "(Priv.)" to + compare this field against in the first place -- comparing it would be + comparing the Ordo against a question colitur's default configuration + was never asked. *) + +module Cal = Colitur_kernel.Calendar +module Layer = Colitur_kernel.Layer +module Overlay = Colitur_kernel.Overlay +module LD = Colitur_kernel.Liturgical_day +module Date = Colitur_kernel.Date +module V = Rite_ef.Vocab_ef +module Preface = Colitur_kernel.Preface + +let sanctoral_path = "../data/ef/sanctoral.sexp" +let adjustments_path = "../data/ef/adjustments.sexp" +let fixture_path = "fixtures/fiuv-ordo-2025-2026.sexp" +let allow_list_path = "../data/ef/expected-divergences-fiuv.sexp" + +(* Duplicated, not shared -- test_lms_ordo.ml's own identical function + carries the same "no shared .mli" reasoning. *) +let sha256_of_file path = + let tmp = Filename.temp_file "colitur_fiuv_ordo_sha256" ".txt" in + Fun.protect + ~finally:(fun () -> try Sys.remove tmp with Sys_error _ -> ()) + (fun () -> + let cmd = Printf.sprintf "sha256sum %s > %s" (Filename.quote path) (Filename.quote tmp) in + let rc = Sys.command cmd in + if rc <> 0 then Alcotest.failf "sha256sum exited %d for %s (is it on PATH?)" rc path; + let ic = open_in tmp in + let line = + try input_line ic + with End_of_file -> + close_in ic; + Alcotest.failf "sha256sum produced no output for %s" path + in + close_in ic; + match String.index_opt line ' ' with + | Some i -> String.sub line 0 i + | None -> Alcotest.failf "unexpected sha256sum output for %s: %S" path line) + +let fixture_sha256 = "a744a2dbc7c8cf09590005e956c973f316209f3cf102b8035edadebf764110de" + +let real_layer () = + let layer = + match Layer.load V.rank_of_sexp sanctoral_path with + | Ok l -> l + | Error e -> Alcotest.failf "%s: failed to load: %s" sanctoral_path e + in + let overlay = + match Overlay.load V.rank_of_sexp adjustments_path with + | Ok o -> o + | Error e -> Alcotest.failf "%s: failed to load: %s" adjustments_path e + in + let layer, diagnostics = Overlay.apply layer overlay in + Alcotest.(check (list string)) "the committed overlay applies cleanly, no diagnostics" [] + (List.map Overlay.diagnostic_to_string diagnostics); + layer + +let real_lectionary () = + match Colitur_kernel.Lectionary.load "../data/ef/lectionary.sexp" with + | Ok l -> l + | Error e -> Alcotest.failf "../data/ef/lectionary.sexp: failed to load: %s" e + +let real_commons () = + match Rite_ef.Lectionary_ef.Commons.load "../data/ef/commons.sexp" with + | Ok c -> c + | Error e -> Alcotest.failf "../data/ef/commons.sexp: failed to load: %s" e + +(* ---------------------------------------------------------------------- *) +(* The Ordo side: the sexp row, mirrored from tools/extract_fiuv_ordo.ml's *) +(* own [row] -- see this file's own header on why there is no *) +(* [has_diocesan_variant] field here, unlike the LMS mirror. *) +(* ---------------------------------------------------------------------- *) + +open Sexplib0.Sexp_conv + +type ordo_row = { + date : string; + class_ : string option; + title : string; + te_deum : bool option; + gloria : bool option; + credo : bool option; + praef : string option; + alt_te_deum : bool option; + (** the "-VEL-" Cum-Sanctissima-alternative office's own Te Deum, + when this day prints one -- see tools/extract_fiuv_ordo.ml's own + [row.alt_te_deum] citation. Captured, not compared here: closing + F3 needed [te_deum] itself to stop reading it, not a new + colitur-side axis to check it against. *) +} +[@@deriving sexp] + +let ordo_rows () = + let sexp = + try Sexplib.Sexp.load_sexp fixture_path + with e -> Alcotest.failf "%s: failed to load: %s" fixture_path (Printexc.to_string e) + in + list_of_sexp ordo_row_of_sexp sexp + +let window_first = "2025-11-27" +let window_last = "2026-12-31" + +(* ---------------------------------------------------------------------- *) +(* The colitur side, over the same window -- mirrors test_lms_ordo.ml's *) +(* own [colitur_rows] exactly (a liturgical year straddles two civil *) +(* years, so the resolution walk starts a civil year early and ends one *) +(* late). *) +(* ---------------------------------------------------------------------- *) + +type colitur_row = { c_date : string; c_creed : bool; c_gloria : bool; c_preface : Preface.t option } + +let colitur_rows () = + let layer = real_layer () in + let rite = Rite_ef.context ~lectionary:(real_lectionary ()) ~commons:(real_commons ()) in + let by_rata : (int, (V.season, V.rank) LD.t) Hashtbl.t = Hashtbl.create 800 in + for y = 2024 to 2027 do + let days = Cal.year rite layer y in + Array.iter (fun (d : (V.season, V.rank) LD.t) -> Hashtbl.replace by_rata (Date.to_rata d.LD.date) d) days + done; + let mk s = match Date.of_iso8601 s with Ok d -> d | Error e -> Alcotest.failf "%s: %s" s e in + let rows = ref [] in + let d = ref (mk window_first) in + let stop = mk window_last in + while Date.compare !d stop <= 0 do + (match Hashtbl.find_opt by_rata (Date.to_rata !d) with + | Some day -> + rows := + { c_date = Date.to_iso8601 day.LD.date; c_creed = day.LD.creed; c_gloria = day.LD.gloria; + c_preface = day.LD.preface } + :: !rows + | None -> Alcotest.failf "no colitur day resolved for %s" (Date.to_iso8601 !d)); + d := Date.add_days !d 1 + done; + List.rev !rows + +(* Te Deum has no colitur-side [Liturgical_day.t] field of its own -- it is + a Breviary fact {!Rite_ef.Rubrics_ef.gloria} reads internally, not a Mass + part {!Colitur_kernel.Rite.t} exposes. Resolved separately, straight from + {!Rite_ef.Rubrics_ef.te_deum}, over the identical window/day set. *) +type colitur_te_deum_row = { + t_date : string; + t_te_deum : bool; + t_rank : V.rank; + t_slug : string; + t_has_commemoration : bool; +} + +let colitur_te_deum_rows () = + let layer = real_layer () in + let rite = Rite_ef.context ~lectionary:(real_lectionary ()) ~commons:(real_commons ()) in + let by_rata : (int, (V.season, V.rank) LD.t) Hashtbl.t = Hashtbl.create 800 in + for y = 2024 to 2027 do + let days = Cal.year rite layer y in + Array.iter (fun (d : (V.season, V.rank) LD.t) -> Hashtbl.replace by_rata (Date.to_rata d.LD.date) d) days + done; + let mk s = match Date.of_iso8601 s with Ok d -> d | Error e -> Alcotest.failf "%s: %s" s e in + let rows = ref [] in + let d = ref (mk window_first) in + let stop = mk window_last in + while Date.compare !d stop <= 0 do + (match Hashtbl.find_opt by_rata (Date.to_rata !d) with + | Some day -> + let te_deum = + Rite_ef.Rubrics_ef.te_deum ~temporal:day.LD.temporal ~observed:day.LD.observed ~date:day.LD.date + in + rows := + { t_date = Date.to_iso8601 day.LD.date; t_te_deum = te_deum; + t_rank = day.LD.observed.Colitur_kernel.Celebration.rank; + t_slug = Colitur_kernel.Slug.to_string day.LD.observed.Colitur_kernel.Celebration.slug; + t_has_commemoration = day.LD.commemorations <> [] } + :: !rows + | None -> Alcotest.failf "no colitur day resolved for %s" (Date.to_iso8601 !d)); + d := Date.add_days !d 1 + done; + List.rev !rows + +(* ---------------------------------------------------------------------- *) +(* data/ef/expected-divergences-fiuv.sexp -- same shape as the LMS/ *) +(* missalemeum allow-lists' own [allow_entry]. A SEPARATE file: this Ordo *) +(* is a fourth, independent lineage from all three others already in this *) +(* project. *) +(* ---------------------------------------------------------------------- *) + +type allow_entry = { id : string; citation : string; verdict : string; note : string; expected_rows : int } +[@@deriving sexp] + +let load_allow_list () = + let sexps = + try Sexplib.Sexp.load_sexps allow_list_path + with e -> Alcotest.failf "%s: failed to load: %s" allow_list_path (Printexc.to_string e) + in + List.map allow_entry_of_sexp sexps + +(* ---------------------------------------------------------------------- *) +(* Tests *) +(* ---------------------------------------------------------------------- *) + +let test_fixture_checksum () = + Alcotest.(check string) "fixture SHA-256 matches its provenance note" fixture_sha256 (sha256_of_file fixture_path) + +let test_dates_align () = + let ordo = ordo_rows () in + let colitur = colitur_rows () in + Alcotest.(check int) "the Ordo fixture has 400 rows (2025-11-27..2026-12-31)" 400 (List.length ordo); + Alcotest.(check int) "colitur resolved the same number of days" (List.length ordo) (List.length colitur); + (match ordo with o :: _ -> Alcotest.(check string) "first date" window_first o.date | [] -> Alcotest.fail "empty"); + (match List.rev ordo with + | o :: _ -> Alcotest.(check string) "last date" window_last o.date + | [] -> Alcotest.fail "empty"); + let mismatched = + List.filter_map + (fun (o, c) -> if String.equal o.date c.c_date then None else Some (o.date, c.c_date)) + (List.combine ordo colitur) + in + Alcotest.(check (list (pair string string))) "no misaligned dates" [] mismatched + +(* Holy Saturday (2026-04-04) is the ONLY day this fixture shows no Credo + marker for -- confirmed directly against the raw source: unlike the + LMS Ordo (whose "no Mass" day is Good Friday, the 1955-restored Holy + Week having no Mass that day at all), THIS Ordo's Good Friday DOES + carry a Mass rubric ("Missa pr., ... Gloria, sine Credo, praef. + comm."), leaving Holy Saturday as the sole day with no Mass mentioned + at all (its own Vigil Mass is conventionally counted under Easter + Sunday's own date in this source, matching a real, if narrower, + instance of the same "a vigil Mass is dated to the day it anticipates" + convention the LMS characterisation already established). Asserted as + the ONLY such day, not merely observed once: a parsing regression that + swallowed a real row would otherwise silently join this bucket instead + of failing loudly as an unexplained mismatch. *) +let test_creed_coverage () = + let ordo = ordo_rows () in + let no_creed = List.filter (fun o -> o.credo = None) ordo in + Alcotest.(check (list string)) "only Holy Saturday has no Ordo Creed marker" [ "2026-04-04" ] + (List.map (fun o -> o.date) no_creed) + +let describe_creed_mismatch (o : ordo_row) (c : colitur_row) = + Printf.sprintf "%s %S: colitur creed=%b, Ordo creed=%b" o.date o.title c.c_creed (Option.get o.credo) + +(* Which allow-list id, if any, explains a Creed mismatch on this date -- + date-keyed, not "any declared entry excuses any mismatch", the same + discipline test_lms_ordo.ml's own [allow_list_id_for_date] uses and + for the identical reason: an entry that starts firing on an + UNEXPECTED new date must be visible as a real change, not silently + absorbed. Empty until characterisation found a real divergence to + name. *) +let fiuv_allow_list_id_for_date = ([] : (string * string) list) + +let test_creed_matches_or_is_explained () = + let ordo = ordo_rows () in + let colitur = colitur_rows () in + let allow_list = load_allow_list () in + let by_id = List.map (fun e -> (e.id, e)) allow_list in + let unexplained = ref [] in + let explained_counts = Hashtbl.create 8 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.credo with + | None -> () + | Some ocreed -> + if Bool.equal ocreed c.c_creed then () + else + match List.assoc_opt o.date fiuv_allow_list_id_for_date with + | Some id -> Hashtbl.replace explained_counts id (1 + try Hashtbl.find explained_counts id with Not_found -> 0) + | None -> unexplained := describe_creed_mismatch o c :: !unexplained) + ordo colitur; + Alcotest.(check (list string)) "every Creed mismatch is named in the allow-list -- none unexplained" [] + (List.rev !unexplained); + Hashtbl.iter + (fun id n -> + match List.assoc_opt id by_id with + | None -> Alcotest.failf "allow-list entry %s used by the comparator but not declared in %s" id allow_list_path + | Some e -> Alcotest.(check int) (Printf.sprintf "%s: expected_rows matches the actual count" id) e.expected_rows n) + explained_counts; + List.iter + (fun e -> + if not (Hashtbl.mem explained_counts e.id) then + Alcotest.failf "allow-list entry %s is declared but never matched a real divergence" e.id) + allow_list + +(* ---------------------------------------------------------------------- *) +(* Gloria (RG 431-432, {!Rite_ef.Rubrics_ef.gloria}) -- Phase 2. Same shape *) +(* as the Creed comparison above, over the identical 400-row window. *) +(* ---------------------------------------------------------------------- *) + +let test_gloria_coverage () = + let ordo = ordo_rows () in + let no_gloria = List.filter (fun o -> o.gloria = None) ordo in + Alcotest.(check int) "exactly one day has no Ordo Gloria marker" 1 (List.length no_gloria) + +let describe_gloria_mismatch (o : ordo_row) (c : colitur_row) = + Printf.sprintf "%s %S: colitur gloria=%b, Ordo gloria=%b" o.date o.title c.c_gloria (Option.get o.gloria) + +(* F1 -- OPEN, adjudicated FOR colitur. The single Gloria mismatch found: + Good Friday (2026-04-03). See data/ef/expected-divergences-fiuv.sexp's + own F1 for the full citation and the raw source text this was checked + against directly (docs/research/ordo/fiuv-ordo-2025-2026.pdf, page 46). *) +let is_f1_good_friday (o : ordo_row) = String.equal o.date "2026-04-03" + +let test_gloria_matches_or_is_explained () = + let ordo = ordo_rows () in + let colitur = colitur_rows () in + let unexplained = ref [] in + let f1_count = ref 0 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.gloria with + | None -> () + | Some ogloria -> + if Bool.equal ogloria c.c_gloria then () + else if is_f1_good_friday o then incr f1_count + else unexplained := describe_gloria_mismatch o c :: !unexplained) + ordo colitur; + Alcotest.(check (list string)) "every Gloria mismatch is named in the allow-list -- none unexplained" [] + (List.rev !unexplained); + Alcotest.(check int) "F1 (Good Friday) count" 1 !f1_count + +(* ---------------------------------------------------------------------- *) +(* Preface (RG 482-499, {!Rite_ef.Rubrics_ef.preface}) -- Phase 3. Same *) +(* shape as Creed/Gloria above, over the identical 400-row window, using *) +(* the [praef] column already captured into the fixture (CAPTURED, NOT *) +(* VALIDATED at the time -- tools/extract_fiuv_ordo.ml's own [row.praef] *) +(* citation) but never compared until now. *) +(* *) +(* CHARACTERISATION FIRST, per the task's own standing instruction (this + project has been misled by trusting an Ordo field's surface shape + before, four times this session alone): [praef] is RAW TRAILING TEXT + after the literal token "praef." to the end of the primary Mass + clause -- it is not a clean enum, it can carry an arbitrary tail of + unrelated rubrical prose glued on by the same token-flattening that + produces it (Good Friday's own [gloria]/F1 finding above is the + worked example of exactly this shape). CLASSIFIED here by PREFIX + match against the FIRST WORD(S) only -- every prefix below was found + by direct inspection of the fixture's own distinct [praef] values + (test/fixtures/fiuv-ordo-2025-2026.sexp, 400 rows, all read by hand + while building this comparison) and cross-checked against the primary + rubric text, not guessed. Two genuine EXCEPTION SHAPES, THREE rows, + found the same way: + + - Christmas Day (both of them -- the fixture's own window, 27 + November 2025-31 December 2026, spans thirteen months and TWO 25 + Decembers, confirmed by running the coverage test below before + pinning it at "two", not three, the first time) and Epiphany Day + (2026-01-06, the window's only one) print "praef. et Communic..." + -- an ELLIPSIS: the compiler treats "this feast's own [i.e. + obviously implied] preface" as not needing its own name restated + on the ONE day that IS that feast, unlike every octave/de-Tempore + day governed by the SAME feast (which always restates the name + explicitly, e.g. 26 December's own "de Nativ."). Confirmed by + direct inspection: no OTHER day in the fixture omits the name this + way. [classify_praef] returns [None] (unrecognised) for all three + rather than special-casing them by date -- both feasts are + independently, directly citable from RG 484(a)/485(a)'s own text + (the Nativity/Epiphany feast itself is the paradigm case each + clause names first), so the oracle's corroboration is not needed + to trust colitur's own answer on these dates, and forcing a match + here would mean trusting an inference about the source's own + ellipsis rather than reading it. + - Good Friday (2026-04-03) prints "comm. Feria VI prima in mense." -- + classifies cleanly as [Common] by the same prefix rule as any + other day, but this file's own F1 (Gloria, above) already + adjudicated this EXACT date's raw text as unreliable (a copied, + not a considered, line -- confirmed against the PDF's own page + image, not merely the extracted fixture). The same defect + extends to whatever trails "praef." on the identical corrupted + line: excluded from this comparison by reusing [is_f1_good_friday] + directly, not re-argued. *) + +let has_prefix ~prefix s = + String.length s >= String.length prefix && String.sub s 0 (String.length prefix) = prefix + +(* Every prefix below maps 1:1 onto exactly one branch of + {!Rite_ef.Rubrics_ef.preface}'s own priority order -- see that + function's own header for the full citation of each. Order does not + matter here (unlike in [preface] itself): the Ordo's own printed text + never carries two of these prefixes on the same row, so this is a + partition, not a priority list. *) +let praef_prefixes = + [ ("comm.", Preface.Common); + ("Trinit.", Preface.Trinity); + ("Quadr.", Preface.Lent); + ("de Sancta Cruce", Preface.Holy_cross); + ("Pasch.", Preface.Easter); + ("etc. ut in festo", Preface.Easter); + (* Easter-octave ferias, "as on the feast [of Easter]" -- e.g. 6 + April 2026, "etc. ut in festo., ad Ite, missa est additur duplex + Alleluia." *) + ("Ascensionis", Preface.Ascension); + ("de Spirito Sancto", Preface.Holy_spirit); + ("BMV", Preface.Bvm); + ("App.", Preface.Apostles); + ("de Nativ.", Preface.Nativity); + ("de Epiphania", Preface.Epiphany); + ("de Ss.mi Corde", Preface.Sacred_heart); + ("de Ss.mo Corde", Preface.Sacred_heart); + ("de Domino Nostro Jesu Rege", Preface.Christ_the_king); + ("de S Iosepho", Preface.St_joseph); + ("de S Ioseph", Preface.St_joseph); + ("defunctorum", Preface.Requiem) ] + +let classify_praef (s : string) : Preface.t option = + let rec go = function + | [] -> None + | (prefix, p) :: rest -> if has_prefix ~prefix s then Some p else go rest + in + go praef_prefixes + +(* Measured directly, not assumed: every one of the 400 rows' own [praef] + text, classified, tallied by outcome. Two rows are genuinely + unclassifiable by this prefix table (the ellipsis dates above); every + other non-[None] [praef] value classifies. Pinned so a change to + either the fixture or [classify_praef] that silently drops coverage + fails loudly here rather than merely narrowing the comparison below. *) +let test_praef_classification_coverage () = + let ordo = ordo_rows () in + let with_praef = List.filter_map (fun o -> o.praef) ordo in + Alcotest.(check int) "399 of 400 rows carry a [praef] value (Holy Saturday is the one exception)" 399 + (List.length with_praef); + let unclassified = List.filter (fun s -> classify_praef s = None) with_praef in + (* THREE rows, not two: the fixture's own window (27 November 2025-31 + December 2026, 13 months) spans TWO Christmas Days, both printing the + identical ellipsis text -- found running this exact assertion, not + assumed from the date count alone. *) + Alcotest.(check int) "the three ellipsis rows (two Christmas Days, one Epiphany) are unclassified" 3 + (List.length unclassified); + Alcotest.(check bool) "every unclassified row starts with the ellipsis's own \"et Communic\"" true + (List.for_all (has_prefix ~prefix:"et Communic") unclassified) + +let describe_preface_mismatch (o : ordo_row) (c : colitur_row) (expected : Preface.t) = + Printf.sprintf "%s %S: colitur preface=%s, Ordo praef=%S (classified %s)" o.date o.title + (match c.c_preface with Some p -> Preface.to_string p | None -> "-") + (Option.get o.praef) (Preface.to_string expected) + +let test_preface_matches_or_is_explained () = + let ordo = ordo_rows () in + let colitur = colitur_rows () in + let unexplained = ref [] in + let unclassified_count = ref 0 in + let f1_count = ref 0 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + if is_f1_good_friday o then incr f1_count + else + match o.praef with + | None -> () + | Some raw -> ( + match classify_praef raw with + | None -> incr unclassified_count + | Some expected -> + if c.c_preface = Some expected then () + else unexplained := describe_preface_mismatch o c expected :: !unexplained)) + ordo colitur; + Alcotest.(check (list string)) "every classified preface difference is explained -- none unexplained" [] + (List.rev !unexplained); + Alcotest.(check int) "the three ellipsis rows are skipped, not silently counted as agreement" 3 + !unclassified_count; + Alcotest.(check int) "F1 (Good Friday) is skipped here too, the same root cause as the Gloria axis" 1 !f1_count + +(* ---------------------------------------------------------------------- *) +(* Te Deum (Breviary 237-238, {!Rite_ef.Rubrics_ef.te_deum}) -- Phase 2, *) +(* the mitigation the task brief names for this source's own stated *) +(* weakness (a single, not yet scan-verified, web transcription). A *) +(* SEPARATE colitur-side resolution ({!colitur_te_deum_rows}), since Te *) +(* Deum has no {!Colitur_kernel.Liturgical_day.t} field of its own. *) +(* *) +(* The SUNDAY shape this same comparison originally found (237(b)'s own *) +(* literal Septuagesima/Sexagesima/Quinquagesima exception, contradicted *) +(* 15/15) is FIXED at the source ({!Rite_ef.Rubrics_ef.te_deum}'s own *) +(* header has the correction and its full citation) -- not allow-listed, *) +(* because it no longer diverges. Three OTHER shapes remain OPEN, *) +(* single-witnessed (never captured by the LMS fixtures, which do not *) +(* record Te Deum at all) -- see data/ef/expected-divergences-fiuv.sexp's *) +(* own F2/F3/F4 for the full citations. Matched by PREDICATE, the same *) +(* "varies by shape, not by a fixed date list" reasoning L5/L6 already *) +(* establish for the LMS suite. *) +(* ---------------------------------------------------------------------- *) + +let test_te_deum_coverage () = + let ordo = ordo_rows () in + let no_te_deum = List.filter (fun o -> o.te_deum = None) ordo in + Alcotest.(check int) "the unresolved-Te-Deum population matches this fixture's own measured figure" 133 + (List.length no_te_deum) + +let describe_te_deum_mismatch (o : ordo_row) (t : colitur_te_deum_row) = + Printf.sprintf "%s %S: colitur te_deum=%b, Ordo te_deum=%b (rank=%s commemoration=%b)" o.date o.title t.t_te_deum + (Option.get o.te_deum) (V.rank_to_string t.t_rank) t.t_has_commemoration + +(* F2 (every I-class and omissible vigil), F4 (the three September Ember + days) and NOW F3 (the privileged-Lenten/Passiontide-feria-plus- + commemoration shape) were ALL THREE found against a buggy extraction + (see the fixture's own provenance header, "FIX HISTORY" section, and + {!Rite_ef.Rubrics_ef.te_deum}'s own 237(a) comment for F2/F4's own + account) -- re-run against the corrected data, NONE of the three fires + any more. + + F3 specifically was NEVER a Te Deum defect on either side: the six + dates print a complete SECOND office after a literal "-VEL-" ("or") + separator -- the same saint kept outright under the 2020 decree Cum + Sanctissima, with its OWN "Ad Mat. ... Te Deum" lessons -- and + tools/extract_fiuv_ordo.ml's own [extract_te_deum] used to scan the + WHOLE block unbounded, so on these six days (whose PRIMARY, strict- + 1962 office states no "Ad Mat." of its own at all) it silently read + the SECOND office's Te Deum instead. Fixed at the source + (tools/extract_fiuv_ordo.ml's own [split_at_alt_office]); the fixture + re-extracted from the SAME pdftotext dump. colitur's own answer + ([false], the primary office's own ferial Matins) was never wrong -- + the OTHER side of the comparison was reading the wrong printed office. + [te_deum] now reads [None] (unresolved, not [false]) on these six + dates, because the PRIMARY office's own text states no "Ad Mat." at + all, so there is nothing to positively confirm either direction from + -- consistent with [te_deum]'s own documented meaning elsewhere in + this fixture. + + NOTE, so a reader arriving here from data/ef/expected-divergences-lms.sexp's + own L5 does not draw the wrong conclusion: F3 never "contradicted" L5 + in the first place, and its removal does not corroborate L5 either. + Both were the SAME underlying fact read two different ways -- L5's own + 16 LMS dates and these 6 FIUV dates are exactly the shape the 2020 + decree Cum Sanctissima changes, and colitur, by CLAUDE.md's own binding + decision 2, models the 1962 core without it. See L5's own rewritten + entry for the full account, including the FIUV "-VEL-" dual printing + as the decisive evidence for BOTH files. + + Removed rather than kept as dead code with an [expected 0] pin, the + same "an entry that stops firing is a real change, not silently + absorbed" discipline data/ef/expected-divergences-lms.sexp's own L1/L3 + closures already establish -- see that file's own history for the + precedent this follows. *) + +let test_te_deum_matches_or_is_explained () = + let ordo = ordo_rows () in + let colitur = colitur_te_deum_rows () in + let unexplained = ref [] in + List.iter2 + (fun (o : ordo_row) (t : colitur_te_deum_row) -> + if not (String.equal o.date t.t_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date t.t_date; + match o.te_deum with + | None -> () + | Some otd -> if Bool.equal otd t.t_te_deum then () else unexplained := describe_te_deum_mismatch o t :: !unexplained) + ordo colitur; + Alcotest.(check (list string)) "every Te Deum mismatch is named in the allow-list -- none unexplained" [] + (List.rev !unexplained) + +let suite = + ( "fiuv-ordo", + [ Alcotest.test_case "fixture SHA-256 matches its provenance note" `Quick test_fixture_checksum; + Alcotest.test_case "streams are 400 rows each, dates aligned 1:1" `Quick test_dates_align; + Alcotest.test_case "only Holy Saturday has no Ordo Creed marker" `Quick test_creed_coverage; + Alcotest.test_case "every Creed difference is named in the cited allow-list -- none unexplained" `Quick + test_creed_matches_or_is_explained; + Alcotest.test_case "Ordo Gloria coverage matches the measured figure" `Quick test_gloria_coverage; + Alcotest.test_case "every Gloria difference is named in the cited allow-list -- none unexplained" `Quick + test_gloria_matches_or_is_explained; + Alcotest.test_case "praef classification coverage matches the measured figure" `Quick + test_praef_classification_coverage; + Alcotest.test_case "every classified preface difference is explained -- none unexplained" `Quick + test_preface_matches_or_is_explained; + Alcotest.test_case "Ordo Te Deum coverage matches the measured figure" `Quick test_te_deum_coverage; + Alcotest.test_case "every Te Deum difference is named in the cited allow-list -- none unexplained" `Quick + test_te_deum_matches_or_is_explained + ] ) diff --git a/test/test_golden.ml b/test/test_golden.ml index ba25d8a..c916a54 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -1281,6 +1281,33 @@ let test_readings_displaced_sunday_feria_known_divergent () = 2026 10 26 "2026-10-26 slug=ef-time-after-pentecost-22-monday first=Col 1:12-20. gospel=John 18:33-37" +(* ---- The Ascension-repeat rubric (celebrant-rubrics-phase1 Bug 2 fix, + 2026-08-22) ---- + + The Missale Romanum's own Proprium de Tempore carries an explicit + marginal rubric immediately after the Ascension's own Mass propers + (scan1.txt:20749-20754, both scans corroborate): "Diebus a feria VI post + Ascensionem usque ad feriam VI ante vigiliam Pentecostes inclusive, + dicitur Missa de festo Ascensionis" -- every feria without its own + proper, from the Friday after the Ascension through the Friday before + the Vigil of Pentecost, repeats the Ascension's own Mass (Acts 1:1-11 / + Mark 16:14-20), not the preceding Sunday's. Witnessed directly: the LMS + Ordo prints "Mass of the Ascension" literally on every affected day of + this shape across all three of its own fixture windows + (data/ef/expected-divergences-lms.sexp's own now-closed L2). + + 2031-05-23 is the exact day the bug report this task fixed was filed + against: the day after Ascension Thursday (2031-05-22, Easter+39), an + unoccupied Friday that step 3 used to walk back to + "ef-easter-sunday-6" -- the 5th Sunday after Easter, the wrong answer + -- instead of resolving at step 2 through the new + data/ef/lectionary.sexp entry. WHEN THIS PIN'S OWN VALUE WOULD REVERT TO + "Iac 1:22-27"/"Ioann 16:23-30" the fix has regressed; update it + deliberately then, never to make the suite pass again without checking + why. *) +let test_readings_ascension_week_repeat () = + check_readings ~msg:"the day after Ascension repeats the Ascension's own Mass, not the 5th Sunday after Easter's" + 2031 5 23 "2031-05-23 slug=ef-easter-6-friday first=Acts 1:1-11 gospel=Mark 16:14-20" (* ---- Rogation Wednesday (RG 87/88/89), movable-date-specs task ---- @@ -1315,6 +1342,95 @@ let test_rogation_wednesday_yields_to_a_feast_2026 () = "2026-05-13 wednesday season=paschaltide week=6 slug=ef-ascension-vigil rank=class-2 colour=white \ subject=temporal name_la=- comms=[robert-bellarmine:ordinary] in=- out=[]" +(* ---- Rogation Monday/Tuesday colour, RG 119/128/88 (celebrant-rubrics- + phase1 Bug 1 fix, 2026-08-22; data/ef/expected-divergences-lms.sexp's + now-closed L6, data/ef/expected-divergences.sexp's reopened C8) ---- + + {!Rite_ef.Temporal_ef.temporal}'s Rogation Monday/Tuesday branch used to + hardcode [Colour.Violet] with no citation. RG 119 assigns white to the + de-Tempore Office and Mass from the Paschal Vigil to the Pentecost Vigil + exclusive -- Easter+36/+37 sit inside that window -- and RG 128's own + exhaustive four-case violet list never names Rogation days; RG 88 ("de + Litaniis minoribus nihil fit in Officio") is why -- the violet belongs + to the Rogation MASS/procession alone, not the day's own Office. Fixed + to [season_colour s], the same call every other Paschaltide feria makes. + + 2028 pins BOTH days at once (unlike the LMS witness, which only reaches + one day per fixture window): neither is impeded by a competing + sanctoral feast that year, so both are observed outright, both white. + Verified directly against `date -d`: Easter 2028-04-16, so 22/23 May are + Easter+36/+37. *) +let test_rogation_monday_white_2028 () = + check ~msg:"2028: Rogation Monday is white (RG 119), not violet" 2028 5 22 + "2028-05-22 monday season=paschaltide week=6 slug=ef-rogation-monday rank=class-4 colour=white \ + subject=temporal name_la=- comms=[] in=- out=[]" + +let test_rogation_tuesday_white_2028 () = + check ~msg:"2028: Rogation Tuesday is white (RG 119), not violet" 2028 5 23 + "2028-05-23 tuesday season=paschaltide week=6 slug=ef-rogation-tuesday rank=class-4 colour=white \ + subject=temporal name_la=- comms=[] in=- out=[]" + +(* ---- The bissextile (leap-year) calendarium footnote, bissextile-shift + task, 2026-08-22 ---- + + The Missale Romanum's own CALENDARIUM table, February, footnote + (docs/research/LT.txt:5011-5014, scan-corroborated docs/research/ + scan2.txt:3050-3058): "In anno bissextili mensis februarius est dierum + 29, et festum S. Matthiae celebratur die 25 februarii, ac festum S. + Gabrielis a Virgine perdolente 28 februarii, et bis dicitur sexto + calendas, id est die 24 et die 25" -- in a leap year the sixth kalends + of March (24 February) is doubled rather than a 29th day appended, so + St Matthias (ordinarily 24 February) is kept on 25 February and St + Gabriel of Our Lady of Sorrows (ordinarily 27 February) on 28 February; + 24 February itself carries no fixed office that year. + {!Rite_ef.Temporal_ef.bissextile_fixed_key} implements this as the + rubric's own general MECHANISM, so a leap year moves the VACATED date's + slug/rank/colour away and the OCCUPIED date's toward it -- both sides + pinned for each saint, plus one common-year control apiece proving the + identity default is unchanged where the footnote does not apply. *) + +(* Matthias, 2044 (leap): 24 February carries no fixed office at all + (Class4 temporal only, zero commemorations); Matthias (Class2, an + Apostle) wins 25 February outright against that day's own Class4 + feria. *) +let test_bissextile_matthias_leap_2044 () = + check ~msg:"leap year: 24 February carries no fixed office, Matthias has moved away" 2044 2 24 + "2044-02-24 wednesday season=septuagesima week=2 slug=ef-septuagesima-2-wednesday rank=class-4 colour=violet \ + subject=temporal name_la=- comms=[] in=- out=[]"; + check ~msg:"leap year: Matthias observed outright on 25 February, not 24" 2044 2 25 + "2044-02-25 thursday season=septuagesima week=2 slug=matthias rank=class-2 colour=red subject=saint name_la=- \ + comms=[] in=- out=[]" + +(* Matthias, 2025 (common): unaffected control -- the identity default + applies, Matthias stays at his ordinary 24 February. *) +let test_bissextile_matthias_common_2025 () = + check ~msg:"common year: Matthias unaffected, still 24 February" 2025 2 24 + "2025-02-24 monday season=septuagesima week=2 slug=matthias rank=class-2 colour=red subject=saint name_la=- \ + comms=[] in=- out=[]" + +(* Gabriel of Our Lady of Sorrows, 2008 (leap): 27 February carries no + trace of him at all (not even a commemoration -- fixed_key removes him + from the candidate set entirely, RG 111's admission machinery never + sees him); on 28 February he is admitted as an ORDINARY commemoration + (Class3 ties the day's own privileged Lenten feria, which keeps + observed). A different shape from Matthias's outright win above, + deliberately pinned: the mechanism moves WHERE the saint is tried, not + whether he wins once he gets there. *) +let test_bissextile_gabriel_leap_2008 () = + check ~msg:"leap year: 27 February carries no trace of Gabriel, he has moved away" 2008 2 27 + "2008-02-27 wednesday season=lent week=3 slug=ef-lent-3-wednesday rank=class-3 colour=violet subject=temporal \ + name_la=- comms=[] in=- out=[]"; + check ~msg:"leap year: Gabriel admitted as an ordinary commemoration on 28 February, not 27" 2008 2 28 + "2008-02-28 thursday season=lent week=3 slug=ef-lent-3-thursday rank=class-3 colour=violet subject=temporal \ + name_la=- comms=[gabriel-of-our-lady-of-sorrows:ordinary] in=- out=[]" + +(* Gabriel of Our Lady of Sorrows, 2025 (common): unaffected control -- + observed outright at his ordinary 27 February. *) +let test_bissextile_gabriel_common_2025 () = + check ~msg:"common year: Gabriel unaffected, still observed on 27 February" 2025 2 27 + "2025-02-27 thursday season=septuagesima week=2 slug=gabriel-of-our-lady-of-sorrows rank=class-3 colour=white \ + subject=saint name_la=- comms=[] in=- out=[]" + (* RG 128, transcribed in docs/research/rules-register.md §3b: violet is used for "II/III-class vigils outside Paschaltide". Two of colitur's five vigils disagreed with that rule until the ef-oconnell-rubrics branch -- the @@ -1507,8 +1623,22 @@ let suite = Alcotest.test_case "readings: displaced-Sunday feria pins M26 shape 2(b)'s KNOWN-WRONG walkback (2026-10-26)" `Quick test_readings_displaced_sunday_feria_known_divergent; + Alcotest.test_case "readings: the Ascension-repeat rubric, the reported bug's own date (2031-05-23)" `Quick + test_readings_ascension_week_repeat; Alcotest.test_case "RG87: Rogation Wednesday admitted (2024)" `Quick test_rogation_wednesday_admitted_2024; Alcotest.test_case "RG87/113: Rogation Wednesday yields to an impeded feast (2026)" `Quick - test_rogation_wednesday_yields_to_a_feast_2026 + test_rogation_wednesday_yields_to_a_feast_2026; + Alcotest.test_case "RG119/128: Rogation Monday is white, not violet (2028)" `Quick + test_rogation_monday_white_2028; + Alcotest.test_case "RG119/128: Rogation Tuesday is white, not violet (2028)" `Quick + test_rogation_tuesday_white_2028; + Alcotest.test_case "bissextile footnote: Matthias moves 24->25 February (leap, 2044)" `Quick + test_bissextile_matthias_leap_2044; + Alcotest.test_case "bissextile footnote: Matthias unaffected (common, 2025)" `Quick + test_bissextile_matthias_common_2025; + Alcotest.test_case "bissextile footnote: Gabriel of Our Lady of Sorrows moves 27->28 February (leap, 2008)" + `Quick test_bissextile_gabriel_leap_2008; + Alcotest.test_case "bissextile footnote: Gabriel of Our Lady of Sorrows unaffected (common, 2025)" `Quick + test_bissextile_gabriel_common_2025 ] ) diff --git a/test/test_lectionary.ml b/test/test_lectionary.ml index 7dbb253..59c739d 100644 --- a/test/test_lectionary.ml +++ b/test/test_lectionary.ml @@ -115,8 +115,14 @@ let test_ef_data_file_loads () = ([epiphanytide_opening_entries], +15); TWO hand-authored directly from the Missal, two major movable feasts with previously no entry at all ([movable_feast_entries], +2). - 116 + 1 + 6 + 1 + 2 + 3 + 2 + 15 + 2 = 148. *) - Alcotest.(check int) "entry count" 153 + 116 + 1 + 6 + 1 + 2 + 3 + 2 + 15 + 2 = 148. + celebrant-rubrics-phase1, Bug 2 (2026-08-22): SIX hand-authored + directly from the Missal's own marginal Ascension-repeat rubric + ([ascension_week_entries], +6, 153 -> 159) -- see that + function's own comment in bootstrap_lectionary.ml for the + citation and why the window's two Saturdays are deliberately + excluded. *) + Alcotest.(check int) "entry count" 159 (List.length (Lectionary.entries l)); (match Lectionary.find l (slug "ef-lent-1-monday") with | Some [ a; b ] -> @@ -179,6 +185,34 @@ let test_ef_data_file_loads () = scans). *) check_entry "ef-corpus-christi" "1 Cor 11:23-29" "John 6:56-59"; check_entry "ef-sacred-heart" "Eph 3:8-12, 14-19" "John 19:31-37"; + (* celebrant-rubrics-phase1, Bug 2: the Missal's own marginal rubric + after the Ascension's own Mass propers ("Diebus a feria VI post + Ascensionem usque ad feriam VI ante vigiliam Pentecostes + inclusive, dicitur Missa de festo Ascensionis") repeats the + Ascension's own citation on the ferias that would otherwise walk + back to the wrong Sunday. Two families pinned (the tail of + Ascension's own week; the following week), not merely one, the + same "more than one weekday" discipline this file already uses + for the Lent Ember pins above. *) + check_entry "ef-easter-6-friday" "Acts 1:1-11" "Mark 16:14-20"; + check_entry "ef-easter-7-monday" "Acts 1:1-11" "Mark 16:14-20"; + check_entry "ef-easter-7-friday" "Acts 1:1-11" "Mark 16:14-20"; + (* [ef-easter-6-saturday] keeps its own PRE-EXISTING entry, unchanged + by this task -- RG 78's votive Office of Our Lady always wins an + otherwise-unoccupied Class4 Saturday first ([readings]' own step + ordering runs that branch before step 2 is ever reached), so this + table's own value for that slug is dead data on shipped data, but + it was already there before this task and touching it is out of + scope. [ef-easter-7-saturday] must stay ABSENT instead: that civil + day is the Vigil of Pentecost, a NAMED day with its own slug and + Mass (temporal_ef.ml's own [named]), so the generic + [ef-<season>-<week>-<weekday>] ferial slug this table's new + entries key off never gets produced there at all -- an entry + would be unreachable data [assert_reachable] would have refused + to emit, checked here too as a direct regression net. *) + (match Lectionary.find l (slug "ef-easter-7-saturday") with + | None -> () + | Some _ -> Alcotest.fail "ef-easter-7-saturday: must stay absent -- the Vigil of Pentecost, named, never a ferial slug"); check_entry "ef-nativity-vigil" "Rom 1:1-6" "Matt 1:18-21"; check_entry "ef-pentecost-ember-wed" "Acts 5:12-16" "John 6:44-52."; check_entry "ef-pentecost-ember-fri" "Joel 2:23-24; 26-27" "Luke 5:17-26"; diff --git a/test/test_lectionary_ef.ml b/test/test_lectionary_ef.ml index d56d187..3e0880e 100644 --- a/test/test_lectionary_ef.ml +++ b/test/test_lectionary_ef.ml @@ -467,7 +467,7 @@ let test_step4_unreachable_commons_still_resolve () = let for_saint s = Lectionary_ef.commons_for ~commons (Slug.of_string_exn s) in let refs_of = function | None -> [ "<no common>" ] - | Some cs -> List.map (fun c -> c.Citation.reference) cs + | Some (_id, cs) -> List.map (fun c -> c.Citation.reference) cs in Alcotest.(check (list string)) "St Benedict (21 March), Common of Abbots" @@ -580,6 +580,89 @@ let test_commons_load_rejects_bad_data () = (Slug.of_string_exn "benedict") = None) +(* ---------------------------------------------------------------------- *) +(* The formulary itself (Task 2): each step of the chain now reports HOW *) +(* it resolved, not only what it resolved. One day per step, plus the RG *) +(* 309(a) votive branch (fix round 1) -- the same dates this file already *) +(* uses (and hand-verifies) elsewhere for the citations those days carry, *) +(* so no new date needs independent checking. *) +(* ---------------------------------------------------------------------- *) + +let formulary_cases = + [ (* step 1: a saint with his own proper -- same date as + [test_step1_proper_beats_any_common_john_of_god]. *) + (2038, 3, 8, Some "john-of-god", Colitur_kernel.Mass_formulary.Proper); + (* step 2: the day's own temporal slug -- same date as + [test_step2_lenten_feria_has_its_own], Monday of Lent I. *) + (2026, 2, 23, Some "ef-lent-1-monday", Colitur_kernel.Mass_formulary.Own_slug); + (* step 3: a feria resuming the preceding Sunday. The task brief's own + snippet pinned this date against week 9 ("ef-time-after-pentecost- + sunday-9"); running the real resolver against 2026 shows 3 August + 2026 is Monday of week 10, resuming 2 August's "...sunday-10" -- + corrected per the brief's own "find the dates by running the current + binary if they drift" instruction. *) + (2026, 8, 3, Some "ef-time-after-pentecost-sunday-10", + Colitur_kernel.Mass_formulary.Preceding_sunday); + (* step 4: a saint sent to a Common -- same date as + [test_step4_commons_perpetua_and_felicity]; [said] is the Common's + OWN id (data/ef/commons.sexp), not the saint's slug. *) + (2038, 3, 6, Some "common-of-non-virgins-1", Colitur_kernel.Mass_formulary.Common); + (* Fix round 1 (coordinator review): the RG 309(a)/RG 78 Saturday votive + Mass of Our Lady, structurally reached between steps 4 and 2 (see + [readings]' own implementation comment) but tagged [Votive], not + [Own_slug] -- RG 431(e) ("in Missis votivis IV classis ... de B. + Maria Virg. quae in sabbato celebrantur") classifies this Mass, in + the Missal's own words, as a "Missa votiva", said in place of the + day's own office's Mass while the office (RG 78) itself is kept. + (CORRECTED, fix round 2: this previously also claimed the Latin Mass + Society Ordo witnesses the tag by printing "V" as an abbreviation for + "votive" on this day -- that was the coordinator's own misreading; + the Ordo's "I"-"V" are roman numerals naming which of the Missal's + five SEASONAL Masses is said, not the Mass's kind -- see + [readings]' own implementation comment for the full account.) 1 August + 2026 verified directly against the real resolver (`colitur day + 2026`), not trusted from a supplied date, given this session's own + drifted-pin history: a IV-class Saturday, "Officium sanctae Mariae in + sabbato", temporal slug [ef-time-after-pentecost-9-saturday]. + (CORRECTED, whole-branch review fix round: [said] used to be + claimed "unaffected by the retag" and pinned to that same reused + ferial slug -- that was the defect this round fixed. [said] is + [None] here: the shipped data names no slug for the votive Mass + actually said, only for the office it replaces. The office slug + itself is checked separately, below, via [observed.slug], not + through [said] -- see {!Colitur_kernel.Mass_formulary.t}'s own + citation for why the two are no longer conflated.) *) + (2026, 8, 1, None, Colitur_kernel.Mass_formulary.Votive) ] + +let test_formulary_reports_its_source () = + List.iter + (fun (y, m, d, expected_slug, expected_via) -> + let day = day y m d in + match day.Colitur_kernel.Liturgical_day.formulary with + | None -> Alcotest.failf "%04d-%02d-%02d: no formulary" y m d + | Some f -> + Alcotest.(check (option string)) + (Printf.sprintf "%04d-%02d-%02d slug" y m d) + expected_slug + (Option.map Colitur_kernel.Slug.to_string f.Colitur_kernel.Mass_formulary.said); + Alcotest.(check string) + (Printf.sprintf "%04d-%02d-%02d source" y m d) + (Colitur_kernel.Mass_formulary.source_to_string expected_via) + (Colitur_kernel.Mass_formulary.source_to_string + f.Colitur_kernel.Mass_formulary.via)) + formulary_cases + +(* [said = None] on the Votive day above does not mean the office is lost -- + {!Colitur_kernel.Mass_formulary.t}'s own citation says a caller reads it + off [observed.slug] instead, on the very same {!Colitur_kernel. + Liturgical_day.t}. Checked directly, not merely asserted: the same + 1 August 2026 date, same expected slug the old (pre-fix) [said] field + used to carry. *) +let test_votive_office_slug_still_available_via_observed () = + let d = day 2026 8 1 in + Alcotest.(check string) "2026-08-01 observed slug" "ef-time-after-pentecost-9-saturday" + (Colitur_kernel.Slug.to_string d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug) + let suite = [ ("step 1: sanctoral proper", `Quick, test_step1_sanctoral_proper); ("step 2: own temporal proper", `Quick, test_step2_lenten_feria_has_its_own); @@ -618,4 +701,8 @@ let suite = ("the five propers no real year reaches are present", `Quick, test_step4_unreachable_propers_are_present); ("Commons.load rejects the four silent-degradation defects", `Quick, - test_commons_load_rejects_bad_data) ] + test_commons_load_rejects_bad_data); + ("the formulary reports its own source, one day per step", `Quick, + test_formulary_reports_its_source); + ("the Votive office slug is still available via observed, not said", `Quick, + test_votive_office_slug_still_available_via_observed) ] diff --git a/test/test_lms_ordo.ml b/test/test_lms_ordo.ml new file mode 100644 index 0000000..0ac314e --- /dev/null +++ b/test/test_lms_ordo.ml @@ -0,0 +1,1020 @@ +(* Task 6 (2026-08-21-colitur-celebrant-rubrics-phase1) built this layer + against ONE LMS Ordo edition (2024-2025). The Witnesses task + (2026-08-22, same phase) extends it to THREE editions -- 2023-2024, + 2024-2025, 2025-2026 -- each compared in its OWN window, counted and + reported SEPARATELY, never merged: a divergence appearing in one year + and not another is informative on its own, and merging would hide it. + [make_suite] below is the shared machinery Task 6 built as a single + flat file; every per-year fact that Task 6 hardcoded (window dates, + fixture SHA-256, the "only Good Friday has no Creed marker" pin, the + formulary-bucket totals, the BVM-Saturday population) is now a + parameter or a value RE-DERIVED from the rubric independently per + window, not copied forward -- see each call site below for the + per-edition numbers, which do differ (397/399/400 rows; not every + edition even has the same II-class "sharp pairing" saint available, + see [fixture_probes] in tools/extract_lms_ordo.ml's own header for + 2025-2026's own Joachim-is-impeded finding). + + WHY THIS LAYER EXISTS, AND WHAT IT IS INDEPENDENT OF: layers 3-4 + (test_differential.ml, test_oracle.ml) are ONE LINEAGE running Divinum + Officium -> missalemeum -> lectio -> colitur (CLAUDE.md's "know what + each layer cannot see" section); layer 5 (test_golden.ml) pins colitur's + own output against itself. This Ordo is compiled independently by the + Latin Mass Society (a printed book, England & Wales diocesan propers) + from the 1962 Missal/1960 rubrics directly -- it never passed through + Divinum Officium, missalemeum or lectio at any point, so an error + inherited by that whole lineage (colitur's own bootstrap included) is + visible here for the first time. Three editions of the SAME publisher's + book are still only ONE compiler's judgement (see docs/research/ordo/ + PROVENANCE-ordo-corpus.md's own "what this corpus still cannot show" -- + genuine cross-compiler independence needs the FIUV layer, test_fiuv_ + ordo.ml, built separately in this same task). + + SCOPE, decided after running the comparison against real data (not + guessed in advance -- see each fixture's own CHARACTERISATION section): + + - The CREED (RG 475-476, {!Rite_ef.Rubrics_ef.creed}): compared on + every day, full 1:1, in every edition's own window. Exactly one day + per window is EXCLUDED, not silently skipped: that window's own + Good Friday (RE-DERIVED per window from {!Colitur_kernel.Computus. + gregorian_easter}, never hardcoded to a specific date) has no Mass + in the 1955-restored Holy Week, so the Ordo prints no Gl/Cr line at + all there -- [test_creed_coverage] asserts this is the ONLY such + day per window. + + - The BVM-SATURDAY SEASONAL SELECTION (RG 309(a), "iuxta temporum + diversitatem", {!Rite_ef.Lectionary_ef.bvm_saturday_citations}): + the Ordo's own roman numeral (I-V) names WHICH of the five seasonal + "Missae de sancta Maria in sabbato" is said, so it validates + colitur's SEASONAL SELECTION, not merely that some BVM Mass was + chosen. Checked against every {!Colitur_kernel.Mass_formulary. + Votive} day inside each edition's own window. + + - The FORMULARY OVERRIDE (does the day say its own Mass, or a + borrowed one) -- compared for THREE of {!Colitur_kernel. + Mass_formulary.source}'s five constructors ([Proper]/ + [Preceding_sunday]/[Common]), on the same [Own_slug]-excluded, + [Votive]-covered-separately basis Task 6 established (see that + task's own report for the full reasoning: 11 of [Own_slug]'s + real days show an Ordo override anyway, a data-representation + ambiguity in colitur's own lectionary, not a rubric question the + Ordo could adjudicate). + + GLORIA is extracted into every fixture (a genuine, independently useful + field for the still-unbuilt Phase 2 Gloria rule) but NOT compared here: + colitur has no {!Rite_ef.Rubrics_ef}-level Gloria predicate yet. + + DIOCESAN SCOPE: colitur computes the UNIVERSAL General Roman Calendar + only (no diocesan overlay loaded by the differential/oracle harnesses + anywhere in this suite) -- every LMS edition is an England & Wales + diocesan Ordo, and each fixture's own provenance header quantifies how + many of its days carry at least one diocesan variant. Every comparison + in this file reads ONLY each fixture's own universal-block fields. *) + +module Cal = Colitur_kernel.Calendar +module Layer = Colitur_kernel.Layer +module Overlay = Colitur_kernel.Overlay +module LD = Colitur_kernel.Liturgical_day +module Date = Colitur_kernel.Date +module Computus = Colitur_kernel.Computus +module MF = Colitur_kernel.Mass_formulary +module V = Rite_ef.Vocab_ef +module TE = Rite_ef.Temporal_ef +module Preface = Colitur_kernel.Preface + +let sanctoral_path = "../data/ef/sanctoral.sexp" +let adjustments_path = "../data/ef/adjustments.sexp" + +(* Duplicated, not shared, from test_oracle.ml/test_differential.ml's own + identical function -- neither file exposes an .mli the other could + depend on, and this is three lines (test_oracle.ml's own comment). *) +let sha256_of_file path = + let tmp = Filename.temp_file "colitur_lms_ordo_sha256" ".txt" in + Fun.protect + ~finally:(fun () -> try Sys.remove tmp with Sys_error _ -> ()) + (fun () -> + let cmd = Printf.sprintf "sha256sum %s > %s" (Filename.quote path) (Filename.quote tmp) in + let rc = Sys.command cmd in + if rc <> 0 then Alcotest.failf "sha256sum exited %d for %s (is it on PATH?)" rc path; + let ic = open_in tmp in + let line = + try input_line ic + with End_of_file -> + close_in ic; + Alcotest.failf "sha256sum produced no output for %s" path + in + close_in ic; + match String.index_opt line ' ' with + | Some i -> String.sub line 0 i + | None -> Alcotest.failf "unexpected sha256sum output for %s: %S" path line) + +let real_layer () = + let layer = + match Layer.load V.rank_of_sexp sanctoral_path with + | Ok l -> l + | Error e -> Alcotest.failf "%s: failed to load: %s" sanctoral_path e + in + let overlay = + match Overlay.load V.rank_of_sexp adjustments_path with + | Ok o -> o + | Error e -> Alcotest.failf "%s: failed to load: %s" adjustments_path e + in + let layer, diagnostics = Overlay.apply layer overlay in + Alcotest.(check (list string)) "the committed overlay applies cleanly, no diagnostics" [] + (List.map Overlay.diagnostic_to_string diagnostics); + layer + +let real_lectionary () = + match Colitur_kernel.Lectionary.load "../data/ef/lectionary.sexp" with + | Ok l -> l + | Error e -> Alcotest.failf "../data/ef/lectionary.sexp: failed to load: %s" e + +let real_commons () = + match Rite_ef.Lectionary_ef.Commons.load "../data/ef/commons.sexp" with + | Ok c -> c + | Error e -> Alcotest.failf "../data/ef/commons.sexp: failed to load: %s" e + +(* ---------------------------------------------------------------------- *) +(* The Ordo side: the sexp row, mirrored (not shared -- see this file's *) +(* own header) from tools/extract_lms_ordo.ml's own [row]. *) +(* ---------------------------------------------------------------------- *) + +open Sexplib0.Sexp_conv + +type ordo_row = { + date : string; + weekday : string; + title : string; + formulary_override : string option; + bvm_numeral : string option; + gloria : bool option; + creed : bool option; + praef : string option; + has_diocesan_variant : bool; +} +[@@deriving sexp] + +let ordo_rows fixture_path = + let sexp = + try Sexplib.Sexp.load_sexp fixture_path + with e -> Alcotest.failf "%s: failed to load: %s" fixture_path (Printexc.to_string e) + in + list_of_sexp ordo_row_of_sexp sexp + +(* ---------------------------------------------------------------------- *) +(* The colitur side, over the SAME window a given fixture covers. Mirrors *) +(* test_oracle.ml's own [colitur_rows]: the resolution walk starts a civil *) +(* year EARLY (and ends one late) because a liturgical year is *) +(* Advent-anchored and straddles two civil years -- generalised from Task *) +(* 6's single hardcoded [2023..2025] to a [~year_lo]/[~year_hi] parameter *) +(* per window, since the three editions' own civil-year spans differ. *) +(* ---------------------------------------------------------------------- *) + +type colitur_row = { + c_date : string; + c_season : V.season; + c_formulary : MF.t option; + c_creed : bool; + c_gloria : bool; + c_preface : Preface.t option; + c_rank : V.rank; + c_slug : string; + c_has_commemoration : bool; + (** whether {!Colitur_kernel.Liturgical_day.t.commemorations} is + non-empty -- needed by the Gloria comparison's own L5 shape + (RG 431(b)/n.302(b)), not by anything Task 6 built. *) +} + +let colitur_rows ~year_lo ~year_hi ~window_first ~window_last = + let layer = real_layer () in + let rite = Rite_ef.context ~lectionary:(real_lectionary ()) ~commons:(real_commons ()) in + let by_rata : (int, (V.season, V.rank) LD.t) Hashtbl.t = Hashtbl.create 800 in + for y = year_lo to year_hi do + let days = Cal.year rite layer y in + Array.iter (fun (d : (V.season, V.rank) LD.t) -> Hashtbl.replace by_rata (Date.to_rata d.LD.date) d) days + done; + let mk s = + match Date.of_iso8601 s with Ok d -> d | Error e -> Alcotest.failf "%s: not a valid ISO-8601 date: %s" s e + in + let rows = ref [] in + let d = ref (mk window_first) in + let stop = mk window_last in + while Date.compare !d stop <= 0 do + (match Hashtbl.find_opt by_rata (Date.to_rata !d) with + | Some day -> + rows := + { c_date = Date.to_iso8601 day.LD.date; c_season = day.LD.temporal.Colitur_kernel.Temporal.season; + c_formulary = day.LD.formulary; c_creed = day.LD.creed; c_gloria = day.LD.gloria; + c_preface = day.LD.preface; + c_rank = day.LD.observed.Colitur_kernel.Celebration.rank; + c_slug = Colitur_kernel.Slug.to_string day.LD.observed.Colitur_kernel.Celebration.slug; + c_has_commemoration = day.LD.commemorations <> [] } + :: !rows + | None -> Alcotest.failf "no colitur day resolved for %s" (Date.to_iso8601 !d)); + d := Date.add_days !d 1 + done; + List.rev !rows + +(* ---------------------------------------------------------------------- *) +(* RG 309(a), "iuxta temporum diversitatem" -- INDEPENDENTLY re-derived *) +(* from the rubric, not called from Lectionary_ef.bvm_saturday_citations. *) +(* ---------------------------------------------------------------------- *) + +let expected_bvm_numeral season ~month ~day = + match (season : V.season) with + | V.Advent -> "I" + | V.Christmastide -> "II" + | V.Time_after_epiphany when month = 1 || (month = 2 && day <= 2) -> "II" + | V.Time_after_epiphany | V.Septuagesima | V.Lent | V.Passiontide -> "III" + | V.Paschaltide -> "IV" + | V.Time_after_pentecost -> "V" + +(* ---------------------------------------------------------------------- *) +(* data/ef/expected-divergences-lms.sexp -- same shape as *) +(* test_oracle.ml's own [allow_entry]/[load_allow_list]. ONE allow-list *) +(* file for all three editions (they are one lineage, the same publisher *) +(* and compiler) -- an entry's own [note] names which edition(s) it fired *) +(* on when that matters. *) +(* ---------------------------------------------------------------------- *) + +type allow_entry = { id : string; citation : string; verdict : string; note : string; expected_rows : int } +[@@deriving sexp] + +let load_allow_list allow_list_path = + let sexps = + try Sexplib.Sexp.load_sexps allow_list_path + with e -> Alcotest.failf "%s: failed to load: %s" allow_list_path (Printexc.to_string e) + in + List.map allow_entry_of_sexp sexps + +(* ---------------------------------------------------------------------- *) +(* Formulary override, restricted to Proper/Common/Preceding_sunday -- *) +(* see this file's own header for why Own_slug is excluded, and Votive is *) +(* covered by the BVM checks instead. Unchanged from Task 6 except for *) +(* being read per-window rather than off a single hardcoded fixture. *) +(* ---------------------------------------------------------------------- *) + +let ordinal n = + let suffix = + if n mod 100 >= 11 && n mod 100 <= 13 then "th" + else match n mod 10 with 1 -> "st" | 2 -> "nd" | 3 -> "rd" | _ -> "th" + in + Printf.sprintf "%d%s" n suffix + +let parse_sunday_slug slug = + let prefix = "ef-" in + let plen = String.length prefix in + if String.length slug <= plen || String.sub slug 0 plen <> prefix then None + else + let body = String.sub slug plen (String.length slug - plen) in + let marker = "-sunday-" in + let mlen = String.length marker and blen = String.length body in + let rec find_last i best = if i + mlen > blen then best + else find_last (i + 1) (if String.sub body i mlen = marker then Some i else best) + in + match find_last 0 None with + | None -> None + | Some i -> ( + let word = String.sub body 0 i in + let num_str = String.sub body (i + mlen) (blen - i - mlen) in + match int_of_string_opt num_str with Some n -> Some (word, n) | None -> None) + +(* [~season] disambiguates ONE genuinely ambiguous case, found extending + this suite to the 2023-2024 window (2024-11-05..08): colitur's own + "resumed-Sunday tail" (CLAUDE.md's own term) REUSES an Epiphany Sunday's + own slug ([ef-time-after-epiphany-sunday-4]) for a feria whose REAL + calendar date falls in November, inside Time after Pentecost -- Easter + was late enough in 2024 that not every Epiphany Sunday got "used" before + Septuagesima cut the season short, so the leftover ones resume near the + END of the year instead. The Ordo's own prose distinguishes the two + occurrences of the SAME slug by wording alone: "4th Sunday after the + Epiphany" in January, "4th Sunday REMAINING after the Epiphany" in + November (verified directly against the raw dump). [c_season] is the + feria's own actual calendar season -- [Time_after_epiphany] for the + January occurrence, [Time_after_pentecost] for the November one -- so + comparing it against the WORD parsed out of the resumed slug ("time- + after-epiphany" either way) is exactly the signal needed, with no new + colitur-side field required. *) +let expected_preceding_sunday_override ~(season : V.season) (word : string) (n : int) = + match (word, n) with + | "advent", 1 -> Some "Advent Sunday" + | "advent", 2 -> Some "2nd Sunday of Advent" + | "advent", 3 -> Some "3rd Sunday of Advent (Gaudete Sunday)" + | "advent", 4 -> Some "4th Sunday of Advent" + | "septuagesima", 1 -> Some "Septuagesima Sunday" + | "septuagesima", 2 -> Some "Sexagesima Sunday" + | "septuagesima", 3 -> Some "Quinquagesima Sunday" + | "time-after-epiphany", n when season = V.Time_after_epiphany -> + Some (Printf.sprintf "%s Sunday after the Epiphany" (ordinal n)) + | "time-after-epiphany", n -> Some (Printf.sprintf "%s Sunday remaining after the Epiphany" (ordinal n)) + | "time-after-pentecost", 24 -> Some "24th & Last Sunday After Pentecost" + | "time-after-pentecost", n -> Some (Printf.sprintf "%s Sunday after Pentecost" (ordinal n)) + (* [n >= 3], no upper bound: Task 6's original [n <= 5] excluded n=6/7 on + the (overfit, 2024-2025-window-only) assumption that EVERY such day is + Ascension-adjacent. Extending to 2023-2024/2025-2026 found a REAL + counter-example -- Rogation Monday (RG 87-89), which also resumes + week 6's own Sunday but falls BEFORE Ascension, not after, and the + Ordo prints the ordinary "5th Sunday after Easter" there, not "Mass + of the Ascension". The caller now decides Ascension-adjacency by the + day's own DATE against {!Computus.ascension}, not by [n] -- so this + mapping can be trusted for n=6/7 whenever the caller does not first + divert to [ascension_week_override]. *) + | "easter", n when n >= 3 -> Some (Printf.sprintf "%s Sunday after Easter" (ordinal (n - 1))) + | _ -> None + +let expected_named_sunday_override slug ~year = + if String.equal slug "ef-christ-the-king" then + match TE.week (TE.christ_the_king year) with + | Some n -> Some (Printf.sprintf "%s Sunday after Pentecost" (ordinal n)) + | None -> None + (* [ef-low-sunday]: a SECOND named-Sunday population reaching + [Preceding_sunday], found the same way [ef-christ-the-king] was -- + absent from the 2024-2025 window Task 6 built this mapping against + (every Low-Sunday-week feria that year had its own proper), present + in both 2023-2024 (9-12 April 2024) and 2025-2026. The Ordo's own + text is the plain, unnumbered "Mass of Low Sunday". *) + else if String.equal slug "ef-low-sunday" then Some "Low Sunday" + else None + +(* See Task 6's own [ascension_week_override] citation (test_lms_ordo.ml + history, data/ef/expected-divergences-lms.sexp's own now-CLOSED L2, + celebrant-rubrics-phase1 Bug 2, 2026-08-22): STRUCTURAL, not a fixture + artefact -- the Ascension is a fixed Easter+39, so every feria whose own + [Preceding_sunday] fallback would otherwise resolve to a week-6/7 Sunday + falls, in SOME years, between Ascension Thursday and the following + Sunday. Extending this suite past the single 2024-2025 window sharpened + the finding: it is specifically the days AFTER Ascension (not merely + "any week-6/7 Preceding_sunday day") that get this treatment -- see + [expected_preceding_sunday_override]'s own citation for the Rogation + Monday counter-example that exposed the difference. [is_after_ascension] + below is the corrected predicate: the day's own DATE compared against + {!Computus.ascension} for its own year, not [n]. + + FIXED (celebrant-rubrics-phase1, Bug 2): data/ef/lectionary.sexp's new + [ascension_week_entries] now answers these six ferial slugs directly at + step 2 (Own_slug), so [check_formulary_overrides]'s own [Preceding_sunday] + branch below never reaches them any more -- moved to a dedicated + [Own_slug] branch in that same function, which still asserts the Ordo's + override reads exactly [ascension_week_override], now as a genuine + confirmation that colitur's OWN citation matches (previously this + predicate only served to EXCLUDE the population from the general + Preceding_sunday mapping, because colitur had no correct answer to + compare). This constant and [is_after_ascension] itself are still load- + bearing for that confirmation -- kept, not deleted, the same "the + regression net survives its own fix" discipline + data/ef/expected-divergences-lms.sexp's own L6 note states for + [is_l6_rogation_colour]. *) +let ascension_week_override = "Mass of the Ascension" + +(* The exact six slugs data/ef/lectionary.sexp's own [ascension_week_entries] + (tools/bootstrap_lectionary.ml) now answers at step 2 -- gated on SLUG + IDENTITY, not merely [is_after_ascension date], because that date range + also covers "Dominica post Ascensionem" and the Vigil of Pentecost, both + genuinely [Own_slug] and both carrying their OWN, different citation, not + the Ascension's (caught live: an earlier, date-only version of this gate + wrongly flagged both as missing an Ordo override before this list was + added). *) +let ascension_week_slugs = + [ "ef-easter-6-friday"; "ef-easter-7-monday"; "ef-easter-7-tuesday"; "ef-easter-7-wednesday"; + "ef-easter-7-thursday"; "ef-easter-7-friday" + ] + +(* Bounded ABOVE by Pentecost, not merely "later than Ascension" -- a bare + lower bound is wrong for any date past Ascension in the SAME civil year + (every date from June to December satisfies "> Ascension", which a + first version of this predicate did and it manufactured 8 false + failures across the 2024-2025/2025-2026 windows, in July/November/ + December, caught immediately by re-running against those two + previously-clean windows). Task 6's own original population (Friday + after Ascension, then the following Monday/Tuesday) already showed the + window extends PAST the immediately-following Sunday, not merely up to + it, so Pentecost -- the next fixed liturgical anchor, Easter+49 -- is + the natural, provable upper bound: nothing in this stretch has its own + proper once Ascension's octave-like privilege takes over, and Pentecost + itself always does (RG 91 entry 3). *) +let is_after_ascension date = + let year = Date.year date in + Date.compare date (Computus.ascension year) > 0 && Date.compare date (Computus.pentecost year) < 0 + +type formulary_counts = { + fc_bad : string list; + fc_proper : int; + fc_common : int; + fc_preceding_sunday : int; + fc_ascension_week : int; +} + +let check_formulary_overrides ordo colitur = + let pairs = List.combine ordo colitur in + let proper = ref 0 and common = ref 0 and preceding_sunday = ref 0 and ascension_week = ref 0 in + let bad = ref [] in + List.iter + (fun ((o : ordo_row), (c : colitur_row)) -> + match c.c_formulary with + | Some { MF.via = MF.Proper; _ } -> + incr proper; + if o.formulary_override <> None then + bad := Printf.sprintf "%s: Proper day but Ordo shows override %s" o.date (Option.get o.formulary_override) + :: !bad + | Some { MF.via = MF.Common; _ } -> + incr common; + if o.formulary_override <> None then + bad := Printf.sprintf "%s: Common day but Ordo shows override %s" o.date (Option.get o.formulary_override) + :: !bad + | Some { MF.via = MF.Preceding_sunday; said } -> ( + incr preceding_sunday; + let slug = + match said with + | Some s -> Colitur_kernel.Slug.to_string s + | None -> Alcotest.failf "%s: Preceding_sunday day with said = None (should be impossible)" o.date + in + let ordo_says = Printf.sprintf "Mass of %s" in + let year = int_of_string (String.sub o.date 0 4) in + let date = match Date.of_iso8601 o.date with Ok d -> d | Error e -> Alcotest.failf "%s: %s" o.date e in + if is_after_ascension date then ( + match o.formulary_override with + | Some got when String.equal got ascension_week_override -> incr ascension_week + | Some got -> + bad := + Printf.sprintf "%s: colitur resumed %S (after Ascension), Ordo shows %S, not the adjudicated %S" + o.date slug got ascension_week_override + :: !bad + | None -> + bad := Printf.sprintf "%s: colitur resumed %S (after Ascension), Ordo shows no override" o.date slug :: !bad) + else + let expected = + match parse_sunday_slug slug with + | Some (word, n) -> expected_preceding_sunday_override ~season:c.c_season word n + | None -> expected_named_sunday_override slug ~year + in + match expected with + | Some expected -> ( + let expected_line = ordo_says expected in + match o.formulary_override with + | Some got when String.equal got expected_line -> () + | Some got -> bad := Printf.sprintf "%s: colitur resumed %S, Ordo says %S" o.date expected_line got :: !bad + | None -> bad := Printf.sprintf "%s: colitur resumed %S, Ordo shows no override" o.date expected_line :: !bad) + | None -> ( + match o.formulary_override with + | Some got when String.equal got ascension_week_override -> incr ascension_week + | Some got -> + bad := + Printf.sprintf "%s: unmapped (colitur resumed %S) and Ordo shows %S, not the adjudicated %S" o.date + slug got ascension_week_override + :: !bad + | None -> + bad := Printf.sprintf "%s: unmapped (colitur resumed %S) and Ordo shows no override" o.date slug :: !bad)) + | Some { MF.via = MF.Own_slug; said } -> ( + (* celebrant-rubrics-phase1, Bug 2 fix: the six Ascension-week + ferias moved from [Preceding_sunday] (the branch above, which + used to special-case them via [is_after_ascension]) to + [Own_slug] -- data/ef/lectionary.sexp's own + [ascension_week_entries] now answers at step 2, before step 3 + is ever reached. Checked HERE, not merely left to fall through + silently the way every OTHER [Own_slug] day already does + (RG 299's ordinary case, a real proper Mass, needs no Ordo + cross-check because nothing about it is adjudicated): this is + the one [Own_slug] population this suite has an OUTSIDE + witness for, and losing that check when the fix landed would + have been a silent regression net, not merely dead code -- the + Ordo's own override text must still read "Mass of the + Ascension" on exactly these days. *) + let slug = match said with Some s -> Colitur_kernel.Slug.to_string s | None -> "" in + if List.mem slug ascension_week_slugs then + match o.formulary_override with + | Some got when String.equal got ascension_week_override -> incr ascension_week + | Some got -> + bad := + Printf.sprintf "%s: colitur resolved %S via Own_slug (after Ascension), Ordo shows %S, not %S" + o.date slug got ascension_week_override + :: !bad + | None -> + bad := Printf.sprintf "%s: colitur resolved %S via Own_slug (after Ascension), Ordo shows no override" + o.date slug :: !bad) + | Some { MF.via = MF.Votive; _ } | None -> ()) + pairs; + { fc_bad = List.rev !bad; fc_proper = !proper; fc_common = !common; fc_preceding_sunday = !preceding_sunday; + fc_ascension_week = !ascension_week } + +(* ---------------------------------------------------------------------- *) +(* Preface (RG 482-499, {!Rite_ef.Rubrics_ef.preface}) -- Preface-witnesses *) +(* task (2026-08-23), extending tools/extract_lms_ordo.ml's new [praef] *) +(* column into a real comparison, the same shape as test_fiuv_ordo.ml's *) +(* own preface axis but with a genuinely DIFFERENT classification rule -- *) +(* see the fixture's own provenance header, finding 5, for the full *) +(* CHARACTERISATION FIRST account this discipline requires. *) +(* *) +(* THE KEY DIFFERENCE FROM FIUV: this Ordo prints OPTION LISTS ("Pr of X *) +(* or Pr of Y or Common Pr"), not a single value per day, and several of *) +(* the named options are NOT among the fourteen RG 484-497 enumerate *) +(* ("Martyrs", "All Saints and Patron Saints", "the Dedication of a *) +(* Church", "the Most Holy Sacrament", "St John the Baptist", "the *) +(* Angels" -- checked directly against docs/research/LT.txt lines *) +(* 3936-4020: no such clause exists there). Every raw value in this *) +(* corpus's own universal block that carries one of these extras also *) +(* carries a genuine RG-482 alternative alongside it (never as the row's *) +(* own and only option) -- so [classify_praef_options] parses the FULL *) +(* option set (splitting on the standalone token "or", never a substring *) +(* search: checked directly that no trailing descriptive prose in this *) +(* corpus's universal block ever uses "or" as an ordinary English *) +(* conjunction), drops any segment that does not name one of *) +(* {!Preface.t}'s fifteen values, and the comparison below checks colitur's *) +(* single computed answer is a MEMBER of what survives, not string *) +(* equality against whichever option prints first. *) +let has_prefix ~prefix s = + String.length s >= String.length prefix && String.sub s 0 (String.length prefix) = prefix + +(* Every prefix here was read directly off the three fixtures' own 47 + distinct universal-block [praef] values (measured, not guessed) -- + mirrors test_fiuv_ordo.ml's own [praef_prefixes] table in spirit, but + this publisher's own English vocabulary, not the FIUV Ordo's Latin. + None of these prefixes is a prefix of another (checked): "Pr of St + Joseph" and "Pr of St John the Baptist" are the one pair that shares an + opening ("Pr of St "), disambiguated by their very next word. *) +let praef_prefixes = + [ ("Common Pr", Preface.Common); + ("Pr of the Nativity", Preface.Nativity); + ("Pr of the Epiphany", Preface.Epiphany); + ("Pr of Lent", Preface.Lent); + ("Pr of the Holy Cross", Preface.Holy_cross); + ("Pr of Easter", Preface.Easter); + ("Pr of the Ascension", Preface.Ascension); + ("Pr of the Sacred Heart", Preface.Sacred_heart); + ("Pr of Our Lord Jesus Christ the King", Preface.Christ_the_king); + ("Pr of the Holy Spirit", Preface.Holy_spirit); + ("Pr of the Trinity", Preface.Trinity); + ("Pr of the BVM", Preface.Bvm); + ("Pr of St Joseph", Preface.St_joseph); + ("Pr of the Apostles", Preface.Apostles); + ("Pr of the Dead", Preface.Requiem) + (* Deliberately UNMAPPED, found live in this corpus's own universal + block (not merely in the excluded diocesan variants): "Pr of + Martyrs", "Pr of All Saints and Patron Saints", "Pr of the + Dedication of a Church", "Pr of the Most Holy Sacrament", "Pr of + St John the Baptist", "Pr of the Angels" -- see this section's own + header. A segment matching none of the fifteen prefixes above is + simply dropped from the parsed option set, never forced into a + guess. *) + ] + +let classify_praef_segment (s : string) : Preface.t option = + let rec go = function [] -> None | (prefix, p) :: rest -> if has_prefix ~prefix s then Some p else go rest in + go praef_prefixes + +(* Splits on the standalone token "or" (never a substring search -- see + this section's own header on why that is safe in this corpus), then + classifies each segment independently and keeps only the recognised + ones. *) +let classify_praef_options (raw : string) : Preface.t list = + let toks = String.split_on_char ' ' raw |> List.filter (fun t -> t <> "") in + let rec split_on_or acc cur = function + | [] -> List.rev (List.rev cur :: acc) + | "or" :: rest -> split_on_or (List.rev cur :: acc) [] rest + | t :: rest -> split_on_or acc (t :: cur) rest + in + let segments = split_on_or [] [] toks in + List.filter_map (fun seg -> classify_praef_segment (String.concat " " seg)) segments + +(* ---------------------------------------------------------------------- *) +(* [make_suite]: one edition's worth of tests, parameterised. Every count *) +(* below is a genuine per-edition PIN (measured once against real data, *) +(* not guessed), the same discipline every other golden/oracle fixture in *) +(* this suite already uses -- a change to any of them is a real finding, *) +(* not noise to silence. *) +(* ---------------------------------------------------------------------- *) + +(* No Str/regex (frozen deps) -- the same hand-rolled substring test every + other file in this codebase reaches for (rubrics_ef.ml's own + [contains_substring], precedence_ef.ml's [contains_substring]). Local to + this file, not shared, on the same "no common .mli to hang it from" + footing those other copies already document. *) +let contains_substring s ~needle = + let ls = String.length s and ln = String.length needle in + let rec at i = i + ln <= ls && (String.sub s i ln = needle || at (i + 1)) in + ln = 0 || at 0 + +let make_suite ~label ~fixture_path ~fixture_sha256 ~window_first ~window_last ~year_lo ~year_hi ~allow_list_path + ~expected_rows ~expected_bvm_votive ~expected_proper ~expected_common ~expected_preceding_sunday + ~expected_ascension_week ~expected_gloria_l5 ~expected_gloria_l6 = + let test_fixture_checksum () = + Alcotest.(check string) "fixture SHA-256 matches its provenance note" fixture_sha256 + (sha256_of_file fixture_path) + in + let test_dates_align () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + Alcotest.(check int) (Printf.sprintf "the Ordo fixture has %d rows (%s..%s)" expected_rows window_first window_last) + expected_rows (List.length ordo); + Alcotest.(check int) "colitur resolved the same number of days" (List.length ordo) (List.length colitur); + (match ordo with o :: _ -> Alcotest.(check string) "first date" window_first o.date | [] -> Alcotest.fail "empty"); + (match List.rev ordo with + | o :: _ -> Alcotest.(check string) "last date" window_last o.date + | [] -> Alcotest.fail "empty"); + let mismatched = + List.filter_map + (fun (o, c) -> if String.equal o.date c.c_date then None else Some (o.date, c.c_date)) + (List.combine ordo colitur) + in + Alcotest.(check (list (pair string string))) "no misaligned dates" [] mismatched + in + (* This window's own Good Friday(s) (Easter-2, RE-DERIVED here from + {!Computus.gregorian_easter} for every civil year the window touches, + never hardcoded) is the only day expected to carry no Ordo Creed + marker at all -- Good Friday has no Mass in the 1955-restored Holy + Week. Exactly one such date falls inside any one edition's ~13-month + window (its OTHER Easter, a year apart, falls outside it), but this + is computed, not assumed: a window that unexpectedly contained zero or + two would be a real finding this test would catch. *) + let window_good_fridays () = + let first_year = int_of_string (String.sub window_first 0 4) in + let last_year = int_of_string (String.sub window_last 0 4) in + let candidates = + List.concat_map + (fun y -> + let gf = Date.add_days (Computus.gregorian_easter y) (-2) in + [ Date.to_iso8601 gf ]) + (List.init (last_year - first_year + 1) (fun i -> first_year + i)) + in + List.filter (fun d -> String.compare d window_first >= 0 && String.compare d window_last <= 0) candidates + in + let test_creed_coverage () = + let ordo = ordo_rows fixture_path in + let no_creed = List.filter (fun o -> o.creed = None) ordo in + let expected = window_good_fridays () in + Alcotest.(check (list string)) "only this window's own Good Friday has no Ordo Creed marker" expected + (List.map (fun o -> o.date) no_creed) + in + let describe_creed_mismatch (o : ordo_row) (c : colitur_row) = + Printf.sprintf "%s %S: colitur creed=%b, Ordo creed=%b (formulary=%s)" o.date o.title c.c_creed + (Option.get o.creed) + (match c.c_formulary with + | Some { MF.said = Some s; _ } -> Colitur_kernel.Slug.to_string s + | Some { MF.said = None; via = MF.Votive } -> "votive (said unnamed in the data)" + | Some { MF.said = None; _ } -> "NONE (said, unexpectedly outside Votive)" + | None -> "NONE") + in + (* Which allow-list id, if any, explains a Creed mismatch on this date. + Date-keyed (not merely "any mismatch is fine") deliberately: an id + that stops firing, or fires on a NEW date it was never adjudicated + for, must be visible as a real change, not silently absorbed by a + loose "some entry explains something" check. Task 6's own version of + this function declared [by_id]/[explained_counts] but never actually + populated the latter (the mechanism this comment sits in) -- L1 was + already CLOSED by the time that task shipped, so it had nothing real + to explain and the gap went unexercised. L4 (Witnesses task, + 2026-08-22, 2023-2024-only) is the first live test of it. L3's own + "2024-02-24" branch (bissextile-shift task, 2026-08-22) is REMOVED, + not left dead: the fix makes that date's Creed match outright, so the + branch would never fire again, and a stale date->id mapping for a + now-closed entry is exactly the kind of thing this file's own + "must be visible as a real change" discipline (this comment's own + opening sentence) argues against leaving in place. *) + let allow_list_id_for_date d = if String.equal d "2023-12-24" then Some "L4" else None in + let test_creed_matches_or_is_explained () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let allow_list = load_allow_list allow_list_path in + let by_id = List.map (fun e -> (e.id, e)) allow_list in + let unexplained = ref [] in + let explained_counts = Hashtbl.create 8 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.creed with + | None -> () + | Some ocreed -> + if Bool.equal ocreed c.c_creed then () + else ( + match allow_list_id_for_date o.date with + | Some id -> Hashtbl.replace explained_counts id (1 + try Hashtbl.find explained_counts id with Not_found -> 0) + | None -> unexplained := describe_creed_mismatch o c :: !unexplained)) + ordo colitur; + Alcotest.(check (list string)) (Printf.sprintf "[%s] every Creed mismatch is named in the allow-list -- none unexplained" label) + [] (List.rev !unexplained); + Hashtbl.iter + (fun id n -> + match List.assoc_opt id by_id with + | None -> Alcotest.failf "allow-list entry %s used by the comparator but not declared in %s" id allow_list_path + | Some e -> + Alcotest.(check int) (Printf.sprintf "%s: expected_rows matches the actual count" id) e.expected_rows n) + explained_counts + in + (* ---- Gloria (RG 431-432, {!Rite_ef.Rubrics_ef.gloria}) -- Phase 2 of + this task. Same shape as the Creed comparison immediately above: + coverage (which dates carry no Ordo "Gl"/"No Gl" marker at all) is + checked separately from the value comparison, and both are + date-keyed against their own allow-list ids, never a loose "some + divergence is fine" check. *) + let test_gloria_coverage () = + let ordo = ordo_rows fixture_path in + let no_gloria = List.filter (fun o -> o.gloria = None) ordo in + let expected = window_good_fridays () in + Alcotest.(check (list string)) "only this window's own Good Friday has no Ordo Gloria marker" expected + (List.map (fun o -> o.date) no_gloria) + in + let describe_gloria_mismatch (o : ordo_row) (c : colitur_row) = + Printf.sprintf "%s %S: colitur gloria=%b, Ordo gloria=%b (rank=%s commemoration=%b formulary=%s)" o.date o.title + c.c_gloria (Option.get o.gloria) (V.rank_to_string c.c_rank) c.c_has_commemoration + (match c.c_formulary with + | Some { MF.said = Some s; _ } -> Colitur_kernel.Slug.to_string s + | Some { MF.said = None; via = MF.Votive } -> "votive (said unnamed in the data)" + | Some { MF.said = None; _ } -> "NONE (said, unexpectedly outside Votive)" + | None -> "NONE") + in + (* L5 is the one REAL, STRUCTURAL shape still open (see + data/ef/expected-divergences-lms.sexp's own L5 for the full + citation) -- not a fixed date list, a property of the day itself, + because it recurs every year the underlying condition holds, not on a + fixed calendar date the way L4 above does. Matched by PREDICATE, not + by date, for the same reason L2's own note gives for why it is + prose-only rather than wired through the shared [expected_rows] + mechanism: the count varies window to window (L5: 6/5/6), so a single + static count cannot check it, and [make_suite] threads the per-window + expected total directly (~expected_gloria_l5 below) instead. + + L6 is CLOSED (celebrant-rubrics-phase1, Bug 1 fix, this task): + {!Rite_ef.Temporal_ef.temporal}'s Rogation Monday/Tuesday branch no + longer hardcodes [Colour.Violet] -- see temporal_ef.ml's own citation + on that branch and data/ef/expected-divergences-lms.sexp's L6 entry + for the fix and its measured blast radius. [is_l6_rogation_colour] and + ~expected_gloria_l6 are kept, at 0 in every window, as the regression + net the same way L3's own bissextile fix keeps a predicate whose count + is now provably zero rather than deleting it. *) + let is_l5_lenten_commemoration (o : ordo_row) (c : colitur_row) = + (* NOT a Gloria defect (CORRECTED, l5-f3-readjudication task, + 2026-08-22 -- data/ef/expected-divergences-lms.sexp's own L5 has + the full account, including the RG 431(b)/n.302(b) hypothesis this + comment used to state as settled and RG 303(b)'s own "dici potest + tantum si occurrit dies liturgicus IV classis", which prohibits + 302(b) on exactly these THIRD-class privileged ferias). Every + instance is a privileged Lenten/Passiontide feria (Class3, violet + -- {!TE}'s own [ferial_rank], RG25) carrying exactly one + commemoration of an impeded Class3 saint, colitur reading + [gloria]=false (the ferial Mass, correctly, per the 1962 core) + where the Ordo reads [true] (the LMS Ordo follows the 2020 decree + Cum Sanctissima, colitur excludes it by binding design, CLAUDE.md + decision 2) -- an OCCURRENCE difference between two different, + both genuine, calendars, not a rule dispute. Predicate kept AS A + MATCHER (the 16-date population is unchanged); only the citation + explaining WHY it is allow-listed was wrong. *) + (not c.c_gloria) && Option.value o.gloria ~default:false && c.c_has_commemoration && c.c_rank = V.Class3 + in + let is_l6_rogation_colour (o : ordo_row) (c : colitur_row) = + (* CLOSED (celebrant-rubrics-phase1, Bug 1 fix). Was root-caused to a + DIFFERENT, pre-existing bug this comparison merely surfaced -- + {!Rite_ef.Temporal_ef.temporal}'s own Rogation Monday/Tuesday branch + used to hardcode [Colour.Violet] with no RG citation at all, where + the Ordo shows this exact date "FERIA IV Cl W" (white, matching + Paschaltide's own [season_colour] and RG88's "nihil fit in Officio" + -- the Office, hence its colour, is unchanged by the Rogation, only + the Mass TEXT is proper) -- so [gloria]'s own 432(b) violet guard + wrongly fired. Now fixed at the source (temporal_ef.ml); this + predicate and its own ~expected_gloria_l6 count (0 in every window) + are kept as the regression net, not deleted. *) + (not c.c_gloria) && Option.value o.gloria ~default:false + && (contains_substring c.c_slug ~needle:"rogation-monday" || contains_substring c.c_slug ~needle:"rogation-tuesday") + in + let test_gloria_matches_or_is_explained ~expected_gloria_l5 ~expected_gloria_l6 () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let unexplained = ref [] in + let l5_count = ref 0 and l6_count = ref 0 in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.gloria with + | None -> () + | Some ogloria -> + if Bool.equal ogloria c.c_gloria then () + else if is_l5_lenten_commemoration o c then incr l5_count + else if is_l6_rogation_colour o c then incr l6_count + else unexplained := describe_gloria_mismatch o c :: !unexplained) + ordo colitur; + Alcotest.(check (list string)) (Printf.sprintf "[%s] every Gloria mismatch is named in the allow-list -- none unexplained" label) + [] (List.rev !unexplained); + Alcotest.(check int) (Printf.sprintf "[%s] L5 (Lenten privileged feria + commemoration) count" label) + expected_gloria_l5 !l5_count; + Alcotest.(check int) (Printf.sprintf "[%s] L6 (Rogation Monday/Tuesday colour bug) count" label) expected_gloria_l6 + !l6_count + in + let test_bvm_seasonal_selection () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let votive_pairs = + List.filter_map + (fun (o, c) -> match c.c_formulary with Some { MF.via = MF.Votive; _ } -> Some (o, c) | _ -> None) + (List.combine ordo colitur) + in + Alcotest.(check int) (Printf.sprintf "%d BVM-Saturday (Votive) days fall inside this window" expected_bvm_votive) + expected_bvm_votive (List.length votive_pairs); + let mismatches = + List.filter_map + (fun (o, c) -> + let expected = expected_bvm_numeral c.c_season ~month:(int_of_string (String.sub c.c_date 5 2)) + ~day:(int_of_string (String.sub c.c_date 8 2)) in + match o.bvm_numeral with + | Some got when String.equal got expected -> None + | Some got -> Some (Printf.sprintf "%s: Ordo says %s, expected %s (season-derived)" o.date got expected) + | None -> + (* One SOURCE-TEXT anomaly, found extending this suite to + 2023-2024: 2024-02-03 is the ONLY BVM-Saturday day in the + 2023-2024 fixture (of 12) whose Ordo entry carries no + roman-numeral "<N> Mass of BVM" line at all. Verified + directly against the raw pdftotext dump (not inferred): + every OTHER BVM-Saturday day in this edition prints "Sat + <n> CELEBRATION of the BVM IV Cl W" immediately followed + by its own "<N> Mass of BVM" line; this one date's block + goes straight from the title line to "(Blessing of + throats in honour of St Blaise may be given on this + day)" -- the numeral line the Ordo's own layout convention + would otherwise print is simply MISSING from the printed + text, a publisher-side omission this session cannot + correct, not a colitur defect (colitur's own side is + independently right here: St Blaise is scan-verified + "Com." -- a bare commemoration, not a feast -- in the + calendarium itself, docs/research/LT.txt:4978, so RG 91's + table has no row for him and the BVM-Saturday office + correctly wins the day outright, exactly as colitur + computes). Excluded by name, not silently: a future + change to this population (a different date, or a SECOND + gap) would still be caught below. *) + if String.equal fixture_path "fixtures/lms-ordo-2023-2024.sexp" && String.equal o.date "2024-02-03" then + None + else Some (Printf.sprintf "%s: colitur says Votive but the Ordo shows no BVM numeral" o.date)) + votive_pairs + in + Alcotest.(check (list string)) "every BVM-Saturday numeral matches its season -- none unexplained" [] mismatches + in + let test_bvm_numeral_implies_votive () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let mismatches = + List.filter_map + (fun (o, c) -> + match (o.bvm_numeral, c.c_formulary) with + | Some n, Some { MF.via = MF.Votive; _ } -> ignore n; None + | Some n, other -> + Some + (Printf.sprintf "%s: Ordo shows %S Mass of BVM but colitur's via is %s" o.date n + (match other with Some f -> MF.source_to_string f.MF.via | None -> "NONE")) + | None, _ -> None) + (List.combine ordo colitur) + in + Alcotest.(check (list string)) "every Ordo BVM numeral day is a colitur Votive day" [] mismatches + in + let test_formulary_override_matches () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let r = check_formulary_overrides ordo colitur in + Alcotest.(check (list string)) "every formulary-override mismatch is explained -- none unexplained" [] r.fc_bad; + Alcotest.(check int) (Printf.sprintf "%d Proper days in the window" expected_proper) expected_proper r.fc_proper; + Alcotest.(check int) (Printf.sprintf "%d Common days in the window" expected_common) expected_common r.fc_common; + Alcotest.(check int) (Printf.sprintf "%d Preceding_sunday days in the window" expected_preceding_sunday) + expected_preceding_sunday r.fc_preceding_sunday; + Alcotest.(check int) + (Printf.sprintf "%d Ascension-week days resolve via Own_slug and match the Ordo's own override, no more, no fewer" + expected_ascension_week) + expected_ascension_week r.fc_ascension_week + in + let test_praef_coverage () = + let ordo = ordo_rows fixture_path in + let no_praef = List.filter (fun o -> o.praef = None) ordo in + let expected = window_good_fridays () in + Alcotest.(check (list string)) "only this window's own Good Friday has no Ordo Pr-of/Common-Pr marker" expected + (List.map (fun o -> o.date) no_praef) + in + let describe_praef_mismatch (o : ordo_row) (c : colitur_row) (options : Preface.t list) = + Printf.sprintf "%s %S: colitur preface=%s, Ordo praef=%S (parsed options: %s)" o.date o.title + (match c.c_preface with Some p -> Preface.to_string p | None -> "NONE") + (Option.get o.praef) + (String.concat ", " (List.map Preface.to_string options)) + in + let test_praef_matches_or_is_explained () = + let ordo = ordo_rows fixture_path in + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let unexplained = ref [] in + let unclassifiable = ref [] in + List.iter2 + (fun (o : ordo_row) (c : colitur_row) -> + if not (String.equal o.date c.c_date) then Alcotest.failf "misaligned: ordo %s vs colitur %s" o.date c.c_date; + match o.praef with + | None -> () + | Some raw -> ( + let options = classify_praef_options raw in + match options with + | [] -> unclassifiable := o.date :: !unclassifiable + | opts -> ( + match c.c_preface with + | None -> + unexplained := + Printf.sprintf "%s %S: colitur preface=NONE (unexpected outside Good Friday), Ordo praef=%S" + o.date o.title raw + :: !unexplained + | Some p -> if List.mem p opts then () else unexplained := describe_praef_mismatch o c opts :: !unexplained))) + ordo colitur; + Alcotest.(check (list string)) + (Printf.sprintf "[%s] every Pr-of/Common-Pr mismatch is named in the allow-list -- none unexplained" label) + [] (List.rev !unexplained); + Alcotest.(check (list string)) + (Printf.sprintf "[%s] every option list has at least one recognised alternative -- none dropped entirely" label) + [] (List.rev !unclassifiable) + in + let test_via_distribution_totals () = + let colitur = colitur_rows ~year_lo ~year_hi ~window_first ~window_last in + let via_name c = match c.c_formulary with None -> "none" | Some f -> MF.source_to_string f.MF.via in + let counts = Hashtbl.create 8 in + List.iter + (fun c -> Hashtbl.replace counts (via_name c) (1 + try Hashtbl.find counts (via_name c) with Not_found -> 0)) + colitur; + let total = Hashtbl.fold (fun _ n acc -> acc + n) counts 0 in + Alcotest.(check int) "every via bucket sums to the full window" expected_rows total + in + ( label, + [ Alcotest.test_case "fixture SHA-256 matches its provenance note" `Quick test_fixture_checksum; + Alcotest.test_case "streams are N rows each, dates aligned 1:1" `Quick test_dates_align; + Alcotest.test_case "only this window's own Good Friday has no Ordo Creed marker" `Quick test_creed_coverage; + Alcotest.test_case "every Creed difference is named in the cited allow-list -- none unexplained" `Quick + test_creed_matches_or_is_explained; + Alcotest.test_case "only this window's own Good Friday has no Ordo Gloria marker" `Quick + test_gloria_coverage; + Alcotest.test_case "every Gloria difference is named in the cited allow-list -- none unexplained" `Quick + (test_gloria_matches_or_is_explained ~expected_gloria_l5 ~expected_gloria_l6); + Alcotest.test_case "every BVM-Saturday numeral matches its season" `Quick test_bvm_seasonal_selection; + Alcotest.test_case "every Ordo BVM numeral day is a colitur Votive day" `Quick + test_bvm_numeral_implies_votive; + Alcotest.test_case "formulary override STRING matches on Proper/Common/Preceding_sunday days" `Quick + test_formulary_override_matches; + Alcotest.test_case "the via distribution sums to the full window" `Quick test_via_distribution_totals; + Alcotest.test_case "only this window's own Good Friday has no Ordo Pr-of/Common-Pr marker" `Quick + test_praef_coverage; + Alcotest.test_case "every Pr-of/Common-Pr mismatch is named in the allow-list -- none unexplained" `Quick + test_praef_matches_or_is_explained + ] ) + +let allow_list_path = "../data/ef/expected-divergences-lms.sexp" + +(* Guards against a stale allow-list entry (declared in the sexp file, but + the OCaml-side [allow_list_id_for_date] predicate above no longer maps + any date to it, or never did) -- the per-window suites above only prove + an id that DOES fire has the right count; nothing in them can notice an + id that never fires in ANY of the three windows, since each suite only + ever looks at its own explained_counts. Fixed to the two ids this task + added (L3, L4) -- L1 is CLOSED/removed and L2 is deliberately prose-only + (see the sexp file's own header on why), so neither is expected here. *) +(* L3 CLOSED (bissextile-shift task, 2026-08-22): removed from the active + sexp record set -- see its own now-prose closure note in + data/ef/expected-divergences-lms.sexp for the fix and the measured + blast radius. Only L4 remains active. *) +let test_allow_list_ids_are_exactly_l4 () = + let ids = List.sort String.compare (List.map (fun e -> e.id) (load_allow_list allow_list_path)) in + Alcotest.(check (list string)) "the LMS allow-list declares exactly L4" [ "L4" ] ids + +let suite_allow_list = ("lms-ordo-allow-list", [ Alcotest.test_case "declares exactly L4" `Quick test_allow_list_ids_are_exactly_l4 ]) + +let suite_2023_2024 = + make_suite ~label:"lms-ordo-2023-2024" ~fixture_path:"fixtures/lms-ordo-2023-2024.sexp" + ~fixture_sha256:"631aedad5a749c814efcffbf1dfd0970181552a7b8985f6f74c5cfa4bf83baf5" ~window_first:"2023-12-01" + ~window_last:"2024-12-31" ~year_lo:2022 ~year_hi:2025 ~allow_list_path ~expected_rows:397 + (* expected_proper 182 -> 181 (bissextile-shift task, 2026-08-22): 24 + February 2024, previously Matthias's own Proper Mass, is now the + Ember Saturday of Lent's own temporal proper -- Own_slug-sourced, not + Proper, so it leaves this bucket's population rather than merely + changing which slug's proper it is (see this file's own header on why + Own_slug is excluded). Matthias himself moves to 25 February, an + I-class Sunday that admits him not even as a commemoration (RG16(a)), + so his own Mass is not said anywhere in this window any more. *) + (* expected_preceding_sunday 61 -> 60 (celebrant-rubrics-phase1, Bug 2 + fix, 2026-08-22): the window's own single Ascension-week day + (2024-05-06 was BEFORE Ascension that year and never counted here in + the first place -- see [ascension_week_override]'s own citation; the + real Ascension-week day this window carries is elsewhere in May) + now resolves via Own_slug (step 2, data/ef/lectionary.sexp's new + [ascension_week_entries]), not Preceding_sunday -- it leaves this + bucket's population the same way a Proper day already does, while + expected_ascension_week itself is UNCHANGED (1): the same day is + still counted, just via check_formulary_overrides' own new + Own_slug branch instead of its Preceding_sunday one. *) + ~expected_bvm_votive:12 ~expected_proper:181 ~expected_common:2 ~expected_preceding_sunday:60 + ~expected_ascension_week:1 ~expected_gloria_l5:5 ~expected_gloria_l6:0 + +let suite_2024_2025 = + make_suite ~label:"lms-ordo-2024-2025" ~fixture_path:"fixtures/lms-ordo-2024-2025.sexp" + ~fixture_sha256:"a2b549f10dfbebfa5f7df7dea74b0e5352f5abbf5e2ce33ef681a9eb8eb116e6" ~window_first:"2024-11-27" + ~window_last:"2025-12-31" ~year_lo:2023 ~year_hi:2026 ~allow_list_path ~expected_rows:400 + (* expected_preceding_sunday 66 -> 63 (celebrant-rubrics-phase1, Bug 2 + fix): this window's own three Ascension-week days move from + Preceding_sunday to Own_slug, the same reasoning as the 2023-2024 + window's own note above; expected_ascension_week stays 3. *) + ~expected_bvm_votive:14 ~expected_proper:179 ~expected_common:2 ~expected_preceding_sunday:63 + ~expected_ascension_week:3 ~expected_gloria_l5:5 ~expected_gloria_l6:0 + +let suite_2025_2026 = + make_suite ~label:"lms-ordo-2025-2026" ~fixture_path:"fixtures/lms-ordo-2025-2026.sexp" + ~fixture_sha256:"8595ffebfc50b7a165643c172f9ba542871dd1d1e45f8c85a21b104da689535f" ~window_first:"2025-11-28" + ~window_last:"2026-12-31" ~year_lo:2024 ~year_hi:2027 ~allow_list_path ~expected_rows:399 + (* expected_preceding_sunday 68 -> 66 (celebrant-rubrics-phase1, Bug 2 + fix): this window's own two Ascension-week days move from + Preceding_sunday to Own_slug, the same reasoning as the 2023-2024 + window's own note above; expected_ascension_week stays 2. *) + ~expected_bvm_votive:13 ~expected_proper:174 ~expected_common:2 ~expected_preceding_sunday:66 + ~expected_ascension_week:2 ~expected_gloria_l5:6 ~expected_gloria_l6:0 diff --git a/test/test_mass_formulary.ml b/test/test_mass_formulary.ml new file mode 100644 index 0000000..1316e47 --- /dev/null +++ b/test/test_mass_formulary.ml @@ -0,0 +1,41 @@ +module MF = Colitur_kernel.Mass_formulary +module Slug = Colitur_kernel.Slug + +let slug s = Slug.of_string_exn s + +let test_round_trips_through_sexp () = + let f = { MF.said = Some (slug "ef-time-after-pentecost-sunday-9"); via = MF.Preceding_sunday } in + let f' = MF.t_of_sexp (MF.sexp_of_t f) in + Alcotest.(check (option string)) "slug survives" + (Option.map Slug.to_string f.MF.said) (Option.map Slug.to_string f'.MF.said); + Alcotest.(check bool) "source survives" true (f.MF.via = f'.MF.via) + +(* [said] is [None] exactly for {!MF.Votive} -- see the .mli's own citation. + Round-tripped separately so the [None] case has its own witness, not only + inferred from the [Some] case above. *) +let test_none_said_round_trips_through_sexp () = + let f = { MF.said = None; via = MF.Votive } in + let f' = MF.t_of_sexp (MF.sexp_of_t f) in + Alcotest.(check bool) "said stays None" true (f'.MF.said = None); + Alcotest.(check bool) "source survives" true (f.MF.via = f'.MF.via) + +(* [to_string] is what an ordo line shows. It names the SOURCE, not the slug, + because the slug is a key and the reader wants "of the preceding Sunday". *) +let test_to_string_names_the_source () = + let cases = + [ (MF.Proper, "proper"); (MF.Own_slug, "own"); (MF.Preceding_sunday, "preceding-sunday"); + (MF.Common, "common"); (MF.Votive, "votive") ] + in + List.iter + (fun (via, expected) -> + Alcotest.(check string) expected expected + (MF.source_to_string via)) + cases + +let suite = + ( "Mass_formulary", + [ Alcotest.test_case "sexp round-trips" `Quick test_round_trips_through_sexp; + Alcotest.test_case "sexp round-trips, said = None (Votive)" `Quick + test_none_said_round_trips_through_sexp; + Alcotest.test_case "source_to_string names each source" `Quick + test_to_string_names_the_source ] ) diff --git a/test/test_oracle.ml b/test/test_oracle.ml index f1d1a89..01938e1 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -1381,6 +1381,33 @@ let m26_dates = citation fields are not, discovered by this task). *) let m27_dates = [ "2026-12-25"; "2027-12-25" ] +(* M31 (celebrant-rubrics-phase1, Bug 2, 2026-08-22) -- the six ferias + between the Ascension and the Friday before the Vigil of Pentecost that + repeat the Ascension's own Mass by an explicit marginal rubric in the + Proprium de Tempore (data/ef/lectionary.sexp's own [ascension_week_ + entries], full citation there and in this file's sibling + data/ef/expected-divergences.sexp's own C41). Only three of the six + civil dates this window's own [c_date] range can reach are actually + unoccupied in 2026-2027: 2026-05-21, 2026-05-22 and 2027-05-14 (the + other three fall to a real sanctoral feast both engines already agree + on). missalemeum -- Divinum Officium's own lineage, the SAME lineage + lectio inherited this defect from before colitur's own bootstrap -- + still walks these ferias back to the preceding Sunday's Mass, the + pre-fix answer colitur itself used to give; [Observed_identity_ + unresolved] fires alongside because none of the three is a SANCTORAL- + origin day (the mapping this whole file's own header describes cannot + name a TEMPORAL office's title either way, unrelated to this cause). *) +let m31_dates = [ "2026-05-21"; "2026-05-22"; "2027-05-14" ] + +(* The exact six slugs data/ef/lectionary.sexp's own [ascension_week_entries] + answers -- reused by [classify_2038]/[classify_2035] below, which key on + slug identity rather than a date list (those two live windows are not + scoped the way the 2026-2027 fixture is). *) +let ascension_week_slugs = + [ "ef-easter-6-friday"; "ef-easter-7-monday"; "ef-easter-7-tuesday"; "ef-easter-7-wednesday"; + "ef-easter-7-thursday"; "ef-easter-7-friday" + ] + (* The oracle's own row went unused when M2 -- its one reader, via [o.o_title] -- was closed/removed (see the comment above [m1_dates]), and was kept as a named, typed parameter rather than dropped from the @@ -1512,6 +1539,8 @@ let layer_m_reason (c : colitur_row) (o : oracle_row) diffs = [ Rank; Colour_f; Comm_presence; Comm_count; Observed_identity_mismatch; Comm_identity_unresolved; First_mismatch; Gospel_mismatch ] then Some "M30" + else if List.mem c.c_date m31_dates && subset diffs [ Observed_identity_unresolved; First_mismatch; Gospel_mismatch ] + then Some "M31" else None (* ---------------------------------------------------------------------- *) @@ -1992,6 +2021,16 @@ let classify_2038 (c : colitur_row) (o : oracle_row) diffs = List.mem c.c_date [ "2035-08-09"; "2035-08-14"; "2038-08-09"; "2038-08-14" ] && diffs = [ Colour_f ] then Some "VIGIL-COLOUR-RG128 (M29, colitur; see C37)" + (* The Ascension-repeat rubric (celebrant-rubrics-phase1, Bug 2; see M31 + in this file's own 2026-2027 [layer_m_reason] and C41 in + data/ef/expected-divergences.sexp for the full citation). 2038 carries + three unoccupied instances the 2026-2027 window did not (2038-06-07/ + 08/09, all week-7 weekdays); 2035 carries one (2035-05-08). Gated on + colitur's own slug rather than on the date list this window's sibling + windows use, the same style [m21_2038_slugs] already establishes for + a live-window slug-keyed class. *) + else if List.mem c.c_observed_slug ascension_week_slugs && diffs = [ First_mismatch; Gospel_mismatch ] then + Some "ASCENSION-WEEK-REPEAT (M31, colitur; register, Bug 2)" else None (* COMMEMORATIONS join the live-window comparison (2026-08-18). @@ -2129,7 +2168,13 @@ let test_2038_class_counts () = ("MISSAL-TWO-PART-CITATION (register 6.9)", 1); ("COMM-IDENTITY-UNRESOLVED (temporal-origin, no English name -- M15's limit)", 2); ("PERPETUA-COMMON (register 6.8)", 1); - ("PETER-COMPANION-ABSENT-UPSTREAM (M19)", 1) + ("PETER-COMPANION-ABSENT-UPSTREAM (M19)", 1); + (* celebrant-rubrics-phase1, Bug 2: 2038-06-07/08/09 (the Monday, + Tuesday and Wednesday of the week after the Sunday after the + Ascension) are unoccupied that year, all three landing on the + Ascension-repeat rubric -- see M31 (2026-2027 window) and C41 + (data/ef/expected-divergences.sexp) for the full citation. *) + ("ASCENSION-WEEK-REPEAT (M31, colitur; register, Bug 2)", 3) ] |> List.sort compare in diff --git a/test/test_precedence.ml b/test/test_precedence.ml index acc89fc..54ab3f9 100644 --- a/test/test_precedence.ml +++ b/test/test_precedence.ml @@ -98,6 +98,49 @@ let test_temporal_only_day () = Alcotest.(check int) "nothing deferred" 0 (List.length r.P.deferred); Alcotest.(check int) "nothing omitted" 0 (List.length r.P.omitted) +(* RG 111(a): sung_mass_commemorations -- see precedence.mli's own citation. + Pure function, no {!resolve} needed: exercised directly against + hand-built Low-Mass admitted lists, the same shape {!P.resolve} would + produce, rather than through a full resolution. *) +let sung_test_cand rank slug = cand ~rank slug + +let test_sung_mass_no_privileged () = + let low_mass = [ (sung_test_cand Lo "a", P.Ordinary); (sung_test_cand Lo "b", P.Ordinary) ] in + Alcotest.(check (list string)) "no privileged commemoration -> sung Mass keeps none" [] + (List.map (fun (c, _) -> slug_of c) (P.sung_mass_commemorations low_mass)) + +let test_sung_mass_one_privileged () = + let low_mass = + [ (sung_test_cand Lo "ordinary-one", P.Ordinary); (sung_test_cand Hi "privileged-one", P.Privileged) ] + in + Alcotest.(check (list string)) "the ordinary commemoration is dropped, the privileged one kept" + [ "privileged-one" ] + (List.map (fun (c, _) -> slug_of c) (P.sung_mass_commemorations low_mass)) + +let test_sung_mass_privileged_first_already () = + let low_mass = + [ (sung_test_cand Hi "privileged-one", P.Privileged); (sung_test_cand Lo "ordinary-one", P.Ordinary) ] + in + Alcotest.(check (list string)) "a privileged commemoration already first is kept alone" [ "privileged-one" ] + (List.map (fun (c, _) -> slug_of c) (P.sung_mass_commemorations low_mass)) + +let test_sung_mass_empty_low_mass_set () = + Alcotest.(check (list string)) "an empty Low-Mass set stays empty at Sung Mass" [] + (List.map (fun (c, _) -> slug_of c) (P.sung_mass_commemorations [])) + +(* If two privileged commemorations were ever admitted together (not known + to occur on any shipped rite's data -- precedence.mli's own citation), + [sung_mass_commemorations] keeps only the FIRST -- input order is + already RG 113 precedence order, so this is "the highest-precedence + privileged entry survives", not an arbitrary truncation. *) +let test_sung_mass_two_privileged_keeps_first () = + let low_mass = + [ (sung_test_cand Hi "first-privileged", P.Privileged); (sung_test_cand Hi "second-privileged", P.Privileged) ] + in + Alcotest.(check (list string)) "only the first (higher-precedence) privileged commemoration survives" + [ "first-privileged" ] + (List.map (fun (c, _) -> slug_of c) (P.sung_mass_commemorations low_mass)) + let suite = ( "Precedence", [ Alcotest.test_case "highest band wins" `Quick test_highest_band_wins; @@ -107,4 +150,14 @@ let suite = test_commemoration_only_never_observed; Alcotest.test_case "nothing silently lost" `Quick test_nothing_silently_lost; Alcotest.test_case "order independent" `Quick test_order_independent; - Alcotest.test_case "temporal-only day" `Quick test_temporal_only_day ] ) + Alcotest.test_case "temporal-only day" `Quick test_temporal_only_day; + Alcotest.test_case "RG 111(a): sung Mass, no privileged commemoration" `Quick + test_sung_mass_no_privileged; + Alcotest.test_case "RG 111(a): sung Mass keeps the one privileged commemoration" `Quick + test_sung_mass_one_privileged; + Alcotest.test_case "RG 111(a): sung Mass, privileged already first" `Quick + test_sung_mass_privileged_first_already; + Alcotest.test_case "RG 111(a): sung Mass, empty Low-Mass set" `Quick + test_sung_mass_empty_low_mass_set; + Alcotest.test_case "RG 111(a): sung Mass keeps only the first of two privileged" `Quick + test_sung_mass_two_privileged_keeps_first ] ) diff --git a/test/test_rubrics_ef.ml b/test/test_rubrics_ef.ml new file mode 100644 index 0000000..77654c0 --- /dev/null +++ b/test/test_rubrics_ef.ml @@ -0,0 +1,1312 @@ +(* RG 475-476, the Creed -- see lib/rites/rite_ef/rubrics_ef.ml for the + rubric quoted in full and every branch's own citation. + + One end-to-end test per clause of 475, plus a 476 negative, resolved + against REAL calendar dates through the shipped sanctoral data (the same + pipeline `colitur day`/`colitur rubrics` use) -- every expected value + below was derived from the rubric's own text and checked against + `colitur day <year>`'s real output (slug/rank/subject/weekday) BEFORE + this module existed, never read off [Rubrics_ef.creed]'s own answer. + Two synthetic unit tests isolate Trap One (RG 475(a) reads [temporal], + never [observed]) directly, without depending on finding a real-calendar + coincidence. + + One further test (celebrant-rubrics-phase1 review, finding 1) is + different in kind from the rest: not an end-to-end [creed] check + against a single real date, but a direct sweep of {!Rite_ef.Temporal_ef} + output across a century, asserting the unstated invariant [creed]'s own + RG 24/25 ferial branches rely on rather than leaving it asserted only + in prose -- see its own header comment for the full account. *) + +module Cal = Colitur_kernel.Calendar +module LD = Colitur_kernel.Liturgical_day +module Date = Colitur_kernel.Date +module Cel = Colitur_kernel.Celebration +module Colour = Colitur_kernel.Colour +module Subject = Colitur_kernel.Subject +module Slug = Colitur_kernel.Slug +module Temporal = Colitur_kernel.Temporal +module Computus = Colitur_kernel.Computus +module V = Rite_ef.Vocab_ef +module RE = Rite_ef.Rubrics_ef +module TE = Rite_ef.Temporal_ef + +let mk y m d = match Date.make ~year:y ~month:m ~day:d with Ok t -> t | Error e -> failwith e + +(* Loaded once, module-level: every test below is a lookup against the same + shipped calendar, and {!Cal.day} recomputes its whole liturgical year on + every call (calendar.mli's own documented cost), so at minimum the layer + itself should not be reloaded and re-merged per test case. *) +let layer = + match Test_support.load_ef_layer () with Ok l -> l | Error e -> Alcotest.failf "%s" e + +let ctx = Test_support.ef_context () + +let creed_on y m d = (Cal.day ctx layer (mk y m d)).LD.creed + +let check name y m d expected = Alcotest.(check bool) name expected (creed_on y m d) + +(* ------------------------------------------------------------------------ *) +(* Breviary 237-238 (Te Deum) and RG 431-432 (Gloria) -- Phase 2 of the *) +(* celebrant-rubrics-phase1 design. See lib/rites/rite_ef/rubrics_ef.ml for *) +(* both rubrics quoted in full and every branch's own citation. One *) +(* end-to-end test per clause, resolved against REAL calendar dates through *) +(* the shipped data -- every expected value below was read off *) +(* `colitur rubrics <year>`'s real output BEFORE being pinned here, the *) +(* same discipline the Creed tests above already establish. *) + +let day_on y m d = Cal.day ctx layer (mk y m d) +let gloria_on y m d = (day_on y m d).LD.gloria +let te_deum_on y m d = RE.te_deum ~temporal:(day_on y m d).LD.temporal ~observed:(day_on y m d).LD.observed + ~date:(mk y m d) + +let check_gloria name y m d expected = Alcotest.(check bool) name expected (gloria_on y m d) +let check_te_deum name y m d expected = Alcotest.(check bool) name expected (te_deum_on y m d) + +(* ---- RG 475(a): "in qualibet dominica, etsi eius Officium alicui festo + locum cedat" ---- *) + +let test_475a_ordinary_sunday () = + (* 2026-01-25: an ordinary Time-after-Epiphany Sunday, Class2, green, + "Dominica III post Epiphaniam" -- confirmed via `colitur day 2026`, + no other clause of 475 could apply (Class2, subject Temporal, no + octave, no apostle/vigil slug), so [true] here can only come from + 475(a) itself. *) + check "475(a): an ordinary Sunday" 2026 1 25 true + +(* Trap One, isolated directly: RG 475(a)'s own "ETSI EIUS OFFICIUM ALICUI + FESTO LOCUM CEDAT" -- even when a feast has displaced the Sunday's own + office, the Creed is still said. [observed] below is deliberately shaped + so that NONE of 475(b)/(c)/(e) can produce [true] on their own (Class3, + subject Saint, a slug on no list this module knows); the only way + [creed] can return [true] is by reading [temporal]'s own [weekday], + never [observed]. The synthetic [date] (an ordinary July day, itself a + Wednesday in 2026) is chosen so nothing about the DATE itself suggests + a Sunday either -- proving the function reads [temporal.weekday], not + [Date.weekday date]. *) +let impeded_observed = + Cel.make ~slug:(Slug.of_string_exn "some-impeding-feast-of-the-lord") ~rank:V.Class3 + ~status:Cel.Feast ~colour:Colour.Red ~subject:Subject.Saint ~layer:"synthetic" () + +let synthetic_temporal ~weekday : (V.season, V.rank) Temporal.t = + { Temporal.season = V.Time_after_pentecost; week = Some 1; weekday; office = impeded_observed } + +let test_475a_reads_temporal_not_observed () = + Alcotest.(check bool) "Sunday-shaped [temporal] overrides a non-Sunday-shaped [observed]" true + (RE.creed ~temporal:(synthetic_temporal ~weekday:Date.Sun) ~observed:impeded_observed + ~date:(mk 2026 7 1)); + Alcotest.(check bool) "same [observed], non-Sunday [temporal]: false" false + (RE.creed ~temporal:(synthetic_temporal ~weekday:Date.Wed) ~observed:impeded_observed + ~date:(mk 2026 7 1)) + +(* ---- RG 475(b): "in festis I classis" ---- *) + +let test_475b_class1_feast () = + (* 2026-08-15: the Assumption, Class1. *) + check "475(b): a I-class feast" 2026 8 15 true + +(* ---- RG 475(c): "in festis II classis Domini et B. Mariae Virg." ---- *) + +let test_475c_lord () = + (* 2026-09-14: Exaltation of the Holy Cross, Class2, subject Lord. *) + check "475(c): a II-class feast of the Lord" 2026 9 14 true + +let test_475c_bvm_via_marian_slugs () = + (* 2026-08-22: Immaculate Heart of Mary, Class2 -- ships [subject = + Saint] in data/ef/sanctoral.sexp (confirmed by grep), so this can only + come out [true] via {!Rite_ef.Precedence_ef.marian_slugs}, not via + [subject = Bvm]. Also carries a real commemoration + (+sts-timothy-hippolytus-and-symphorianus-martyrs), a live instance of + 476(e): the commemoration plays no part in this answer. *) + check "475(c): a II-class BVM feast (via marian_slugs, subject=Saint in the data)" 2026 8 22 true + +(* ---- RG 475(d): "per octavas Nativitatis Domini, Paschatis et + Pentecostes, etiam in festis occurrentibus et in Missis votivis" ---- *) + +let test_475d_octave_even_occurring_feast () = + (* 2026-12-26: St Stephen, Class2, "S. Stephani Protomartyris" -- a real + saint's feast OCCURRING within the Octave of the Nativity (RG 67's own + "Com. octavae Nativitatis", carried as +ef-nativity-octave-day-2 in + colitur's own commemoration). RG 475(d)'s own "etiam in festis + occurrentibus" is written for exactly this shape: the Creed is said + regardless. (This is the one place this suite deliberately diverges + from the task brief's own worked example, which expected [false] here + -- the brief mis-cited 26 December as 476(b)'s "plain II-class feast" + case, missing that RG 475(d) explicitly overrides 476(b) inside the + Nativity octave; see the task report.) *) + check "475(d): a saint's feast occurring within the Nativity octave" 2026 12 26 true + +let test_475d_octave_day_boundary () = + (* 2026-01-01: the Octave Day of the Nativity itself (Circumcision), + Class1 -- also [true] via 475(b) alone, kept as a boundary check that + 1 January is correctly included in the 8-day window. *) + check "475(d): 1 January, the Octave Day of the Nativity" 2026 1 1 true + +(* ---- RG 475(e): "in festis nataliciis Apostolorum et Evangelistarum, + necnon in festis Cathedrae S. Petri et S. Barnabae Ap." ---- *) + +let test_475e_apostle_natalicium () = + (* 2026-11-30: St Andrew, Class2, subject Saint -- not covered by 475(c) + (not Domini/BVM), so [true] here can only come from 475(e)'s own + natalicia list. Also carries a real commemoration + (+ef-advent-1-monday), another live 476(e) instance. *) + check "475(e): an Apostle's own natalicium (Andrew)" 2026 11 30 true + +let test_475e_barnabas_named_explicitly () = + (* 2026-06-11: St Barnabas, Class3 -- named explicitly by the clause + ("S. Barnabae Ap."); at Class3 it could not reach [true] via 475(b) or + (c) regardless. *) + check "475(e): St Barnabas, named explicitly" 2026 6 11 true + +let test_475e_chair_of_peter_named_explicitly () = + (* 2027-02-22 (NOT 2026: Feb 22 2026 is impeded by Lent I Sunday, so the + Chair is not observed that year -- checked via `colitur day 2026` + before picking 2027 instead): the Chair of St Peter, Class2, subject + Saint -- NOT a natalicium (Peter's own is 29 June, shared with Paul), + so [true] here can only come from the clause's own explicit "Cathedrae + S. Petri" naming, not from the natalicium reading in general. *) + check "475(e): the Chair of St Peter, named explicitly (not a natalicium)" 2027 2 22 true + +let test_475e_excludes_conversion_of_paul () = + (* Trap Two, directly: 2027-01-25, the Conversion of St Paul, Class3 -- + names an Apostle but is NOT his natalicium (his own is 29 June, with + Peter); Class3 rules out 475(b)/(c), and this slug is deliberately + absent from [creed_apostle_slugs]. Picked 2027 for the same impeded- + Sunday reason as the Chair of Peter above (25 January 2026 is itself a + Sunday). *) + check "475(e) does NOT cover the Conversion of St Paul (not a natalicium)" 2027 1 25 false + +(* ---- RG 23 (feriae) / RG 476(a): Ash Wednesday, Holy Week's own feriae, + the Chrism/Lord's Supper Mass, the Easter Vigil Mass ---- *) + +let test_ash_wednesday_no_creed () = + check "RG 23(a)/476: Ash Wednesday, a I-class FERIA, not a festum" 2026 2 18 false + +let test_holy_thursday_no_creed () = + (* 2026-04-02: "Feria V in Cena Domini" -- RG 23(b)'s own "omnes feriae + Hebdomadae sanctae"; also explicitly named by 476(a) ("sive... in + Cena Domini"). *) + check "RG 23(b)/476(a): Holy Thursday (Mass of the Lord's Supper)" 2026 4 2 false + +let test_holy_saturday_easter_vigil_no_creed () = + (* 2026-04-04: "Sabbato sanctum" -- RG 23(b) again; also explicitly named + by 476(a) ("in Missa Vigiliae paschalis"). *) + check "RG 23(b)/476(a): Holy Saturday (the Easter Vigil Mass)" 2026 4 4 false + +(* ---- RG 476(f): "in Missis defunctorum" -- the Creed is never said at a + Requiem Mass. Whole-branch review finding 1: colitur used to say [true] + here on rank alone (475(b), Class1) -- the LMS Ordo layer's own former + allow-list entry L1, now closed, was this exact day. See rubrics_ef.ml's + own header for why {!Colour.Black} is a sound RG 117 proxy for "this Mass + is a Requiem" on the shipped data. ---- *) + +let test_476f_all_souls_no_creed () = + (* 2025-11-03: All Souls' Day (2 November, a Sunday that year, transferred + to the next open day, RG's own Class1/black office unchanged by the + transfer) -- `colitur day 2025` confirms class-1/black/ + commemoration-of-all-souls on this date. Before this fix [creed] here + was [true] via 475(b); the Ordo's own text ("No Cr") says otherwise. *) + check "RG 476(f): All Souls' Day (transferred), a Requiem, says no Creed" 2025 11 3 false + +let test_476f_good_friday_no_creed () = + (* 2026-04-03: Good Friday, [colour = Black] (temporal_ef.ml's own + [days_between easter d = -2] branch) -- already [false] via the RG + 23(b) feria-I-classis exclusion checked earlier in [creed], so this is + a belt-and-braces witness that the 476(f) guard, were it ever reached + first, would agree rather than a case that depends on it: Good Friday + has no Mass in the 1955-restored Holy Week to begin with. *) + check "RG 476(f)/RG 23(b): Good Friday, black, says no Creed" 2026 4 3 false + +(* Whole-branch review finding 1's own instruction: a test that FAILS if a + third {!Colour.Black} celebration is ever introduced, so the RG 476(f) + guard's colour proxy cannot silently rot into covering the wrong + population. Two independent checks, matching the two places a black + celebration could be added: + + DATA: every entry the shipped sanctoral layer (sanctoral.sexp, with + adjustments.sexp merged on top -- the same [layer] every other test in + this file resolves against) carries directly, fixed AND movable alike + ({!Colitur_kernel.Layer.entries} holds the raw [Date_spec.t], not a + resolved index, so this needs no date walk at all to cover every civil + year). + + CODE: {!Rite_ef.Temporal_ef.temporal}'s own colour logic, which + sanctoral.sexp cannot see (Good Friday's black is computed, not data) -- + swept across a century the same span and for the same coverage reason + {!test_ferial_origin_never_carries_lord_bvm_or_apostle_slug} above + already uses, since a Colour.Black bug introduced into a rare branch + (an Ember day, Rogation Wednesday...) would not show up in one year. *) +let test_colour_black_population_is_exactly_two () = + let black_data_entries = + List.filter + (fun (e : V.rank Colitur_kernel.Layer.entry) -> e.Colitur_kernel.Layer.cel.Cel.colour = Colour.Black) + layer.Colitur_kernel.Layer.entries + in + Alcotest.(check int) "exactly one Colour.Black entry in the shipped data" 1 + (List.length black_data_entries); + (match black_data_entries with + | [ e ] -> + Alcotest.(check string) "the one Colour.Black data entry is All Souls" "commemoration-of-all-souls" + (Slug.to_string e.Colitur_kernel.Layer.cel.Cel.slug) + | _ -> ()); + let code_black = ref [] in + for y = 1583 to 1682 do + let dec31 = mk y 12 31 in + let d = ref (mk y 1 1) in + while Date.compare !d dec31 <= 0 do + let t = TE.temporal !d in + if t.Temporal.office.Cel.colour = Colour.Black then code_black := (y, !d, t) :: !code_black; + d := Date.add_days !d 1 + done + done; + Alcotest.(check bool) "the century sweep found at least 100 Colour.Black temporal days" true + (List.length !code_black >= 100); + List.iter + (fun (_, d, (t : (V.season, V.rank) Temporal.t)) -> + let easter = Computus.gregorian_easter (Date.year d) in + Alcotest.(check int) + (Printf.sprintf "%s: the only code-side Colour.Black day is Good Friday (Easter-2)" + (Date.to_iso8601 d)) + (-2) (Date.to_rata d - Date.to_rata easter); + Alcotest.(check string) + (Printf.sprintf "%s: Good Friday's own slug" (Date.to_iso8601 d)) + "ef-passiontide-2-friday" + (Slug.to_string t.Temporal.office.Cel.slug)) + !code_black + +(* ---- RG 476(b) negative: a plain II-class saint, not Domini/BVM, not an + Apostle/Evangelist ---- *) + +let test_476b_plain_class2_saint () = + (* 2026-08-10: St Lawrence, Class2, subject Saint -- a deacon and martyr, + no Apostle/Evangelist connection, not on any list this module reads. *) + check "476(b): a plain II-class saint (Lawrence) does not say the Creed" 2026 8 10 false + +(* ---- RG 28-34 (vigils): checked ahead of 475(c) so a Class2 vigil that + is ALSO on marian_slugs is still excluded ---- *) + +let test_vigil_excluded_even_when_class2_and_marian () = + (* 2026-08-14: Vigil of the Assumption, Class2 -- IS on + {!Rite_ef.Precedence_ef.marian_slugs} (a real Marian entry), so without + the vigil check ahead of 475(c) this would wrongly come out [true]. + Also carries a real commemoration (+eusebius-confessor), a second live + 476(e) instance. *) + check "vigils are excluded even when Class2 and Marian (Vigil of the Assumption)" 2026 8 14 false + +(* ---- RG 476(d): a IV-class office (also exercises RG 78/309(a)'s votive + Office of the BVM on Saturday, itself IV class) ---- *) + +let test_476d_bvm_saturday_office () = + (* 2026-07-11: the unoccupied Saturday's Office of Our Lady, Class4 -- + already a pinned example in test/cli.t (Task 4). *) + check "476(d): the BVM Saturday Office, IV class" 2026 7 11 false + +(* One full civil year, walked day by day: RG 475(a)'s own invariant, "every + Sunday says the Creed, no exceptions" -- the same sanity check the task + asks for at the domain-measurement step, pinned here as a real assertion + rather than left to a one-off shell scan. *) +let test_every_sunday_in_2026_says_the_creed () = + let days = Cal.year ctx layer 2026 in + Array.iter + (fun (d : (V.season, V.rank) LD.t) -> + if d.LD.temporal.Temporal.weekday = Date.Sun then + Alcotest.(check bool) + (Printf.sprintf "%s is a Sunday: creed must be true" (Date.to_iso8601 d.LD.date)) + true d.LD.creed) + days + +(* ---- Review finding 1 (celebrant-rubrics-phase1 fix task): RG 24/25's + feriae II and III classis (the Advent ferias 17-23 December, the + Advent/Lent/September Ember sets, and the numbered Lenten/Passiontide + ferias) are excluded from the Creed by NO check in rubrics_ef.ml -- see + that file's own RG 23 comment (the [n = -46 ...] branch) for the full + account. [creed]'s correct [false] answer for them rests entirely on an + unstated property of {!Rite_ef.Temporal_ef}: no ferial-origin office it + ever builds carries [subject = Lord] or [subject = Bvm] at [Class2] + (RG 475(c)'s own rank guard), and none carries a slug on + [RE.creed_apostle_slugs] (RG 475(e), which has no rank guard at all). + This test asserts that property directly against real Temporal_ef + output, rather than leaving it asserted only in prose, so a future + Temporal_ef change that breaks it fails HERE loudly instead of silently + changing the Creed. + + Two real, harmless, already-documented exceptions are excluded from the + [subject] checks rather than papered over: the Sacred Triduum + ([subject = Lord], [Class1] -- verified in temporal_ef.ml's own + [triduum_names] branch) and the votive Office of the BVM on Saturday, + RG 91 entry 27 ([subject = Bvm], [Class4] -- {!TE}'s own [is_bvm_saturday] + citation). Neither can ever reach [creed]'s 475(c) branch: the Triduum + is caught earlier by the explicit feria-I-classis check (its own + [Class1] is not [Class2]), and the BVM Saturday Office is [Class4], not + [Class2], so 475(c)'s own rank guard excludes it regardless of subject. + Excluding them here is not a loophole in the test -- it is the precise + boundary of what RG 475(c) actually reads, confirmed rather than + assumed by restricting the [Lord]/[Bvm] checks to exactly [Class2] (RG + 24's own II-class population) and [Class3] (RG 25's III-class + population), the two ranks a real feria can carry that are NOT already + handled by an explicit branch or a rank mismatch. The apostle-slug + check has no such carve-out: it is asserted for every ferial-origin day + of every rank, matching 475(e)'s own unguarded text. + + A THIRD exception -- not anticipated when this test was first written, + found by actually running it, not by inspection -- had to be excluded + from the POPULATION itself, not from the subject checks: RG 17(a)'s own + "secus die 2 ianuarii" fallback (2 January, only in a civil year with + no 2-5 January Sunday) is a genuine FEAST, [subject = Lord], [Class2], + sitting outside {!TE.named}'s table for a purely architectural reason + (temporal_ef.ml's own citation: that table's shape cannot express a + fallback conditional on a per-year fact) and not always a Sunday + either, so neither of [is_ferial_origin]'s two filters caught it on the + first run -- it failed on 1584-01-02 before {!is_holy_name_fallback} + below was added. Left in as evidence the sweep has real teeth rather + than trimmed from the span: excluding a genuine mistaken positive by + name, once found, is the correct fix; narrowing the span to dodge it + would not have been. + + A day is "ferial-origin" here iff {!TE.named} returns [None] for it + (nothing in the fixed/movable table of named feasts, vigils and octave + days claims it), it is not a Sunday (RG 21's own definition: "Nomine + feriae intelleguntur singuli dies hebdomadae, praeter dominicam" -- + every day of the week EXCEPT Sunday), and it is not the RG 17(a) + fallback date just above. *) +let contains_substring ~needle haystack = + let nl = String.length needle and hl = String.length haystack in + let rec loop i = (i + nl <= hl) && (String.sub haystack i nl = needle || loop (i + 1)) in + nl = 0 || loop 0 + +(* RG 17(a)'s own "secus die 2 ianuarii" fallback (temporal_ef.ml's own + citation on [holy_name_fallback_date]): a genuine FEAST, [subject = + Lord], [Class2] -- legitimately outside {!TE.named}'s table only for an + architectural reason (that table's bare [Date.t -> ... option] shape + cannot express a fallback conditional on a per-year fact, + [holy_name_sunday y = None]), never a ferial one, and it is not always + a Sunday, so the weekday filter below does not catch it either. Found + by running this test before this exclusion existed: it failed on + 1584-01-02, a real year with no 2-5 January Sunday. *) +let is_holy_name_fallback (d : Date.t) = + let y = Date.year d in + Date.compare d (TE.holy_name_fallback_date y) = 0 && TE.holy_name_sunday y = None + +let is_ferial_origin (d : Date.t) = + TE.named d = None && Date.weekday d <> Date.Sun && not (is_holy_name_fallback d) + +(* Span: civil years 1583-1682, the domain's own opening century -- every + RG 24/25 population recurs every civil year (Advent 17-23, all three + non-Whitsun Ember sets, and Lenten/Passiontide ferias are none of them + rare or conditional), so one year already gives full COVERAGE; a + century instead of one is for confidence the invariant is not an + accident of a single Easter date, at a cost (day-by-day calls to the + pure {!TE.temporal}, no Calendar/Precedence resolution) cheap enough to + stay in the default, unsampled suite. 1583 is also the domain's own + lower bound, and this span contains 1598, the earliest possible Easter + (22 March) in [1583, 2500] per {!test_easter_extremes} above -- a real, + not merely nominal, edge case. Coverage is VERIFIED below via counters, + not assumed: a test that never actually walks an Ember day would prove + nothing about Ember days. *) +let test_ferial_origin_never_carries_lord_bvm_or_apostle_slug () = + let total = ref 0 + and advent_ember = ref 0 + and lent_ember = ref 0 + and september_ember = ref 0 + and advent_17_23 = ref 0 + and lenten_passiontide_class3 = ref 0 in + for y = 1583 to 1682 do + let dec31 = mk y 12 31 in + let d = ref (mk y 1 1) in + while Date.compare !d dec31 <= 0 do + (if is_ferial_origin !d then begin + let t = TE.temporal !d in + incr total; + let office = t.Temporal.office in + let slug = Slug.to_string office.Cel.slug in + let label = Printf.sprintf "%s (%s, rank=%s)" (Date.to_iso8601 !d) slug + (match office.Cel.rank with + | V.Class1 -> "1" + | V.Class2 -> "2" + | V.Class3 -> "3" + | V.Class4 -> "4") + in + (* Coverage tallies -- checked against zero below. *) + if contains_substring ~needle:"advent-ember" slug then incr advent_ember; + if contains_substring ~needle:"lent-ember" slug then incr lent_ember; + if contains_substring ~needle:"september-ember" slug then incr september_ember; + if Date.month !d = 12 && Date.day !d >= 17 && Date.day !d <= 23 then incr advent_17_23; + if + office.Cel.rank = V.Class3 + && (t.Temporal.season = V.Lent || t.Temporal.season = V.Passiontide) + then incr lenten_passiontide_class3; + (* The invariant itself. Apostle slugs: every rank, no carve-out. *) + Alcotest.(check bool) (label ^ ": not on the apostle-natalicium slug list") false + (List.mem slug RE.creed_apostle_slugs); + (* Lord/Bvm subject: only at the two ranks a real RG 24/25 feria + can carry -- see this test's own header for why Class1 + (Triduum) and Class4 (BVM Saturday) are deliberately excluded. *) + if office.Cel.rank = V.Class2 || office.Cel.rank = V.Class3 then begin + Alcotest.(check bool) (label ^ ": not subject Lord") false (office.Cel.subject = Subject.Lord); + Alcotest.(check bool) (label ^ ": not subject Bvm") false (office.Cel.subject = Subject.Bvm) + end + end); + d := Date.add_days !d 1 + done + done; + Alcotest.(check bool) "span examined a real number of ferial-origin days" true (!total > 10_000); + Alcotest.(check bool) "span reached Advent Ember days" true (!advent_ember > 0); + Alcotest.(check bool) "span reached Lent Ember days" true (!lent_ember > 0); + Alcotest.(check bool) "span reached September Ember days" true (!september_ember > 0); + Alcotest.(check bool) "span reached Advent 17-23 ferias" true (!advent_17_23 > 0); + Alcotest.(check bool) "span reached Lenten/Passiontide III-class ferias" true + (!lenten_passiontide_class3 > 0) + +(* ---- 237(a): the three named Paschaltide days ---- *) + +let test_237a_easter_sunday () = check_te_deum "237(a): Easter Sunday" 2026 4 5 true +let test_237a_low_sunday () = check_te_deum "237(a): Low Sunday" 2026 4 12 true +let test_237a_pentecost () = check_te_deum "237(a): Pentecost Sunday" 2026 5 24 true + +(* ---- 237(f): the vigils of Ascension and Pentecost, both otherwise + reachable by 238(b) (the Ascension vigil is Class2) or moot to it + (the Pentecost vigil is Class1) ---- *) + +let test_237f_ascension_vigil () = check_te_deum "237(f): Vigil of the Ascension" 2026 5 13 true +let test_237f_pentecost_vigil () = check_te_deum "237(f): Vigil of Pentecost" 2026 5 23 true + +(* ---- 237(d): the three privileged octaves, reusing [creed]'s own windows + -- a day within the Nativity octave whose OWN office is a real saint + (RG 67's "Com. octavae Nativitatis"), and an Easter-week feria outside + the narrower 237(a) list ---- *) + +let test_237d_nativity_octave_saint () = + check_te_deum "237(d): St John within the Nativity octave" 2026 12 27 true + +let test_237d_easter_week_feria () = check_te_deum "237(d): Easter Tuesday" 2026 4 7 true + +(* ---- 238(b): the omissible (Class2/Class3) vigils -- St Lawrence's own, + picked in a year where nothing displaces it, confirmed via + `colitur day 2026` first the same way the Creed tests were derived ---- *) + +let test_238b_omissible_vigil () = + (* 9 August 2026 is itself a Sunday (the vigil impeded, see 237(b)'s own + test below, which reuses that exact date) -- 2027 is picked instead, + confirmed via `colitur day 2027` first, the same discipline every + other date in this file follows. *) + check_te_deum "238(b): Vigil of St Lawrence" 2027 8 9 false + +(* ---- The Nativity Vigil (I class): NOT literally named by 238(b)'s own + "II et III classis" text -- excluded here on the structural RG 21/35 + taxonomy inference [te_deum]'s own comment states explicitly as an + inference, not a citation. Flagged the same way in the task report; + checked against the FIUV Ordo's own Te Deum marker for 24 December in + test_fiuv_ordo.ml, which is this inference's real corroboration. ---- *) + +let test_nativity_vigil_excluded_by_inference () = + check_te_deum "Nativity Vigil (I class): excluded, inference not literal 238(b)" 2026 12 24 false + +(* ---- 238(c)/RG23: Ash Wednesday and Good Friday (moot -- no Mass, but the + RG23 feria-I-classis exclusion still answers [false] regardless of + colour) ---- *) + +let test_238c_ash_wednesday () = check_te_deum "238(c)/RG23: Ash Wednesday" 2026 2 18 false +let test_238c_good_friday () = check_te_deum "238(c)/RG23: Good Friday" 2026 4 3 false + +(* ---- 237(g): the votive Office of the BVM on Saturday -- reused directly + from test/cli.t's own pinned example ---- *) + +let test_237g_bvm_saturday () = check_te_deum "237(g): BVM Saturday Office" 2026 7 11 true + +(* ---- 237(e): a plain, non-octave, non-Sunday feria of Christmastide (2-5 + January) ---- *) + +let test_237e_christmastide_feria () = + check_te_deum "237(e): 2 January, a Christmastide feria" 2026 1 2 true + +(* ---- 237(b): an ordinary II-class Sunday outside Septuagesima, and its + own explicit exception (a Septuagesima/Sexagesima Sunday, [Class2], + excepted by name) ---- *) + +let test_237b_ordinary_class2_sunday () = + check_te_deum "237(b): an ordinary Time-after-Pentecost Sunday" 2026 8 9 true + +(* RE-VERIFIED against the CORRECTED FIUV extraction ([te_deum]'s own + 237(a) comment has the full account of the extractor bug an earlier + pass of this task found and fixed): 237(b)'s own literal "exceptis + dominicis in Septuagesima, in Sexagesima et in Quinquagesima" holds + after all -- these two Sundays do NOT say the Te Deum, confirmed + against the corrected data, not merely the original transcription + alone. *) +let test_237b_septuagesima_exception () = + check_te_deum "237(b)'s own exception: Septuagesima Sunday" 2027 1 24 false + +let test_237b_sexagesima_exception () = + check_te_deum "237(b)'s own exception: Sexagesima Sunday" 2027 1 31 false + +(* ---- 237(c): a genuine sanctoral feast kept during a penitential season + (St Paul of the Cross, Class3, outside any privileged window) and one in + Ordinary Time (Lawrence, Class2) ---- *) + +let test_237c_sanctoral_feast () = check_te_deum "237(c): a sanctoral feast (Lawrence)" 2026 8 10 true + +(* Found alongside the FIUV extractor-bug fix ([te_deum]'s own 237(c) + comment has the full account): Passion Sunday and Palm Sunday are BOTH + entries in {!Temporal_ef.named} (named individually for RG 91 entry 6), + which without the [temporal.weekday <> Sun] guard on 237(c)'s own + [named<>None] disjunct would wrongly grant them [true] by ACCIDENT of + table membership -- neither is a genuine "festum" (RG 35's own "dies + dominica" is its own category), and both are [Class1] Sundays 237(b)'s + own [Class2] guard already excludes. Confirmed [false] directly against + the corrected FIUV extraction. *) +let test_passion_sunday_not_a_festum () = check_te_deum "Passion Sunday is not a festum for 237(c)" 2026 3 22 false +let test_palm_sunday_not_a_festum () = check_te_deum "Palm Sunday is not a festum for 237(c)" 2026 3 29 false + +(* ---- 238(d): the Requiem proxy, shared with [creed]'s own 476(f) and the + SAME two-member {!Colour.Black} population + {!test_colour_black_population_is_exactly_two} already asserts ---- *) + +let test_238d_all_souls () = check_te_deum "238(d): All Souls' Day (transferred)" 2025 11 3 false + +(* ---- RG 431(c): Holy Thursday and the Easter Vigil Mass say the Gloria + even though neither day's own Matins says the Te Deum (both are + feria-I-classis, [te_deum]'s own 238(c) branch) -- the one place [gloria] + and [te_deum] genuinely disagree on real data. Holy Saturday also proves + 431(c) outranks 432(b): its own colour is [Violet] + (Passiontide's [season_colour]), yet the Gloria is still said. ---- *) + +let test_431c_holy_thursday () = check_gloria "431(c): Holy Thursday" 2026 4 2 true +let test_431c_easter_vigil () = check_gloria "431(c): the Easter Vigil Mass (Holy Saturday)" 2026 4 4 true + +(* ---- RG 432(b): violet vestments -- independent of [te_deum], checked + against an Advent Sunday (I class, so [te_deum] would ALSO answer + [false] here via its own 237(b) rank guard: this is a same-answer + witness, not proof of independent teeth -- see the task report for why + no fully independent (te_deum=true, violet) witness exists anywhere in + the shipped 1583-9999 domain: every real [Colour.Violet] [Feast] entry + is one of the five sanctoral vigils, already excluded by [te_deum]'s + own [is_vigil] branch either way). ---- *) + +let test_432b_violet_sunday () = check_gloria "432(b): Advent I Sunday, violet" 2026 11 29 false + +(* ---- RG 432(d): the Requiem proxy, same population as 238(d) above ---- *) + +let test_432d_all_souls () = check_gloria "432(d): All Souls' Day (transferred)" 2025 11 3 false + +(* ---- RG 431(a)/432(a): mirrors [te_deum] for everything not already + decided above -- one true, one false, neither reachable via 431(c)/432(b)/ + 432(d) ---- *) + +let test_431a_mirrors_te_deum_true () = + check_gloria "431(a): mirrors [te_deum]=true (a sanctoral feast, Lawrence)" 2026 8 10 true + +let test_432a_mirrors_te_deum_false () = + check_gloria "432(a): mirrors [te_deum]=false (an ordinary Advent feria)" 2025 12 1 false + +(* ---- The Rogation Monday/Tuesday cascade (celebrant-rubrics-phase1 Bug 1 + fix, 2026-08-22): {!Rite_ef.Temporal_ef.temporal} used to hardcode + [Colour.Violet] on these two days with no citation, which silenced + [gloria] via 432(b) even though 237(e)'s own Paschaltide-feria branch + already said [te_deum]=true underneath. Fixed to [season_colour] (RG + 119: white from the Paschal Vigil to the Pentecost Vigil exclusive; RG + 128's own violet list never names Rogation days; RG 88 -- the violet + belongs to the Rogation MASS, not the Office this field describes). + 2028-05-22/23: neither day is impeded that year (test_golden.ml's own + [test_rogation_{monday,tuesday}_white_2028] pins the colour side of the + same fix), so both resolve to white and both now say the Gloria, MIRROR + OF [te_deum] via 431(a) once 432(b)'s violet guard no longer fires -- + MATCHING the LMS Ordo witness (2023-2024, 2024-05-06, "FERIA IV Cl W + ... Gl"). Reverting temporal_ef.ml's fix alone (mutation-checked while + building this task) turns both [false], the pre-fix answer. *) +let test_rogation_monday_gloria_2028 () = check_gloria "Rogation Monday: white -> Gloria said (2028)" 2028 5 22 true +let test_rogation_tuesday_gloria_2028 () = check_gloria "Rogation Tuesday: white -> Gloria said (2028)" 2028 5 23 true + +(* ---- Domain-wide sanity, task requirement 5: "every violet day must be + false (RG 432 b), and every Requiem must be false (432 d)". Two + invariants, checked over every day {!Cal.year} resolves -- [Cal.year], + not [Cal.day] in a loop, for the same cost reason + {!test_every_sunday_in_2026_says_the_creed} above already gives. + + FAST (default suite): a fixed 200-year span, 1583-1782 -- large enough + to cross multiple Easter cycles and every season repeatedly, cheap + enough to stay in `dune test`'s own budget. EXHAUSTIVE (gated the same + way {!test_validate.test_exhaustive_domain_sweep} already is, via + COLITUR_EXHAUSTIVE_SWEEP): the full 1583-9999 domain, also tallying and + printing the true/false distribution so the measurement this task asks + for is not merely "did the invariant hold" but has a number attached -- + see the task report for the printed figures. *) +(* NOT a blanket "every violet day is [gloria]=false" (the task brief's own + phrasing, taken literally, is one exception too strong): RG 431(c) is a + NAMED, lex-specialis override for the Easter Vigil Mass, and colitur's + own per-day colour model gives Holy Saturday [Colour.Violet] + ([gloria]'s own header has the full argument for why -- the historical + violet-to-white vestment change happens AT the Gloria itself, a + per-action nuance this whole day/colour model already cannot express). + So the real invariant, checked here, is "every violet day is + [gloria]=false EXCEPT the Easter Vigil (Easter offset -1), which is + [gloria]=true BY DESIGN" -- and the exception is asserted to be EXACTLY + that one shape, every year, nothing else: [n = -1] is checked directly + rather than merely excluded, so a second, unexpected (violet, + gloria=true) day anywhere in the domain still fails loudly. Pushed back + on the task brief's own simplified phrasing rather than silently + special-cased -- see the task report. *) +let check_gloria_invariants_for_year y (counts : (int * int * int * int) ref) = + let days = Cal.year ctx layer y in + (* Per-date, NOT once per loop iteration off [y]: a liturgical year + "opening in civil year y" ({!Rite.t.year_start}'s own doc comment) + runs from that year's Advent into MOST of civil year y+1 -- so + [Cal.year ctx layer y]'s own array holds dates whose civil year is + y+1 for the whole Christmas-to-Pentecost span, governed by EASTER OF + y+1, not y. A single [Computus.gregorian_easter y] computed once here + wrongly used year y's own Easter for those dates -- found live: it + misidentified 1584-03-31 (Holy Saturday, governed by 1584's Easter, + surfaced while processing loop iteration y=1583) as an ordinary + violet day instead of the Vigil's own 431(c) exception, because + Easter 1583 (not 1584) was subtracted. Fixed by keying off + [Date.year d.LD.date] instead, which is always safe here: Holy + Saturday and Easter Sunday are never more than a few days apart and + never cross a civil-year boundary. *) + let violet, black, gloria_true, gloria_false = !counts in + let violet = ref violet + and black = ref black + and gloria_true = ref gloria_true + and gloria_false = ref gloria_false in + Array.iter + (fun (d : (V.season, V.rank) LD.t) -> + (if d.LD.gloria then incr gloria_true else incr gloria_false); + if d.LD.observed.Cel.colour = Colour.Violet then begin + incr violet; + let easter = Computus.gregorian_easter (Date.year d.LD.date) in + let n = Date.to_rata d.LD.date - Date.to_rata easter in + if n = -1 then + Alcotest.(check bool) + (Printf.sprintf "%s: the Easter Vigil's own 431(c) override, [gloria]=true despite violet" + (Date.to_iso8601 d.LD.date)) + true d.LD.gloria + else + Alcotest.(check bool) + (Printf.sprintf "%s: violet -> [gloria]=false (RG 432(b))" (Date.to_iso8601 d.LD.date)) + false d.LD.gloria + end; + if d.LD.observed.Cel.colour = Colour.Rose then + (* Gaudete/Laetare -- [gloria] reads [false] here via [te_deum]'s + own [Class2] guard on 237(b) (both Rose Sundays are [Class1] BY + CONSTRUCTION -- {!Rite_ef.Rubrics_ef.gloria}'s own 432(b) + citation has the full "checked, then found redundant, then + removed" account of why 432(b) itself does NOT need its own + Rose branch). Not folded into the [violet] counter above: + keeping the two colours separately tallied is what let this + invariant catch the Gaudete/Laetare gap live in the first place + (found via the LMS Ordo, 2023-12-17 and 2024-03-10) rather than + silently averaging it away inside one shared bucket. *) + Alcotest.(check bool) + (Printf.sprintf "%s: Rose (Gaudete/Laetare) -> [gloria]=false" (Date.to_iso8601 d.LD.date)) + false d.LD.gloria; + if d.LD.observed.Cel.colour = Colour.Black then begin + incr black; + Alcotest.(check bool) + (Printf.sprintf "%s: Requiem (black) -> [gloria]=false (RG 432(d))" (Date.to_iso8601 d.LD.date)) + false d.LD.gloria + end) + days; + counts := (!violet, !black, !gloria_true, !gloria_false) + +let test_domain_violet_implies_no_gloria_sample () = + let counts = ref (0, 0, 0, 0) in + for y = 1583 to 1782 do + check_gloria_invariants_for_year y counts + done; + let violet, _, _, _ = !counts in + Alcotest.(check bool) "the 200-year sample reached a real number of violet days" true (violet > 1000) + +let test_domain_requiem_implies_no_gloria_sample () = + (* Separate test name, same underlying sweep as the one immediately above + -- {!Cal.year} is only computed once per year regardless (module-level + [ctx]/[layer], no per-test reload), so this is not a second pass over + the domain, only a second, independently-named assertion on the same + tally, matching how {!test_colour_black_population_is_exactly_two} + above separates its own DATA and CODE checks into one function while + this pair keeps violet and black as two named outcomes. *) + let counts = ref (0, 0, 0, 0) in + for y = 1583 to 1782 do + check_gloria_invariants_for_year y counts + done; + let _, black, _, _ = !counts in + Alcotest.(check bool) "the 200-year sample reached at least one Requiem day" true (black > 0) + +let colitur_exhaustive_sweep_env = "COLITUR_EXHAUSTIVE_SWEEP" + +let test_exhaustive_gloria_domain_sweep () = + if Sys.getenv_opt colitur_exhaustive_sweep_env = None then Alcotest.skip () + else begin + let counts = ref (0, 0, 0, 0) in + for y = 1583 to 9999 do + check_gloria_invariants_for_year y counts + done; + let violet, black, gloria_true, gloria_false = !counts in + Printf.printf + "gloria domain sweep 1583..9999: violet=%d black=%d gloria_true=%d gloria_false=%d total=%d\n%!" + violet black gloria_true gloria_false (gloria_true + gloria_false); + Alcotest.(check bool) "the full domain reached a real number of violet days" true (violet > 100_000); + Alcotest.(check bool) "the full domain reached a real number of Requiem days" true (black > 1_000) + end + +(* ---- RG 482-499, the preface -- see lib/rites/rite_ef/rubrics_ef.ml for + the rubric quoted in full and every branch's own citation. One + end-to-end test per branch, resolved against REAL calendar dates + through the shipped data, the same discipline every other section of + this file already follows -- most of these dates were cross-checked + directly against the FIUV Ordo's own [praef] column + (test/fixtures/fiuv-ordo-2025-2026.sexp) before being pinned here, not + merely derived from the Latin text in isolation; see [preface]'s own + header for the full account of what that cross-check settled. ---- *) + +module Pref = Colitur_kernel.Preface + +let preface_on y m d = (day_on y m d).LD.preface + +let preface_string_on y m d = + match preface_on y m d with Some p -> Pref.to_string p | None -> "-" + +let check_preface name expected y m d = + Alcotest.(check string) name (Pref.to_string expected) (preface_string_on y m d) + +let check_no_preface name y m d = Alcotest.(check string) name "-" (preface_string_on y m d) + +(* ---- Good Friday: no Mass at all, [None] -- checked ahead of the + Requiem/Black-colour branch (this file's own [preface] header explains + why the two need different answers, unlike creed/gloria/te_deum). ---- *) +let test_preface_good_friday_no_mass () = check_no_preface "Good Friday: no Mass, no preface" 2026 4 3 + +(* ---- RG 499: the Requiem proxy, the SAME two-member {!Colour.Black} + population {!test_colour_black_population_is_exactly_two} already + asserts, with Good Friday split out above. ---- *) +let test_preface_499_all_souls () = + check_preface "RG 499: All Souls' Day (transferred)" Pref.Requiem 2025 11 3 + +(* ---- RG 487(a): the two fixed Holy Cross feast triggers. ---- *) +let test_preface_487a_exaltation () = + check_preface "RG 487(a): the Exaltation of the Holy Cross" Pref.Holy_cross 2026 9 14 + +let test_preface_487a_precious_blood () = + check_preface "RG 487(a): the Most Precious Blood" Pref.Holy_cross 2026 7 1 + +(* ---- RG 491/492: Sacred Heart, Christ the King -- single named days. ---- *) +let test_preface_491_sacred_heart () = check_preface "RG 491: the Sacred Heart" Pref.Sacred_heart 2026 6 12 +let test_preface_492_christ_the_king () = + check_preface "RG 492: Christ the King" Pref.Christ_the_king 2026 10 25 + +(* ---- RG 490(a): Ascension Day itself. ---- *) +let test_preface_490a_ascension_day () = check_preface "RG 490(a): Ascension Day" Pref.Ascension 2026 5 14 + +(* ---- RG 494(a): Trinity Sunday itself. ---- *) +let test_preface_494a_trinity_sunday () = check_preface "RG 494(a): Trinity Sunday" Pref.Trinity 2026 5 31 + +(* ---- RG 496: St Joseph's two feasts. ---- *) +let test_preface_496_joseph_spouse () = check_preface "RG 496: St Joseph, Spouse of the BVM" Pref.St_joseph 2026 3 19 +let test_preface_496_joseph_workman () = check_preface "RG 496: St Joseph the Workman" Pref.St_joseph 2027 5 1 + +(* ---- RG 495: a genuine Marian FEAST via [marian_slugs] (the Assumption), + and the VOTIVE-shaped BVM Saturday Office via [subject = Bvm] -- the + latter is the live witness for RG 495's own "et votivis" half on this + engine's data (this file's own [preface] header has the full account, + corroborated against the Ordo on 3/10 January 2026). ---- *) +let test_preface_495_assumption () = check_preface "RG 495: the Assumption (marian_slugs)" Pref.Bvm 2026 8 15 +let test_preface_495_bvm_saturday_office () = + check_preface "RG 495: the BVM Saturday Office (subject=Bvm, votive-shaped)" Pref.Bvm 2026 7 11 + +(* ---- RG 484(a)'s own explicit Purification clause: 2 February, checked + as a standalone slug trigger regardless of season -- see [preface]'s + own header for why this needed to be independent of the Nativity + WINDOW below (2 February is nowhere near it). ---- *) +let test_preface_484a_purification () = check_preface "RG 484(a): the Purification" Pref.Nativity 2026 2 2 + +(* ---- RG 484(a)/(b) merged: the Nativity octave window, 25 December-1 + January, PLUS RG 484(b)'s own extra "2 ad 5 ianuarii" days -- one + contiguous window. St Stephen (26 December) is the live witness that + this OUTRANKS an ordinary saint's own otherwise-Common preface; + {!creed}'s own 475(d) test picks the identical date for the identical + "occurring inside a privileged window" shape. ---- *) +let test_preface_484_nativity_day () = check_preface "RG 484(a): Christmas Day itself" Pref.Nativity 2026 12 25 +let test_preface_484_stephen_in_octave () = + check_preface "RG 484(b): St Stephen, occurring within the Nativity octave" Pref.Nativity 2026 12 26 + +let test_preface_484_jan1_octave_day () = + check_preface "RG 484(a): 1 January, the Octave Day" Pref.Nativity 2026 1 1 + +let test_preface_484b_jan2to5 () = + (* 2 January 2026 (a plain Christmastide feria, "ef-christmas-1-friday", + confirmed via `colitur day 2026`) -- 3 January that year is the BVM + Saturday Office instead (RG 495's own "et votivis" outranking this + window, this file's own [test_preface_495_bvm_saturday_office] and + [preface]'s own header have the full account), so this date is picked + specifically to witness the PLAIN de-Tempore grant, uncomplicated by + that override. *) + check_preface "RG 484(b): 2 January, the extra de-Tempore days" Pref.Nativity 2026 1 2 + +(* ---- RG 484(b)'s own NARROWER exception: an Apostle/Evangelist inside + the Nativity octave is STILL overridden to [Nativity] (unlike every + other window, which an Apostle's own preface outranks -- the next test + below). John the Evangelist, 27 December, is the live witness this + file's own [preface] header cites. ---- *) +let test_preface_484b_overrides_apostle_in_octave () = + check_preface "RG 484(b): St John the Evangelist, inside the Nativity octave, still [Nativity]" + Pref.Nativity 2026 12 27 + +(* ---- RG 497: the Apostle/Evangelist natalicia list, reused from + {!creed_apostle_slugs} -- OUTSIDE the Nativity octave, an Apostle keeps + his own preface even inside another window (Sts Philip & James, 11 May, + inside the Paschaltide/Easter window -- the FIUV Ordo's own witness + this file's own [preface] header cites for RG 484(b)'s narrower + carve-out, checked from the other direction). ---- *) +let test_preface_497_barnabas () = check_preface "RG 497: St Barnabas" Pref.Apostles 2026 6 11 +let test_preface_497_peter_paul () = check_preface "RG 497: Sts Peter & Paul" Pref.Apostles 2026 6 29 +let test_preface_497_philip_james_inside_easter_window () = + check_preface "RG 497: Sts Philip & James, inside the Easter window, still [Apostles]" Pref.Apostles 2026 5 11 + +(* ---- RG 497 also covers "conversion-of-st-paul" (25 January, Class3, + NOT his own natalicium -- {!creed_apostle_slugs} deliberately excludes + it from the CREED for exactly that reason, RG 475(e)'s own natalicium + restriction). RG 497 carries no such restriction, and unlike + {!test_fiuv_ordo.ml}'s own single window (where 25 January falls on a + Sunday, hence impeded), the Latin Mass Society Ordo's three editions + (test/test_lms_ordo.ml, Preface-witnesses task, 2026-08-23) each carry + an unimpeded 25 January in two of their three civil years, 2024 and + 2025, and BOTH independently read "Pr of the Apostles" -- 2024-01-25 is + the date pinned here, matching the FIRST of those two witnessed + years directly (day names elsewhere in this file default to 2026 for + uniformity with the FIUV Ordo's own window, but 2026-01-25 is itself + impeded by a Sunday, so it cannot witness this branch at all). ---- *) +let test_preface_497_conversion_of_st_paul () = + check_preface "RG 497: the Conversion of St Paul, not his own natalicium, still [Apostles]" Pref.Apostles 2024 1 25 + +(* ---- RG 485(a)/(b): Epiphany itself and its own Baptism commemoration + (a), the wider 7-13 January window (b) -- Holy Family Sunday (11 + January 2026) is the live witness that a temporal-origin Sunday inside + this window gets [Epiphany], not some Holy-Family-specific preface this + engine has none of. ---- *) +let test_preface_485a_epiphany_day () = check_preface "RG 485(a): Epiphany Day" Pref.Epiphany 2026 1 6 +let test_preface_485a_baptism_commemoration () = + check_preface "RG 485(a): the Commemoration of the Baptism of the Lord" Pref.Epiphany 2026 1 13 + +let test_preface_485b_holy_family_sunday () = + check_preface "RG 485(b): Holy Family Sunday, inside the 7-13 January window" Pref.Epiphany 2026 1 11 + +(* ---- RG 486(a)/(b): the Lenten window, Ash Wednesday through the + Saturday before Passion Sunday I. ---- *) +let test_preface_486_ash_wednesday () = check_preface "RG 486(a): Ash Wednesday" Pref.Lent 2026 2 18 +let test_preface_486_lent_saturday_boundary () = + check_preface "RG 486: the Saturday immediately before Passion Sunday I" Pref.Lent 2026 3 21 + +(* ---- RG 487(a)/(b): the Passiontide window, Passion Sunday I through + Holy Thursday inclusive. ---- *) +let test_preface_487_passion_sunday () = check_preface "RG 487: Passion Sunday I" Pref.Holy_cross 2026 3 22 +let test_preface_487_palm_sunday () = check_preface "RG 487: Palm Sunday" Pref.Holy_cross 2026 3 29 +let test_preface_487_holy_thursday () = check_preface "RG 487: Holy Thursday" Pref.Holy_cross 2026 4 2 + +(* ---- RG 489(a)/(b): the Easter window, the Vigil Mass through the vigil + of the Ascension. ---- *) +let test_preface_489_easter_vigil_mass () = check_preface "RG 489(a): the Easter Vigil Mass" Pref.Easter 2026 4 4 +let test_preface_489_easter_sunday () = check_preface "RG 489(a): Easter Sunday" Pref.Easter 2026 4 5 +let test_preface_489_ascension_vigil () = check_preface "RG 489(b): the vigil of the Ascension" Pref.Easter 2026 5 13 + +(* ---- RG 490(b): the post-Ascension window. ---- *) +let test_preface_490b_post_ascension_feria () = + check_preface "RG 490(b): the Friday after Ascension" Pref.Ascension 2026 5 15 + +let test_preface_490b_sunday_after_ascension () = + check_preface "RG 490(b): the Sunday after Ascension" Pref.Ascension 2026 5 17 + +(* ---- RG 493(a)/(b): the Pentecost-octave window, the vigil through the + following Saturday (the Ember Saturday). ---- *) +let test_preface_493_pentecost_vigil () = check_preface "RG 493(a): the vigil of Pentecost" Pref.Holy_spirit 2026 5 23 +let test_preface_493_pentecost_sunday () = check_preface "RG 493(a): Pentecost Sunday" Pref.Holy_spirit 2026 5 24 +let test_preface_493_ember_saturday () = + check_preface "RG 493(a): the Ember Saturday within the Pentecost octave" Pref.Holy_spirit 2026 5 30 + +(* ---- RG 494(b): the Trinity de-Tempore Sundays -- an Advent Sunday + ([temporal.season = Advent], [Class1] by construction) and an ordinary + Time-after-Pentecost Sunday. Both now read off [temporal]'s own season, + not [observed]'s rank -- see the next test for why the distinction is + live, not merely stylistic. ---- *) +let test_preface_494b_advent_sunday () = check_preface "RG 494(b): Advent I Sunday" Pref.Trinity 2026 11 29 +let test_preface_494b_ordinary_class2_sunday () = + check_preface "RG 494(b): an ordinary Time-after-Pentecost Sunday" Pref.Trinity 2026 8 9 + +(* ---- RG 494(b), the RG 16(a)-shaped fix round: All Saints' Day (1 + November), [Class1], observed OUTRIGHT over the ordinary Sunday it + commemorates -- found via the FIUV Ordo (its own entry reads "Trinit. + vel de Omnibus Sanctis et Patronis", the "vel..." half an alternate + ORATIO reference, the SAME pattern every other "X vel Y" [praef] value + in that fixture already follows, never a second genuine preface). No + dedicated preface exists for All Saints among RG 484-497's own + fourteen, so RG 482's chain falls to the SUNDAY's own de-Tempore grant + regardless of which rank actually won the day -- exactly why this + branch must read [temporal]'s season, not [observed]'s [Class1] rank, + which an EARLIER version of [preface] wrongly required to equal + [Class2] and so answered [Common] here instead. + + 1 November 2026 is itself a Sunday (confirmed via `colitur day 2026`: + "all-saints class-1 white +ef-time-after-pentecost-sunday-23"), the + exact shape this fix concerns -- picked for that reason, not merely + because it is All Saints' Day. *) +let test_preface_494b_all_saints_class1_sunday () = + check_preface "RG 494(b): All Saints' Day, Class1, still Trinity (no dedicated preface exists)" Pref.Trinity + 2026 11 1 + +(* ---- RG 498: the Common residual -- Corpus Christi is the deliberately + chosen witness (NOT simply "any ordinary weekday"): the 1962 Missal + gives it no preface of its own at all, only an OPTIONAL alternative + (Sacred Heart's), so it takes the plain Common, confirmed against the + Ordo directly (4 June 2026: "comm. vel de Cor Sacratissimo") -- a real + trap this engine's own tier1 list does NOT fall into (no + "ef-corpus-christi" entry anywhere in it). ---- *) +let test_preface_498_corpus_christi () = check_preface "RG 498: Corpus Christi (no proper of its own)" Pref.Common 2026 6 4 + +let test_preface_498_plain_saint () = check_preface "RG 498: a plain sanctoral saint (Lawrence)" Pref.Common 2026 8 10 + +(* ---- Corroborating real-data invariants, task requirement 5: "every day + in Paschaltide should take the Easter preface unless it has a proper + one; every Lenten feria the Lent preface". Checked as a SWEEP, not a + single date, over a fixed sample span (1583-2200, matching the century+ + spans other domain checks in this file already use) -- FAST in the + default suite, EXHAUSTIVE (1583-9999) gated behind + COLITUR_EXHAUSTIVE_SWEEP the same way {!test_exhaustive_gloria_domain_sweep} + above already is. + + The invariant actually checked is NOT the brief's own literal phrasing + (which is one exception too strong, the identical "pushed back, not + silently special-cased" stance {!check_gloria_invariants_for_year}'s own + header already takes for [gloria]/432(b)): every Paschaltide-season day + takes [Easter], [Ascension] or [Holy_spirit] (its own three seasonal + windows), OR one of the season-independent title triggers this engine + can construct inside Paschaltide's real date range ([Bvm]/[St_joseph]/ + [Apostles]/[Requiem]) -- but NEVER [Nativity]/[Epiphany]/[Lent]/[Trinity]/ + [Sacred_heart]/[Christ_the_king]/[Common], none of which any real date + inside Paschaltide can trigger. Symmetrically for Lent: [Lent] or one of + [Bvm]/[St_joseph]/[Apostles]/[Requiem], never a preface belonging to a + date-disjoint window. Two further invariants the sweep found and kept, + not originally asked for but load-bearing: EVERY Christmastide-season + day resolves [Nativity], [Epiphany] or [Bvm] (RG 484/485 between them + leave no gap at all in that season on their own -- confirmed + exhaustively -- but RG 495's own votive-Mass half, live for the BVM + Saturday Office, can and does fall on a Christmastide Saturday too; + found live at 1584-01-07 while first running this exact sweep, kept as + a real witness rather than narrowed away); and Passiontide, uniquely, + legitimately + ALSO produces [Easter] exactly once a year (Holy Saturday's own Vigil + Mass, [n = -1] -- {!Rite_ef.Rubrics_ef.preface}'s own RG 489(a) comment; + this engine's day/colour model keeps that date [Passiontide] by season + even though the Vigil Mass's own preface has already moved to Easter's, + the same acknowledged per-action nuance [gloria]'s own RG 431(c) comment + already documents) -- asserted to be EXACTLY once per year, not merely + allowed, so a second, unexplained (Passiontide, Easter) day anywhere in + the domain still fails loudly. *) +let check_preface_season_invariants_for_year y (counts : (int * int * int * int) ref) = + let days = Cal.year ctx layer y in + let christmastide_gaps = ref 0 + and paschaltide_gaps = ref 0 + and lent_gaps = ref 0 + and passiontide_easter = ref 0 in + let christmastide_gaps0, paschaltide_gaps0, lent_gaps0, passiontide_easter0 = !counts in + christmastide_gaps := christmastide_gaps0; + paschaltide_gaps := paschaltide_gaps0; + lent_gaps := lent_gaps0; + passiontide_easter := passiontide_easter0; + Array.iter + (fun (d : (V.season, V.rank) LD.t) -> + let label = Printf.sprintf "%s (preface=%s)" (Date.to_iso8601 d.LD.date) + (match d.LD.preface with Some p -> Pref.to_string p | None -> "NONE") + in + (match d.LD.temporal.Temporal.season with + | V.Christmastide -> ( + match d.LD.preface with + | Some (Pref.Nativity | Pref.Epiphany | Pref.Bvm) -> () + | _ -> + incr christmastide_gaps; + Alcotest.failf "%s: Christmastide day with neither Nativity, Epiphany nor Bvm" label) + | V.Paschaltide -> ( + match d.LD.preface with + | Some (Pref.Easter | Pref.Ascension | Pref.Holy_spirit | Pref.Bvm | Pref.St_joseph + | Pref.Apostles | Pref.Requiem) -> + () + | _ -> + incr paschaltide_gaps; + Alcotest.failf "%s: Paschaltide day with an out-of-window preface" label) + | V.Lent -> ( + match d.LD.preface with + | Some (Pref.Lent | Pref.Bvm | Pref.St_joseph | Pref.Apostles | Pref.Requiem) -> () + | _ -> + incr lent_gaps; + Alcotest.failf "%s: Lent day with an out-of-window preface" label) + | V.Passiontide -> + if d.LD.preface = Some Pref.Easter then begin + incr passiontide_easter; + let easter = Computus.gregorian_easter (Date.year d.LD.date) in + Alcotest.(check int) + (Printf.sprintf "%s: the ONLY Passiontide/Easter day is the Vigil Mass (Easter-1)" label) + (-1) (Date.to_rata d.LD.date - Date.to_rata easter) + end + | _ -> ())) + days; + counts := (!christmastide_gaps, !paschaltide_gaps, !lent_gaps, !passiontide_easter) + +let test_preface_season_invariants_sample () = + let counts = ref (0, 0, 0, 0) in + for y = 1583 to 1782 do + check_preface_season_invariants_for_year y counts + done; + let _, _, _, passiontide_easter = !counts in + Alcotest.(check bool) "the 200-year sample found the once-a-year Passiontide/Easter exception" true + (passiontide_easter >= 200) + +let test_exhaustive_preface_season_domain_sweep () = + if Sys.getenv_opt colitur_exhaustive_sweep_env = None then Alcotest.skip () + else begin + let counts = ref (0, 0, 0, 0) in + for y = 1583 to 9999 do + check_preface_season_invariants_for_year y counts + done; + let christmastide_gaps, paschaltide_gaps, lent_gaps, passiontide_easter = !counts in + Printf.printf + "preface season sweep 1583..9999: christmastide_gaps=%d paschaltide_gaps=%d lent_gaps=%d \ + passiontide_easter=%d\n%!" + christmastide_gaps paschaltide_gaps lent_gaps passiontide_easter; + Alcotest.(check int) "zero Christmastide gaps anywhere in the domain" 0 christmastide_gaps; + Alcotest.(check int) "zero Paschaltide out-of-window prefaces anywhere in the domain" 0 paschaltide_gaps; + Alcotest.(check int) "zero Lent out-of-window prefaces anywhere in the domain" 0 lent_gaps; + (* 8416, not 8417 (the domain's own year count): a genuine, pre-existing + DOMAIN-BOUNDARY edge, not a preface defect -- {!Cal.year}'s own + liturgical year "opening in civil year 9999" cannot construct any + date past 1583-9999 ({!Date.make}'s own validated range), so it + returns only 34 days (28 November-31 December), never reaching its + own Easter/Holy Saturday (which would fall in year 10000). Found by + running this exact sweep: it returned 8416 first, not asserted + blindly at 8417 -- checked directly ([Cal.year ctx layer 9999] + alone, printed length 34) before writing this comment, the same + "measure before adjudicating" discipline every allow-list in this + project follows. The identical edge is why + docs/research/rules-register.md's own Layer.index citation already + reads "both edges, 1582 and 10000, bit during development" -- + this sweep is a second witness to the same known boundary, not a + new one. *) + Alcotest.(check int) "one Passiontide/Easter day per year, every year but the domain's own last" 8416 + passiontide_easter + end + +(* ---- BLAST RADIUS, Preface-witnesses task (2026-08-23): adding + "conversion-of-st-paul" to {!Rite_ef.Rubrics_ef.preface_apostle_slugs} + changes exactly one thing -- the preface on every year's own 25 January + WHEN [conversion-of-st-paul] is the day actually observed (impeded, most + often by a Sunday, in every other year). Measured directly rather than + estimated: every observed occurrence must now read [Apostles], never + anything else, and the domain total is printed so the SIZE of this + change is on the record, not only its correctness. *) +let check_conversion_of_st_paul_for_year y (counts : (int * int) ref) = + let days = Cal.year ctx layer y in + let observed0, wrong0 = !counts in + let observed = ref observed0 and wrong = ref wrong0 in + Array.iter + (fun (d : (V.season, V.rank) LD.t) -> + if String.equal (Slug.to_string d.LD.observed.Cel.slug) "conversion-of-st-paul" then begin + incr observed; + if d.LD.preface <> Some Pref.Apostles then begin + incr wrong; + Alcotest.failf "%s: conversion-of-st-paul is observed but preface=%s, not Apostles" + (Date.to_iso8601 d.LD.date) + (match d.LD.preface with Some p -> Pref.to_string p | None -> "NONE") + end + end) + days; + counts := (!observed, !wrong) + +let test_conversion_of_st_paul_preface_sample () = + let counts = ref (0, 0) in + for y = 1583 to 1782 do + check_conversion_of_st_paul_for_year y counts + done; + let observed, wrong = !counts in + Alcotest.(check int) "zero wrong-preface days in the 200-year sample" 0 wrong; + Alcotest.(check bool) "the 200-year sample found real conversion-of-st-paul occurrences" true (observed > 100) + +let test_exhaustive_conversion_of_st_paul_preface_sweep () = + if Sys.getenv_opt colitur_exhaustive_sweep_env = None then Alcotest.skip () + else begin + let counts = ref (0, 0) in + for y = 1583 to 9999 do + check_conversion_of_st_paul_for_year y counts + done; + let observed, wrong = !counts in + Printf.printf "conversion-of-st-paul preface blast radius 1583..9999: observed=%d wrong=%d\n%!" observed wrong; + Alcotest.(check int) "zero wrong-preface days anywhere in the domain" 0 wrong + end + +(* ---- ITEM 1: RG 111(a), the sung-Mass commemoration cap + ({!Colitur_kernel.Precedence.sung_mass_commemorations}) -- two real + calendar days, one of each shape, resolved through the identical + [Cal.day] pipeline every other test in this file uses. See + precedence.mli's own citation for the rubric and the reasoning for why + this is a derivation over [LD.commemorations] (the Low-Mass admitted + set), not a second stored field. ---- *) + +module Prec = Colitur_kernel.Precedence + +let sung_slugs y m d = + List.map + (fun (c, _) -> Slug.to_string c.Cel.slug) + (Prec.sung_mass_commemorations (day_on y m d).LD.commemorations) + +let test_rg111a_ordinary_only_dropped () = + (* 2026-08-14: Vigil of the Assumption, commemorating [eusebius-confessor] + ORDINARILY (no privileged category applies) -- confirmed via `colitur + day 2026`. At Low Mass this is admitted (RG 111(c)); at a + non-conventual Sung Mass RG 111(a) admits it not at all. *) + Alcotest.(check (list string)) "RG 111(a): an ordinary-only Low-Mass set is empty at Sung Mass" [] + (sung_slugs 2026 8 14) + +let test_rg111a_privileged_kept () = + (* 2026-04-25: St Mark, commemorating the Major Litanies -- RG 80/109(f), + a PRIVILEGED commemoration (data/ef/adjustments.sexp's own [Add + major-litanies]) -- confirmed via `colitur day 2026`. Kept at BOTH Low + Mass (RG 111(c), one privileged) and Sung Mass (RG 111(a), the same + single privileged commemoration). *) + Alcotest.(check (list string)) "RG 111(a): the one privileged commemoration survives at Sung Mass" + [ "major-litanies" ] (sung_slugs 2026 4 25) + +let suite = + ( "Rubrics_ef", + [ Alcotest.test_case "475(a): ordinary Sunday" `Quick test_475a_ordinary_sunday; + Alcotest.test_case "475(a): reads [temporal], not [observed] (Trap One)" `Quick + test_475a_reads_temporal_not_observed; + Alcotest.test_case "475(b): I-class feast" `Quick test_475b_class1_feast; + Alcotest.test_case "475(c): II-class feast of the Lord" `Quick test_475c_lord; + Alcotest.test_case "475(c): II-class BVM feast via marian_slugs" `Quick + test_475c_bvm_via_marian_slugs; + Alcotest.test_case "475(d): octave overrides an occurring feast" `Quick + test_475d_octave_even_occurring_feast; + Alcotest.test_case "475(d): 1 January octave-day boundary" `Quick test_475d_octave_day_boundary; + Alcotest.test_case "475(e): an Apostle's own natalicium" `Quick test_475e_apostle_natalicium; + Alcotest.test_case "475(e): Barnabas, named explicitly" `Quick + test_475e_barnabas_named_explicitly; + Alcotest.test_case "475(e): Chair of Peter, named explicitly" `Quick + test_475e_chair_of_peter_named_explicitly; + Alcotest.test_case "475(e) excludes the Conversion of St Paul (Trap Two)" `Quick + test_475e_excludes_conversion_of_paul; + Alcotest.test_case "RG 23/476: Ash Wednesday" `Quick test_ash_wednesday_no_creed; + Alcotest.test_case "RG 23/476(a): Holy Thursday" `Quick test_holy_thursday_no_creed; + Alcotest.test_case "RG 23/476(a): Holy Saturday / Easter Vigil" `Quick + test_holy_saturday_easter_vigil_no_creed; + Alcotest.test_case "476(f): All Souls' Day (transferred), a Requiem, no Creed" `Quick + test_476f_all_souls_no_creed; + Alcotest.test_case "476(f)/RG 23(b): Good Friday, black, no Creed" `Quick + test_476f_good_friday_no_creed; + Alcotest.test_case "Colour.Black population is exactly two (data + code)" `Quick + test_colour_black_population_is_exactly_two; + Alcotest.test_case "476(b): plain II-class saint (negative)" `Quick + test_476b_plain_class2_saint; + Alcotest.test_case "vigils excluded even when Class2 and Marian" `Quick + test_vigil_excluded_even_when_class2_and_marian; + Alcotest.test_case "476(d): BVM Saturday Office, IV class" `Quick test_476d_bvm_saturday_office; + Alcotest.test_case "every Sunday in 2026 says the Creed" `Quick + test_every_sunday_in_2026_says_the_creed; + Alcotest.test_case "RG 24/25: no ferial-origin office carries Lord/Bvm or an apostle slug" `Quick + test_ferial_origin_never_carries_lord_bvm_or_apostle_slug; + Alcotest.test_case "237(a): Easter Sunday" `Quick test_237a_easter_sunday; + Alcotest.test_case "237(a): Low Sunday" `Quick test_237a_low_sunday; + Alcotest.test_case "237(a): Pentecost Sunday" `Quick test_237a_pentecost; + Alcotest.test_case "237(f): Vigil of the Ascension" `Quick test_237f_ascension_vigil; + Alcotest.test_case "237(f): Vigil of Pentecost" `Quick test_237f_pentecost_vigil; + Alcotest.test_case "237(d): St John within the Nativity octave" `Quick + test_237d_nativity_octave_saint; + Alcotest.test_case "237(d): Easter Tuesday" `Quick test_237d_easter_week_feria; + Alcotest.test_case "238(b): Vigil of St Lawrence" `Quick test_238b_omissible_vigil; + Alcotest.test_case "Nativity Vigil excluded by structural inference, not literal 238(b)" `Quick + test_nativity_vigil_excluded_by_inference; + Alcotest.test_case "238(c)/RG23: Ash Wednesday" `Quick test_238c_ash_wednesday; + Alcotest.test_case "238(c)/RG23: Good Friday" `Quick test_238c_good_friday; + Alcotest.test_case "237(g): BVM Saturday Office" `Quick test_237g_bvm_saturday; + Alcotest.test_case "237(e): 2 January, a Christmastide feria" `Quick test_237e_christmastide_feria; + Alcotest.test_case "237(b): an ordinary Class2 Sunday" `Quick test_237b_ordinary_class2_sunday; + Alcotest.test_case "237(b)'s own exception: Septuagesima Sunday" `Quick test_237b_septuagesima_exception; + Alcotest.test_case "237(b)'s own exception: Sexagesima Sunday" `Quick test_237b_sexagesima_exception; + Alcotest.test_case "237(c): a sanctoral feast (Lawrence)" `Quick test_237c_sanctoral_feast; + Alcotest.test_case "Passion Sunday is not a festum for 237(c)" `Quick test_passion_sunday_not_a_festum; + Alcotest.test_case "Palm Sunday is not a festum for 237(c)" `Quick test_palm_sunday_not_a_festum; + Alcotest.test_case "238(d): All Souls' Day (transferred)" `Quick test_238d_all_souls; + Alcotest.test_case "431(c): Holy Thursday" `Quick test_431c_holy_thursday; + Alcotest.test_case "431(c): the Easter Vigil Mass" `Quick test_431c_easter_vigil; + Alcotest.test_case "432(b): Advent I Sunday, violet" `Quick test_432b_violet_sunday; + Alcotest.test_case "432(d): All Souls' Day (transferred)" `Quick test_432d_all_souls; + Alcotest.test_case "431(a): mirrors [te_deum]=true" `Quick test_431a_mirrors_te_deum_true; + Alcotest.test_case "432(a): mirrors [te_deum]=false" `Quick test_432a_mirrors_te_deum_false; + Alcotest.test_case "Rogation Monday: white -> Gloria said (2028)" `Quick test_rogation_monday_gloria_2028; + Alcotest.test_case "Rogation Tuesday: white -> Gloria said (2028)" `Quick test_rogation_tuesday_gloria_2028; + Alcotest.test_case "domain sanity: every violet day has [gloria]=false (sample)" `Quick + test_domain_violet_implies_no_gloria_sample; + Alcotest.test_case "domain sanity: every Requiem day has [gloria]=false (sample)" `Quick + test_domain_requiem_implies_no_gloria_sample; + Alcotest.test_case "domain sweep 1583..9999: violet/Requiem invariants, committed not sampled" + `Slow test_exhaustive_gloria_domain_sweep; + Alcotest.test_case "RG 111(a): an ordinary-only Low-Mass set is empty at Sung Mass" `Quick + test_rg111a_ordinary_only_dropped; + Alcotest.test_case "RG 111(a): a privileged commemoration survives at Sung Mass" `Quick + test_rg111a_privileged_kept; + Alcotest.test_case "preface: Good Friday, no Mass" `Quick test_preface_good_friday_no_mass; + Alcotest.test_case "RG 499: All Souls' Day (transferred)" `Quick test_preface_499_all_souls; + Alcotest.test_case "RG 487(a): the Exaltation of the Holy Cross" `Quick test_preface_487a_exaltation; + Alcotest.test_case "RG 487(a): the Most Precious Blood" `Quick test_preface_487a_precious_blood; + Alcotest.test_case "RG 491: the Sacred Heart" `Quick test_preface_491_sacred_heart; + Alcotest.test_case "RG 492: Christ the King" `Quick test_preface_492_christ_the_king; + Alcotest.test_case "RG 490(a): Ascension Day" `Quick test_preface_490a_ascension_day; + Alcotest.test_case "RG 494(a): Trinity Sunday" `Quick test_preface_494a_trinity_sunday; + Alcotest.test_case "RG 496: St Joseph, Spouse of the BVM" `Quick test_preface_496_joseph_spouse; + Alcotest.test_case "RG 496: St Joseph the Workman" `Quick test_preface_496_joseph_workman; + Alcotest.test_case "RG 495: the Assumption (marian_slugs)" `Quick test_preface_495_assumption; + Alcotest.test_case "RG 495: the BVM Saturday Office (subject=Bvm)" `Quick + test_preface_495_bvm_saturday_office; + Alcotest.test_case "RG 484(a): the Purification" `Quick test_preface_484a_purification; + Alcotest.test_case "RG 484(a): Christmas Day itself" `Quick test_preface_484_nativity_day; + Alcotest.test_case "RG 484(b): St Stephen, inside the Nativity octave" `Quick + test_preface_484_stephen_in_octave; + Alcotest.test_case "RG 484(a): 1 January, the Octave Day" `Quick test_preface_484_jan1_octave_day; + Alcotest.test_case "RG 484(b): 3 January, the extra de-Tempore days" `Quick test_preface_484b_jan2to5; + Alcotest.test_case "RG 484(b): St John the Evangelist, inside the Nativity octave" `Quick + test_preface_484b_overrides_apostle_in_octave; + Alcotest.test_case "RG 497: St Barnabas" `Quick test_preface_497_barnabas; + Alcotest.test_case "RG 497: Sts Peter & Paul" `Quick test_preface_497_peter_paul; + Alcotest.test_case "RG 497: Sts Philip & James, inside the Easter window" `Quick + test_preface_497_philip_james_inside_easter_window; + Alcotest.test_case "RG 497: the Conversion of St Paul, not his own natalicium" `Quick + test_preface_497_conversion_of_st_paul; + Alcotest.test_case "RG 485(a): Epiphany Day" `Quick test_preface_485a_epiphany_day; + Alcotest.test_case "RG 485(a): the Commemoration of the Baptism of the Lord" `Quick + test_preface_485a_baptism_commemoration; + Alcotest.test_case "RG 485(b): Holy Family Sunday, inside the 7-13 January window" `Quick + test_preface_485b_holy_family_sunday; + Alcotest.test_case "RG 486(a): Ash Wednesday" `Quick test_preface_486_ash_wednesday; + Alcotest.test_case "RG 486: the Saturday before Passion Sunday I" `Quick + test_preface_486_lent_saturday_boundary; + Alcotest.test_case "RG 487: Passion Sunday I" `Quick test_preface_487_passion_sunday; + Alcotest.test_case "RG 487: Palm Sunday" `Quick test_preface_487_palm_sunday; + Alcotest.test_case "RG 487: Holy Thursday" `Quick test_preface_487_holy_thursday; + Alcotest.test_case "RG 489(a): the Easter Vigil Mass" `Quick test_preface_489_easter_vigil_mass; + Alcotest.test_case "RG 489(a): Easter Sunday" `Quick test_preface_489_easter_sunday; + Alcotest.test_case "RG 489(b): the vigil of the Ascension" `Quick test_preface_489_ascension_vigil; + Alcotest.test_case "RG 490(b): the Friday after Ascension" `Quick test_preface_490b_post_ascension_feria; + Alcotest.test_case "RG 490(b): the Sunday after Ascension" `Quick + test_preface_490b_sunday_after_ascension; + Alcotest.test_case "RG 493(a): the vigil of Pentecost" `Quick test_preface_493_pentecost_vigil; + Alcotest.test_case "RG 493(a): Pentecost Sunday" `Quick test_preface_493_pentecost_sunday; + Alcotest.test_case "RG 493(a): the Ember Saturday within the Pentecost octave" `Quick + test_preface_493_ember_saturday; + Alcotest.test_case "RG 494(b): Advent I Sunday" `Quick test_preface_494b_advent_sunday; + Alcotest.test_case "RG 494(b): an ordinary Time-after-Pentecost Sunday" `Quick + test_preface_494b_ordinary_class2_sunday; + Alcotest.test_case "RG 494(b): All Saints' Day, Class1, still Trinity" `Quick + test_preface_494b_all_saints_class1_sunday; + Alcotest.test_case "RG 498: Corpus Christi (no proper of its own)" `Quick test_preface_498_corpus_christi; + Alcotest.test_case "RG 498: a plain sanctoral saint (Lawrence)" `Quick test_preface_498_plain_saint; + Alcotest.test_case "preface domain sanity: Christmastide/Paschaltide/Lent window invariants (sample)" + `Quick test_preface_season_invariants_sample; + Alcotest.test_case + "preface domain sweep 1583..9999: window invariants, committed not sampled" `Slow + test_exhaustive_preface_season_domain_sweep; + Alcotest.test_case "conversion-of-st-paul preface blast radius (sample)" `Quick + test_conversion_of_st_paul_preface_sample; + Alcotest.test_case "conversion-of-st-paul preface blast radius 1583..9999, committed not sampled" `Slow + test_exhaustive_conversion_of_st_paul_preface_sweep ] ) diff --git a/test/test_validate.ml b/test/test_validate.ml index 8b3014a..3da8fbb 100644 --- a/test/test_validate.ml +++ b/test/test_validate.ml @@ -300,15 +300,16 @@ module Synthetic = struct defaults against the default empty [layer], since nothing ever contests the temporal office there) so the resolution fixtures further down can override them without duplicating every other field. *) - (* Most fixtures here exercise no citations -- [readings] is a harmless - constant [], the same role the other placeholder defaults above play, - and {!Validate}'s own citation checks are gated on a rite producing SOME - citation somewhere, so a constant [] leaves them entirely dormant. Task + (* Most fixtures here exercise no citations and no formulary -- [readings] + is a harmless constant [(None, [])], the same role the other + placeholder defaults above play, and {!Validate}'s own citation and + formulary checks are gated on a rite producing SOME citation/formulary + somewhere, so a constant [(None, [])] leaves them entirely dormant. Task 10 makes it overridable ([?readings] below) so the citation fixtures at the end of this file can drive those checks directly, exactly as every - other check here is driven -- rather than leaving two kernel checks with - no committed proof that they can fire at all. *) - let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = [] + other check here is driven -- rather than leaving kernel checks with no + committed proof that they can fire at all. *) + let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = (None, []) (* The shape {!Validate} accepts: exactly one First and one Gospel. The references are deliberately nonsense -- these fixtures assert SHAPE, @@ -317,16 +318,35 @@ module Synthetic = struct [ { Citation.part = Citation.First; reference = "Synth 1:1" }; { Citation.part = Citation.Gospel; reference = "Synth 2:2" } ] + (* The formulary equivalent of [well_formed_citations] above -- shape only, + never rubrically meaningful content. *) + let well_formed_formulary = + { Colitur_kernel.Mass_formulary.said = Some (Slug.of_string_exn "syn-formulary"); + via = Colitur_kernel.Mass_formulary.Own_slug } + + (* No fixture here exercises the Creed, Gloria or preface rubrics -- a + rite that has not implemented them returns [false]/[None] explicitly, + {!Rite.t.creed}/{!Rite.t.gloria}/{!Rite.t.preface}'s own documented + default. Made overridable ([?creed]/[?gloria]/[?preface] below) on + the same footing as [?readings] just above, for Task 6's own + fixtures. *) + let creed ~temporal:_ ~observed:_ ~date:_ = false + let gloria ~temporal:_ ~observed:_ ~date:_ = false + let preface ~temporal:_ ~observed:_ ~date:_ = None + let rite ?(vocab = vocab) ?(anchors = fun _ -> []) ?(season_runs = [ A; B ]) ?(rules = rules) - ?(transfer_target = fun _ origin _ -> origin) ?(readings = readings) temporal : - (season, rank) Rite.t = + ?(transfer_target = fun _ origin _ -> origin) ?(readings = readings) ?(creed = creed) + ?(gloria = gloria) ?(preface = preface) temporal : (season, rank) Rite.t = { Rite.id = "synthetic"; vocab; year_start; temporal; anchors; rules; season_runs; (* Not a Roman rite, but a Rite.t must supply SOME Easter now that movable Date_spec variants exist. The Gregorian one is as good as any for a fixture; nothing here is Easter-relative, so the value is never actually read. *) easter = Colitur_kernel.Computus.gregorian_easter; - transfer_target; readings } + (* Not a Roman rite either, so no bissextile-doubling convention: + identity, {!Rite.t.fixed_key}'s own documented default. *) + fixed_key = (fun d -> Some (D.month d, D.day d)); + transfer_target; readings; creed; gloria; preface } (* Empty by default: every check built before Task 12 exercises the TEMPORAL-only pass, where an empty layer is exactly the fixture that @@ -759,7 +779,7 @@ let test_citations_silent_without_a_lectionary () = (* The positive: well-formed citations on every day report nothing. *) let test_citations_clean_when_well_formed () = - let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = well_formed_citations in + let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = (None, well_formed_citations) in let fs = run ~readings good in Alcotest.(check bool) "neither citation check fires when every day carries First + Gospel" false (has_check "citations" fs || has_check "citations-unresolved" fs) @@ -769,7 +789,7 @@ let test_citations_clean_when_well_formed () = plausibly produce -- half a lookup succeeding. *) let test_citations_fires_on_a_lone_epistle () = let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = - [ { Citation.part = Citation.First; reference = "Synth 1:1" } ] + (None, [ { Citation.part = Citation.First; reference = "Synth 1:1" } ]) in Alcotest.(check bool) "citations check fires when a day carries an Epistle but no Gospel" true (has_check "citations" (run ~readings good)) @@ -780,7 +800,7 @@ let test_citations_fires_on_a_lone_epistle () = even though the day is otherwise a well-formed pair. *) let test_citations_fires_on_an_out_of_scope_part () = let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = - { Citation.part = Citation.Tract; reference = "Synth 3:3" } :: well_formed_citations + (None, { Citation.part = Citation.Tract; reference = "Synth 3:3" } :: well_formed_citations) in Alcotest.(check bool) "citations check fires when a part outside First/Gospel appears" true (has_check "citations" (run ~readings good)) @@ -792,7 +812,7 @@ let test_citations_fires_on_an_out_of_scope_part () = this file singles out. *) let test_citations_unresolved_fires_on_a_gap () = let readings ~observed:_ ~temporal:_ ~date ~temporal_at:_ = - if D.compare date target = 0 then [] else well_formed_citations + if D.compare date target = 0 then (None, []) else (None, well_formed_citations) in Alcotest.(check bool) "citations-unresolved fires when one day of the year resolves nothing" true (has_check "citations-unresolved" (run ~readings good)); @@ -801,6 +821,79 @@ let test_citations_unresolved_fires_on_a_gap () = Alcotest.(check bool) "the well-formedness check stays silent on a pure coverage gap" false (has_check "citations" (run ~readings good)) +(* ---------------------------------------------------------------------- *) +(* The formulary invariant (Task 3, celebrant-rubrics-phase1): the same *) +(* negative-path discipline the citation checks above already hold *) +(* themselves to, driven through the same synthetic fixture. Model on the *) +(* citations trio above -- "same shape, its own name" is what {!Validate} *) +(* itself now does, so the tests proving it can fire follow the same *) +(* pattern. *) +(* ---------------------------------------------------------------------- *) + +(* The gate: a rite that resolves no formulary at all (the default constant + [(None, [])]) must report nothing -- not "usually", not "on this year". *) +let test_formulary_silent_without_a_lectionary () = + let fs = run good in + Alcotest.(check bool) "no formulary check fires for a rite with no readings at all" false + (has_check "formulary" fs) + +(* The positive: a formulary on every day reports nothing. *) +let test_formulary_clean_when_well_formed () = + let readings ~observed:_ ~temporal:_ ~date:_ ~temporal_at:_ = + (Some well_formed_formulary, well_formed_citations) + in + Alcotest.(check bool) "formulary check stays silent when every day resolves one" false + (has_check "formulary" (run ~readings good)) + +(* The coverage gap: a rite that resolves a formulary on most days but falls + through on one. On real EF data this has no witness at all (Task 3's own + [test_every_day_has_a_formulary] below confirms it directly), so this + fixture is the only thing that holds it honest. *) +let test_formulary_fires_on_a_gap () = + let readings ~observed:_ ~temporal:_ ~date ~temporal_at:_ = + if D.compare date target = 0 then (None, []) + else (Some well_formed_formulary, well_formed_citations) + in + Alcotest.(check bool) "formulary check fires when one day of the year resolves none" true + (has_check "formulary" (run ~readings good)) + +(* ---------------------------------------------------------------------- *) +(* Direct real-EF-data coverage (Task 3 brief): every day of every year in *) +(* the sample resolves a formulary, the same discipline the "citations" *) +(* checks already hold EF to -- asserted directly against *) +(* [Liturgical_day.t] rather than through [Validate.run]'s failure list, *) +(* so a bug in [Validate]'s own gating could not hide this gap. *) +(* ---------------------------------------------------------------------- *) + +(* 2005-2050: the same 46-year sample test_rite_ef.ml's own [sample_years] + uses, for the same reason -- non-trivial, deterministic, and already the + project's differential-testing window (CLAUDE.md). Defined locally + rather than shared: test executables in this project cross-reference + only [.suite] values (test_colitur.ml), never each other's internal + helpers. *) +let sample_years = + let rec range a b = if a > b then [] else a :: range (a + 1) b in + range 2005 2050 + +let year_of y = Colitur_kernel.Calendar.year real_ef_rite real_ef_layer y + +(* Every day of every year resolves a formulary, for the same reason + [Validate] already asserts exactly one First and one Gospel: a day that + says no Mass at all is a defect, not a gap. Mirrors the "citations" + check. *) +let test_every_day_has_a_formulary () = + let missing = ref [] in + List.iter + (fun y -> + Array.iter + (fun (d : (_, _) Colitur_kernel.Liturgical_day.t) -> + if d.Colitur_kernel.Liturgical_day.formulary = None then + missing := + Colitur_kernel.Date.to_iso8601 d.Colitur_kernel.Liturgical_day.date :: !missing) + (year_of y)) + sample_years; + Alcotest.(check (list string)) "every day resolves a formulary" [] !missing + let suite = ( "Validate", [ Alcotest.test_case "landmark years" `Quick test_landmark_years; @@ -830,6 +923,13 @@ let suite = test_citations_fires_on_an_out_of_scope_part; Alcotest.test_case "citations-unresolved fires on a gap" `Quick test_citations_unresolved_fires_on_a_gap; + Alcotest.test_case "formulary silent without a lectionary" `Quick + test_formulary_silent_without_a_lectionary; + Alcotest.test_case "formulary clean when well formed" `Quick + test_formulary_clean_when_well_formed; + Alcotest.test_case "formulary fires on a gap" `Quick test_formulary_fires_on_a_gap; + Alcotest.test_case "every day (2005-2050) resolves a formulary" `Quick + test_every_day_has_a_formulary; Alcotest.test_case "lost fires on resolution exception" `Quick test_lost_fires_on_resolution_exception; Alcotest.test_case "duplicated fires" `Quick test_duplicated_fires; Alcotest.test_case "unconverged fires" `Quick test_unconverged_fires; diff --git a/tools/bootstrap_lectionary.ml b/tools/bootstrap_lectionary.ml index 7df290b..1e9b8ed 100644 --- a/tools/bootstrap_lectionary.ml +++ b/tools/bootstrap_lectionary.ml @@ -637,6 +637,75 @@ let trinity_week_entries = lectionary has been bitten by before. *) [ "monday"; "tuesday"; "wednesday"; "friday"; "saturday" ] +(* RG 299's own escape clause, second instance (celebrant-rubrics-phase1, + Bug 2, 2026-08-22). The Proprium de Tempore carries an explicit + marginal rubric immediately after the Ascension's own Mass propers, + before "Dominica post Ascensionem" begins (scan1.txt:20749-20754, both + scans corroborate): "Diebus a feria VI post Ascensionem usque ad + feriam VI ante vigiliam Pentecostes inclusive, dicitur Missa de festo + Ascensionis, cum Gloria et praefatione de Ascensione, sine Credo et + Communicantes proprio" -- on the days from the Friday after the + Ascension until the Friday before the Vigil of Pentecost INCLUSIVE, + the MASS OF THE FEAST OF THE ASCENSION is said (with the Gloria and + the Ascension preface, without the Creed and the proper + Communicantes). Corroborated independently by RG 490(b) (LT.txt:3981- + 3985), which assigns the Ascension preface "tamquam de Tempore" to + every Mass in that same window lacking a proper preface of its own -- + consistent only if the Mass repeated there is the Ascension's own, + not a numbered Sunday's (which would need no preface override at + all). + + Witnessed directly, not merely inferred from the rubric: the LMS Ordo + prints "Mass of the Ascension" literally, across all three fixture + windows this project has built (2023-2024: 1 day; 2024-2025: 3 days; + 2025-2026: 2 days -- data/ef/expected-divergences-lms.sexp's own L2, + closed by this entry), on EVERY affected day in BOTH the remainder of + Ascension's own week and the following week, not only the first -- + ruling out the alternative reading that the second week instead + resumes "Dominica post Ascensionem"'s own Mass. The FIUV Ordo's own + title convention for these days (2025-2026 fixture, 2026-05-21/22, + "Feria V/VI Dom. post Ascensionem, De ea") could look like the + opposite at a glance -- it is not: FIUV's title names which WEEK a + feria belongs to (a bookkeeping label, the same role colitur's own + week-numbered slug plays), while its own [praef] field for those + exact two days independently reads "Ascensionis", confirming the Mass + actually said is still the Ascension's, exactly as the marginal + rubric and RG 490(b) both require. + + The window's two Saturdays (Easter+41, Easter+48) are DELIBERATELY + NOT given entries here. Easter+48 is the Vigil of Pentecost, a named + day with its own Mass ({!Rite_ef.Temporal_ef.named}), outside the + rubric's own "usque ad feriam VI" upper bound. Easter+41 is an + ordinary IV-class Saturday, so {!Rite_ef.Lectionary_ef.readings}'s + own RG 78/RG 309(a) votive-Mass-of-Our-Lady-on-Saturday branch ALWAYS + intercepts it before step 2 is ever reached (checked directly: + [is_bvm_saturday_office] fires unconditionally on any unoccupied + Class4 Saturday, which every ordinary Paschaltide Saturday is) -- an + entry for either Saturday slug would be dead data that + [assert_reachable] cannot catch (both slugs it would name ARE real, + reachable Temporal_ef offices; the shadowing happens one level up, in + [readings]' own step ordering, not in slug reachability). + + Six ferias, matching the Ascension's own citation already given above + (Act. 1, 1-11 / Marc. 16, 14-20, scan1.txt:20701-20730, + [ef-ascension]'s own entry): the one remaining non-Saturday day of + Ascension's own week (Easter+40) and the five weekdays of the + following week (Easter+43..47), bounded above by that week's own + Friday -- the Saturday after it is the Vigil of Pentecost, named, + never reaching this table. *) +let ascension_week_citations = pair ~first:"Acts 1:1-11" ~gospel:"Mark 16:14-20" + +let ascension_week_entries = + List.map + (fun slug -> (slug_or_die slug, ascension_week_citations)) + [ "ef-easter-6-friday"; + "ef-easter-7-monday"; + "ef-easter-7-tuesday"; + "ef-easter-7-wednesday"; + "ef-easter-7-thursday"; + "ef-easter-7-friday" + ] + let epiphanytide_opening_entries = List.concat_map (fun (family, wds, cs) -> @@ -789,6 +858,7 @@ let () = translated @ vigil_entries @ holy_week_entries @ passion_tuesday_entry @ ember_saturday_corrections @ nativity_octave_entries @ holy_name_entries @ epiphanytide_opening_entries @ trinity_week_entries @ movable_feast_entries + @ ascension_week_entries in assert_reachable entries; let lect = @@ -23,6 +23,20 @@ (name bootstrap_lectionary) (libraries colitur_kernel rite_ef unix sexplib)) +; Task 6 (2026-08-21-colitur-celebrant-rubrics-phase1): turns pdftotext's +; -layout dump of the Latin Mass Society Ordo into test/fixtures/ +; lms-ordo-2024-2025.sexp. Run via `dune exec tools/extract_lms_ordo.exe -- +; <pdftotext-layout.txt> <source.pdf> <dest.sexp>`. Same `unix`-for- +; `sha256sum` usage as the two bootstrap executables above; `colitur_kernel` +; only, no `rite_ef` -- this tool validates dates through `Date.make` but +; reads no EF-specific vocabulary. +(executable + (name extract_lms_ordo) + (modules extract_lms_ordo) + (libraries colitur_kernel unix sexplib) + (preprocess + (pps ppx_sexp_conv))) + ; check_citations.py's own self-test (test_check_citations.py). Python, not ; OCaml, so it cannot be a `(test ...)` stanza -- an alias rule invoking it ; directly is dune's own documented shape for a non-OCaml check. Wired into @@ -41,3 +55,16 @@ (deps check_citations.py test_check_citations.py) (action (run python3 test_check_citations.py))) + +; Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1): turns +; pdftotext's -layout dump of the FIUV universal Ordo into +; test/fixtures/fiuv-ordo-2025-2026.sexp. Run via `dune exec +; tools/extract_fiuv_ordo.exe -- <pdftotext-layout.txt> <source.pdf> +; <dest.sexp>`. Same `unix`-for-`sha256sum` usage as extract_lms_ordo.ml; +; `colitur_kernel` only, no `rite_ef` -- same reasoning, dates only. +(executable + (name extract_fiuv_ordo) + (modules extract_fiuv_ordo) + (libraries colitur_kernel unix sexplib) + (preprocess + (pps ppx_sexp_conv))) diff --git a/tools/extract_efdotorg_ordo.py b/tools/extract_efdotorg_ordo.py new file mode 100644 index 0000000..05ef014 --- /dev/null +++ b/tools/extract_efdotorg_ordo.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python3 +# tools/extract_efdotorg_ordo.py -- efdotorg-preface task +# (2026-08-24-colitur-celebrant-rubrics-phase1). Turns the ALREADY-PARSED +# extraordinaryform.org corpus (docs/research/ordo/ordo-2024-2027.json, +# 1091 days, produced by docs/research/ordo/parse_ordo.py and audited for +# fidelity in .superpowers/ordo-fidelity-report.md -- 1091/1091 against an +# independently-written parser) into three sexp fixtures, +# test/fixtures/efdotorg-ordo-{2024-2025,2025-2026,2026-2027}.sexp, one row +# per calendar day, mirroring how tools/extract_fiuv_ordo.ml and +# tools/extract_lms_ordo.ml shape their own fixtures. +# +# PYTHON, NOT OCAML -- same reasoning tools/extract_missalemeum_oracle.py's +# own header already gives: there is no JSON library in this project's +# frozen deps (dune alcotest qcheck qcheck-alcotest sexplib ppx_sexp_conv), +# and hand-writing one is out of scope ("no hand-written JSON parser" is +# about colitur's OWN sexp format, not a licence to reimplement JSON). The +# JSON itself is already the parsed artefact ("do not rebuild the parser" -- +# this script does not re-read the PDFs at all, only the JSON parse_ordo.py +# already produced from them). +# +# Usage: +# python3 tools/extract_efdotorg_ordo.py \ +# docs/research/ordo/ordo-2024-2027.json test/fixtures +# +# Writes the three fixtures named above into the given output directory. +# +# --------------------------------------------------------------------------- +# CHARACTERISATION (re-derived independently against the live JSON below, +# not copied from .superpowers/ordo-fidelity-report.md's own prose summary +# -- that report's own filter was RE-RUN here and its counts reproduced +# exactly, which is the independent confirmation, not a citation of trust): +# +# 1. THE MENU TRAP (element [0] is not reliably the day's own office). +# Re-derived over the whole 1091-day JSON: walk each day's Mass-option +# list; skip a leading entry whose `mass` starts with "Requiem:" (a +# votive Mass for the Dead, listed ahead of the real office on an +# unimpeded low-class day -- 99 instances, confirmed never the SOLE +# option and never followed by a second Requiem entry); then, if the +# NEXT entry's `mass` starts with "and " (a preliminary rite -- Blessing +# of Ashes/Palms, Candlemas, Holy Saturday's daytime office -- joined to +# its real companion Mass by that literal prefix), treat that next entry +# as the office instead (12 instances). 99 + 12 = 111, exactly the +# figure ordo-fidelity-report.md's own independent audit already found +# -- reproduced, not merely trusted. +# +# 2. THE "CHRIST THE KING" CLASSIFIER GAP -- a NEW finding, not in the +# prior fidelity audit. Of the 1091 office-selected rows, exactly 6 have +# `preface: null`: 3 Good Friday (genuinely no preface -- the +# 1955-restored Holy Week's Good Friday has no Mass at all, RG 28) and 3 +# Christ the King (25/26/31 October across the three editions). The +# latter is a real extraction-classifier gap, not a source blank: +# docs/research/ordo/parse_ordo.py's own hardcoded `PREFACES` set (its +# module-level constant) does not include "Christ the King" as a +# recognised preface name, so its own `opt()` function's `pref = f[0] if +# f and f[0] in PREFACES else None` falls through and files the literal +# string "Christ the King" into `comms` instead of `preface` -- checked +# directly against all three instances, `comms == ['Christ the King']` +# on every one, no other None-preface row has this shape. RECOVERED +# here (reading `comms` when `preface` is null and `comms` is exactly +# `['Christ the King']`), not silently left blank, and not a parser +# rewrite -- parse_ordo.py itself and its JSON output are untouched; +# this is a documented, characterised repair applied only inside this +# comparison-layer generator, reading a field the JSON already carries. +# +# 3. "ADVENT" IS NOT A PREFACE, AND NEITHER IS ITS MAPPING A CONSTANT. +# RG 484-499 name no Advent preface among the fourteen; this source's +# own "Advent" label is an informal convention (plausibly Novus-Ordo- +# influenced) covering BOTH of two genuinely different 1962 outcomes: +# - RG 494(b), "in dominicis Adventus... praefatio de Ss.ma +# Trinitate" -- every ADVENT SUNDAY takes the TRINITY preface as +# its own de-Tempore grant (lib/rites/rite_ef/rubrics_ef.ml's own +# [preface] function already implements this, cross-checked against +# the FIUV and LMS Ordos independently -- see that function's own +# header). Confirmed live in this JSON: "Advent" is the raw label on +# every Advent Sunday in the corpus too (11 of the 12 possible +# Advent-Sunday instances across three editions; the twelfth, +# 2024-12-08, is impeded by the Immaculate Conception, a fixed +# I-class BVM feast, and correctly carries "BVM" instead). +# - RG 498 (the residual Common) governs every Advent FERIA (a +# non-Sunday day with no proper of its own). +# So "Advent" is NOT simply "colitur's Common" (an earlier, declined +# version of this task's own reasoning) -- it is Trinity on a Sunday, +# Common otherwise, decided by the civil weekday alone (never by +# parsing this source's own text further, and never by trusting +# colitur's own answer circularly: the civil weekday is public, +# independently computable information). Encoded in the comparator +# (test/test_efdotorg_ordo.ml), not baked into this generator, because +# it needs the day's own weekday, which this fixture's `date` field +# already carries losslessly. +# +# 4. THE KNOWN VIGIL-OF-ST-LAWRENCE DEFECT (docs/research/ordo/ +# PROVENANCE-ordo-corpus.md, .superpowers/ordo-class-report.md) is +# RECONFIRMED present at the same two dates, unchanged: 2025-08-09 and +# 2027-08-09 both list "St. Romanus, Martyr" (cls 4) as the day's own +# office, with no Vigil of St Lawrence entry anywhere in either day's +# option list (2026-08-09 is a Sunday, impeding the vigil on every +# source, so it is not part of this population). NOT re-derived from +# scratch -- already fully adjudicated in the class/colour layers +# named above; carried forward here as a known fact to characterise +# against, not a new investigation. +# +# 5. TWO ALREADY-DOCUMENTED SOURCE-PDF DEFECTS (ordo-fidelity-report.md) +# do not need a fresh finding here, only a check of whether they touch +# the preface field at all -- they do not, checked directly: +# - 2027-03-03 is missing from the JSON outright (a source PDF +# row-drop); 2027-03-02 carries 03-03's own Wednesday content under +# 03-02's date instead. Both dates' own `preface` value happens to +# read "Lent" regardless of which day's content is attached (both +# are ordinary Lenten ferias in the same week), so the mislabelling +# does not propagate into a preface divergence -- checked, not +# assumed. 2027-03-03 (the missing day) is still emitted as its own +# "no data" row below (mass/cls/colour/praef all absent), the same +# shape Good Friday's genuine blank already uses, so the fixture +# keeps one row per calendar day. +# - 2026-12-13 (Gaudete Sunday) carries the wrong COLOUR/commemoration +# in the source PDF (a known, isolated editorial error, already +# allow-listed for class/colour purposes elsewhere) -- its own +# `preface` value is untouched ("Advent", exactly like every other +# Advent Sunday), confirmed directly against this JSON. +# +# 6. RULE A -- "SATURDAY OF OUR LADY" IS UNCONDITIONALLY THE OFFICE. A +# second, NEW office-selection finding, beyond the two patterns in +# finding 1 above: 38 days across the whole corpus list an entry whose +# `mass` is exactly "Saturday of Our Lady" (RG 78's own votive BVM +# Saturday Office) ALONGSIDE another named saint's own optional Mass +# (structurally identical to the Requiem pattern -- a low-class +# "priest's menu" option printed ahead of, or beside, the real office). +# Checked EXHAUSTIVELY, not sampled: on all 38, colitur's own real +# computed office is this BVM Office (`dune exec bin/main.exe -- +# rubrics <year>`, cross-checked against `day`'s own "Officium sanctae +# Mariae in sabbato" line) -- including the ONE case where a further +# listed entry outranks every OTHER candidate on the page by class +# number (18 January 2025's own "Chair of St. Peter (for Church +# Unity)", cls 2): that entry is not even part of the 1962 General +# Roman Calendar at all (the single Roman Chair-of-Peter feast was +# consolidated to 22 February by the 1960 Rubricae Generales; colitur's +# own sanctoral data has no 18 January entry for it, and neither the +# LMS nor the FIUV Ordo -- both already-validated witnesses -- ever +# name it), so its presence does not defeat the rule. UNCONDITIONAL, +# not merely "no lower-class competitor": empirically the simpler, +# equally correct reading of the whole 38-instance population. +# +# (USA)/(Can)-TAGGED REGIONAL INDULTS were checked and found NEVER to be +# the JSON's own element [0] anywhere in the whole 1091-day corpus (0 +# instances) -- so, unlike ordo-fidelity-report.md's own +# class/colour-comparison method, THIS generator needs no indult- +# stripping step: Rules 1/6 above never reach far enough into an +# option list for an indult's presence to matter. Checked, not assumed. +# +# 7. THE RESIDUAL -- 11 rows, all 3 editions combined, 7 distinct root +# causes, every one individually adjudicated in +# data/ef/expected-divergences-efdotorg.sexp (not attempted here, a +# THIRD, generic "absorption" rule was deliberately NOT built: it would +# have resolved 2 of these 11 rows (Our Lady of Mt Carmel, 16 July) but +# ALSO wrongly mis-fired on a genuinely different shape (Ss Philip & +# James/Rogation Day, 11 May, where an equal-CLASS "Rogation Day" +# option's own [comms] names the real feast for the OPPOSITE reason -- +# an optional votive substitution, not a rank-based demotion -- and the +# JSON alone cannot distinguish the two shapes without already knowing +# colitur's own Commemoration_only/Feast status distinction, which +# would defeat the point of an independent witness). Manufacturing a +# rule that fixes 2 cases while breaking a 3rd is a worse trade than +# leaving all of them to individual adjudication. +# +# --------------------------------------------------------------------------- +import datetime +import json +import subprocess +import sys + +EDITIONS = [ + ("2024-2025", "2024-12-01", "2025-11-29"), + ("2025-2026", "2025-11-30", "2026-11-28"), + ("2026-2027", "2026-11-29", "2027-11-27"), +] +# Boundaries re-derived, not copied: both PDF-to-PDF seams are exact (no +# overlap, no gap) and 364 + 364 + 363 = 1091, the JSON's own total day +# count -- checked below in main(), not merely asserted here. + + +def sha256_of(path): + out = subprocess.run(["sha256sum", path], capture_output=True, text=True, check=True) + return out.stdout.split()[0] + + +def pick_office(opts): + """The menu-trap filter -- see this module's own header, findings 1 and 6.""" + i = 0 + if opts[0]["mass"].startswith("Requiem:"): + i = 1 + if i < len(opts) - 1 and opts[i + 1]["mass"].startswith("and "): + i += 1 + # Rule A (finding 6): "Saturday of Our Lady", whenever listed at all, IS + # the office -- checked exhaustively over all 38 instances across the + # whole 1091-day corpus (not a sample): colitur's own RG 78 BVM-Saturday + # Office wins on every single one, including the one case where a + # competing entry outranks every OTHER real candidate on the page (a + # Chair-of-St-Peter, 18 January, entry that is not even part of the + # 1962 calendar at all -- see finding 6). No guard/condition needed; + # unconditional preference is the empirically safe rule. + bvm_saturday = next((o for o in opts if o["mass"] == "Saturday of Our Lady"), None) + if bvm_saturday is not None: + return bvm_saturday + return opts[i] + + +def sexp_string(s): + out = [] + for ch in s: + b = ch.encode("utf-8") + if ch == '"': + out.append('\\"') + elif ch == "\\": + out.append("\\\\") + elif len(b) == 1 and 32 <= b[0] < 127: + out.append(ch) + else: + for byte in b: + out.append("\\%03d" % byte) + return '"' + "".join(out) + '"' + + +def sexp_opt_string(s): + return "(" + sexp_string(s) + ")" if s is not None else "()" + + +def sexp_opt_int(n): + return f"({n})" if n is not None else "()" + + +def daterange(lo, hi): + d = datetime.date.fromisoformat(lo) + end = datetime.date.fromisoformat(hi) + while d <= end: + yield d.isoformat() + d += datetime.timedelta(days=1) + + +def build_rows(data, lo, hi): + rows = [] + for date in daterange(lo, hi): + opts = data.get(date) + if opts is None: + # 2027-03-03 only -- see this module's own header, finding 5. + rows.append((date, None, None, None, None)) + continue + office = pick_office(opts) + praef = office["preface"] + if praef is None and office.get("comms") == ["Christ the King"]: + praef = "Christ the King" # RECOVERED -- see finding 2 above. + rows.append((date, office["mass"], office["cls"], office["colour"], praef)) + return rows + + +def write_fixture(out_path, label, lo, hi, rows, json_path, json_sha): + n_missing = sum(1 for r in rows if r[1] is None) + n_none_praef = sum(1 for r in rows if r[1] is not None and r[4] is None) + with open(out_path, "w") as f: + f.write(f"""; test/fixtures/efdotorg-ordo-{label}.sexp -- efdotorg-preface task +; (2026-08-24-colitur-celebrant-rubrics-phase1): the THIRD independent +; preface witness (RG 482-499), extraordinaryform.org's {label} Ordo, +; extracted from the already-parsed, fidelity-audited corpus +; docs/research/ordo/ordo-2024-2027.json (SHA-256 {json_sha}) rather than +; re-parsed from the PDF -- see tools/extract_efdotorg_ordo.py's own +; header for the full characterisation this fixture rests on (the menu- +; trap office filter, the Christ-the-King classifier-gap recovery, why +; "Advent" is not baked into a single mapping here, the known Vigil-of- +; St-Lawrence gap, and the two source-PDF defects that turn out not to +; touch this field). +; +; Generator: tools/extract_efdotorg_ordo.py -- do not hand-edit; re-run +; against the same JSON and commit the diff instead. +; python3 tools/extract_efdotorg_ordo.py {json_path} test/fixtures +; +; Source PDF (gitignored, CLAUDE.md: "docs/ is gitignored", see +; docs/research/ordo/SHA256SUMS for its own hash): {label}Ordo.pdf, +; extraordinaryform.org. +; +; COVERAGE: {len(rows)} day-rows, {lo}..{hi} (this edition's own civil-date +; span, re-derived from the JSON's own seams -- see the generator's own +; EDITIONS comment). {n_missing} row(s) are a genuine SOURCE GAP (2027-03-03 +; only, a PDF row-drop, ordo-fidelity-report.md) -- mass/cls/colour/praef +; all absent, the same shape a structurally blank day (Good Friday) uses. +; {n_none_praef} further row(s) have mass/cls/colour but no praef at all +; (Good Friday -- RG 28, no Mass in the 1955-restored Holy Week). +; +; Each row's `praef` is RAW TEXT from the day's own OFFICE (after the +; menu-trap filter, with the Christ-the-King recovery already applied) -- +; classified against {{!Colitur_kernel.Preface.t}} by +; test/test_efdotorg_ordo.ml, not here. +""") + f.write("(\n") + for date, mass, cls, colour, praef in rows: + f.write( + f" ((date {date}) (mass {sexp_opt_string(mass)}) (cls {sexp_opt_int(cls)}) " + f"(colour {sexp_opt_string(colour)}) (praef {sexp_opt_string(praef)}))\n" + ) + f.write(")\n") + print(f"wrote {len(rows)} rows to {out_path}", file=sys.stderr) + print(f"SHA-256 of {out_path}: {sha256_of(out_path)}", file=sys.stderr) + + +def main(): + if len(sys.argv) != 3: + print(f"usage: {sys.argv[0]} <ordo-2024-2027.json> <out-dir>", file=sys.stderr) + sys.exit(2) + json_path, out_dir = sys.argv[1], sys.argv[2] + with open(json_path) as f: + data = json.load(f) + json_sha = sha256_of(json_path) + + # The three windows span 1092 CALENDAR days (one more than the JSON's + # own 1091 keys, because 2027-03-03 is a genuine source gap -- see + # finding 5 above); of those, exactly 1091 must be present as JSON + # keys and exactly 1 (2027-03-03 alone) absent, or the boundaries are + # wrong. + all_dates = [d for _, lo, hi in EDITIONS for d in daterange(lo, hi)] + present = [d for d in all_dates if d in data] + missing = [d for d in all_dates if d not in data] + if len(all_dates) != 1092 or len(present) != 1091 or missing != ["2027-03-03"]: + print( + f"ERROR: edition boundaries cover {len(all_dates)} calendar days, " + f"{len(present)} present in the JSON, missing={missing} " + "(expected 1092/1091/['2027-03-03'])", + file=sys.stderr, + ) + sys.exit(1) + + for label, lo, hi in EDITIONS: + rows = build_rows(data, lo, hi) + out_path = f"{out_dir}/efdotorg-ordo-{label}.sexp" + write_fixture(out_path, label, lo, hi, rows, json_path, json_sha) + + +if __name__ == "__main__": + main() diff --git a/tools/extract_fiuv_ordo.ml b/tools/extract_fiuv_ordo.ml new file mode 100644 index 0000000..26f5b16 --- /dev/null +++ b/tools/extract_fiuv_ordo.ml @@ -0,0 +1,855 @@ +(* Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1): turns + pdftotext's -layout dump of the FIUV (Foederatio Internationalis Una + Voce) universal Ordo into test/fixtures/fiuv-ordo-2025-2026.sexp, one + row per day, 2025-11-27..2026-12-31. + + A DIFFERENT format from tools/extract_lms_ordo.ml's own LMS PDFs in + every way that matters (see docs/research/ordo/PROVENANCE-ordo-corpus.md): + UNIVERSAL (no diocesan variants to exclude at all -- one block per day, + not "the first of several"), IN LATIN, using the rubrics' own + vocabulary ("Missa pr., Gloria, sine Credo, praef. comm."), and BOTH + directions of Gloria/Credo are stated explicitly in the source's own + words ("Gloria"/"sine Gloria", "Credo"/"sine Credo") rather than by a + printed flag letter. Hand-rolled, no Str/regex (frozen deps) -- the + same String.sub/index/split_on_char discipline extract_lms_ordo.ml + already uses for a different publisher's layout. + + THE KEY STRUCTURAL FACTS this parser leans on, established during + characterisation (see the fixture's own provenance header for the + full record): + + 1. A day-start line's own FIRST token is always "<1-2 digit day>." + (e.g. "27.", "3."), immediately followed by a colour code (not + anchored on below -- colour is captured as raw prose, never parsed + into a closed set, because a few real days use a COMPOUND colour + ("Viol. in Off., Alb. in Missa." on Holy Thursday) or drop the + token to a blank cell entirely (13 December 2026, a rendering + quirk) -- neither is needed for anything this task compares). + + 2. Month headers/running-footers name a month EITHER in English with a + trailing ROMAN-NUMERAL year ("November MMXXV", the book's own first + two months only) OR bare in Latin with no year at all + ("Januarius", "Februarius", ... every month after). The English + Nov/Dec spellings happen to be IDENTICAL to their Latin + equivalents, so one 12-entry table covers both vocabularies. + CHARACTERISATION FINDING: the SECOND header ("December MMXV") is a + publisher-side TYPO -- MMXV is 2015, ten years off, contradicted by + every neighbouring date and by month-order inference alone. This + parser therefore reads a Roman-numeral year ONLY off the very + FIRST header encountered (the anchor) and tracks every subsequent + month purely by wraparound inference (increment the year exactly + once, at the Dec->Jan transition) -- the typo is never read at all, + not merely tolerated. + + 3. Every real Mass rubric line starts with the literal token "Missa" + (401 of ~400 real day-blocks, confirmed structurally). A SECOND, + alternate Mass option, when the day offers one, is introduced by + the CAPITALISED two-token sequence "Vel Missa" -- never bare lower- + case "vel" alone, which is the ordinary Latin conjunction "or" and + appears constantly inside ordinary prose (e.g. "praef. comm. vel de + Martyribus", part of ONE preface's own text, not a second Mass + option) -- so only "Vel Missa", both tokens, anchors a real + alternate-option boundary. This parser reads Gloria/Credo/praef. + from the FIRST Mass option only, bounded above by whichever comes + first: "Vel Missa" or "VESPERAE"/"VESPERA" -- the identical + "day's own PRIMARY office, not a menu entry" discipline + extract_lms_ordo.ml already uses for the LMS diocesan-variant + colon boundary. + + 4. SUBSTRING TRAP, found and defended against: "Gloria" is also the + first word of "Gloria Patri" (the psalm doxology, "Glory be to the + Father"), a DIFFERENT liturgical unit that has nothing to do with + whether the Mass's own Gloria in excelsis is said -- and it can + appear INSIDE the very Mass clause being scanned (Good Friday: + "Missa pr., (omittuntur ps. Iudica me et Gloria Patri), Gloria, + sine Credo, praef. comm." -- the real, standalone "Gloria," follows + immediately after). [find_word] below rejects any "Gloria" hit + whose very next token is "Patri", the same whole-token discipline + extract_lms_ordo.ml's own header describes for "V Mass of BVM" + being a substring of "IV Mass of BVM". + + 5. A WHOLE-SECOND-OFFICE TRAP, found and defended against + (celebrant-rubrics-phase1 Phase 2 correction, 2026-08-22, closing + data/ef/expected-divergences-fiuv.sexp's own F3): six real days + print BOTH a strict-1962 reading (a privileged Lenten/Passiontide + feria, saint reduced to a commemoration, "Off. feriale") AND, after + a literal separator token, a SECOND, complete alternative office + (the same saint kept outright under the 2020 decree Cum + Sanctissima, "Off. ordinarium", with its OWN "Ad Mat. ... Te Deum" + lessons). The separator is an en-dash, "VEL" (Latin "or"), another + en-dash, glued by pdftotext into ONE token with no internal spaces + -- "\xe2\x80\x93VEL\xe2\x80\x93" ("VEL" wrapped in en-dashes) -- + confirmed by direct byte inspection of the raw dump, NOT the same + shape as [extract_missa_fields]'s own "Vel"+"Missa" two-token + boundary above (a narrower "choice of Mass formulary within the + SAME office" marker, e.g. a Common vs a Proper Mass for one saint). + [extract_missa_fields]'s own Gloria/Credo/praef span happened to + stay correctly bounded to the PRIMARY office on all six real + instances even before this fix, because a Vespers line ("VESPER..." + -- already one of its own boundary tokens) always intervenes before + the separator in this corpus; [extract_te_deum] had NO such + protection at all -- it scans the WHOLE block's own text for "Ad + Mat." unbounded, so on these six days (whose PRIMARY office states + no "Ad Mat." of its own at all -- an ordinary privileged feria's + Matins needs no special note) it read the SECOND office's own "Ad + Mat. ... Te Deum." instead, manufacturing a same-day contradiction + that F3 first recorded as "colitur's own possible gap". [split_at_alt_office] + below cuts every block's own token array at this separator BEFORE + any field extraction runs, so every extractor now reads the PRIMARY + office only; the alternative is captured, not discarded, in its own + [alt_te_deum] field (the row type's own comment has the full + account of why only this one field, not a parallel alt_gloria/ + alt_credo/alt_class -- those three were never wrong, so widening + them now would be undirected scope creep, not a fix). + + Usage: + pdftotext -layout docs/research/ordo/fiuv-ordo-2025-2026.pdf /tmp/fiuv.txt + dune exec tools/extract_fiuv_ordo.exe -- /tmp/fiuv.txt \ + docs/research/ordo/fiuv-ordo-2025-2026.pdf \ + test/fixtures/fiuv-ordo-2025-2026.sexp *) + +open Sexplib0.Sexp_conv +module Date = Colitur_kernel.Date + +let die fmt = Printf.ksprintf (fun s -> prerr_endline ("extract_fiuv_ordo: " ^ s); exit 1) fmt + +(* Mirrored, not shared, by test/test_fiuv_ordo.ml -- tools/ and test/ + have no common .mli either could hang a shared type from, the same + reasoning extract_lms_ordo.ml's own header already gives. *) +type row = { + date : string; (** ISO-8601 *) + class_ : string option; (** raw, e.g. "III cl.", "III cl. (Priv.)", "I cl." -- [None] only if genuinely unparseable, read off the PRIMARY office alone *) + title : string; (** the day-start line's own text before the class marker, PRIMARY office alone *) + te_deum : bool option; (** [None] only if neither "Te Deum" nor "non dicitur Te Deum"/"sine Te Deum" is found WITHIN THE PRIMARY OFFICE (see [split_at_alt_office]) *) + gloria : bool option; (** PRIMARY office *) + credo : bool option; (** PRIMARY office *) + praef : string option; (** raw trailing text after "praef." within the primary Mass clause -- CAPTURED, NOT VALIDATED *) + alt_te_deum : bool option; + (** the SECOND, Cum-Sanctissima-alternative office's own Te Deum + status, when this day prints one (see [split_at_alt_office]'s + own citation) -- [None] both when the day has no such + alternative at all (394 of 400 real days) AND when it has one + but that alternative's own text doesn't state Te Deum either + (never observed live: on all six real instances the alternative + states it unnegated). Captured rather than discarded because a + FUTURE Cum-Sanctissima overlay (CLAUDE.md's own binding + decision 2 -- an addition, never core) would have exactly this + shape to compare against; not compared by anything in this + project yet. Deliberately NOT joined by an [alt_gloria]/ + [alt_credo]/[alt_class] -- see [split_at_alt_office]'s own + citation for why only this one field was ever wrong. *) +} +[@@deriving sexp] + +(* The literal separator between a day's PRIMARY (strict 1962) office and + a printed SECOND, Cum-Sanctissima-2020 alternative -- see the module + header's own point 5 for the full account of the bug this closes + (data/ef/expected-divergences-fiuv.sexp's own F3) and why it is a + DIFFERENT token from [extract_missa_fields]'s own "Vel"+"Missa" + two-token boundary. Exactly 6 occurrences in the whole corpus, + confirmed by direct grep of the raw pdftotext dump -- all 6 on the + exact dates F3 named (2026-03-06/07/09/12/21/24). *) +let alt_office_marker = "\xe2\x80\x93VEL\xe2\x80\x93" + +let split_at_alt_office tokens = + let n = Array.length tokens in + let rec go i = if i >= n then None else if tokens.(i) = alt_office_marker then Some i else go (i + 1) in + match go 0 with + | None -> (tokens, None) + | Some i -> (Array.sub tokens 0 i, Some (Array.sub tokens (i + 1) (n - i - 1))) + +(* --- tiny hand-rolled helpers, no Str/regex ------------------------------ *) + +let split_ws s = + String.split_on_char ' ' (String.map (fun c -> if c = '\t' then ' ' else c) s) + |> List.filter (fun t -> t <> "") + +let is_all_digits s = s <> "" && String.for_all (fun c -> c >= '0' && c <= '9') s + +let has_prefix ~prefix s = + String.length s >= String.length prefix && String.sub s 0 (String.length prefix) = prefix + +(* Strips ASCII trailing punctuation only (.,();) -- tokens in this source + never carry other trailing marks that matter to comparisons below. *) +let rec strip_trailing_punct s = + let n = String.length s in + if n = 0 then s + else + match s.[n - 1] with + | '.' | ',' | ')' | ';' | ':' -> strip_trailing_punct (String.sub s 0 (n - 1)) + | _ -> s + +let contains s ~sub = + let ls = String.length s and lu = String.length sub in + if lu = 0 then true + else + let rec go i = if i + lu > ls then false else if String.sub s i lu = sub then true else go (i + 1) in + go 0 + +let index_of s ~sub = + let ls = String.length s and lu = String.length sub in + if lu = 0 then Some 0 + else + let rec go i = if i + lu > ls then None else if String.sub s i lu = sub then Some i else go (i + 1) in + go 0 + +let months = + [| "Januarius"; "Februarius"; "Martius"; "Aprilis"; "Maius"; "Junius"; "Julius"; "Augustus"; "September"; + "October"; "November"; "December" |] + +let month_index name = + let rec go i = if i >= Array.length months then None else if months.(i) = name then Some (i + 1) else go (i + 1) in + go 0 + +(* Roman numerals, subtractive form -- only ever called once, on the + FIRST month header's own year token (the anchor); see the module + header on why every LATER header's own year, when present at all, is + deliberately never read. *) +let roman_value = function + | 'I' -> Some 1 | 'V' -> Some 5 | 'X' -> Some 10 | 'L' -> Some 50 | 'C' -> Some 100 | 'D' -> Some 500 + | 'M' -> Some 1000 | _ -> None + +let parse_roman s = + let n = String.length s in + let rec go i acc = + if i >= n then Some acc + else + match roman_value s.[i] with + | None -> None + | Some v -> ( + let next = if i + 1 < n then roman_value s.[i + 1] else None in + match next with + | Some nv when nv > v -> go (i + 2) (acc + nv - v) + | _ -> go (i + 1) (acc + v)) + in + if n = 0 then None else go 0 0 + +(* --- day-block scanning --------------------------------------------------- *) + +type block = { b_day : int; b_month : int; b_year : int; b_lines : string list } + +let is_day_start_line toks = + match toks with + | t :: _ :: _ when String.length t >= 2 && t.[String.length t - 1] = '.' -> + let core = String.sub t 0 (String.length t - 1) in + if is_all_digits core then + let d = int_of_string core in + if d >= 1 && d <= 31 then Some d else None + else None + | _ -> None + +(* A month running-header/footer line: first token is a recognised month + name (English Nov/Dec spelled identically to Latin), optionally + followed by a Roman-numeral year and/or a page number -- ALWAYS pure + noise for the day-block scanner (never a continuation line's own + content), but the FIRST time a given month index is seen it also + drives the [cur_month]/[cur_year] state transition. *) +let is_month_marker_line toks = match toks with m :: _ -> month_index m <> None | [] -> false + +(* Left-margin indulgence-notation codes ("Ind." = an indulgence is + available, "Plen." = a plenary one, "DFP" unexplained but structurally + identical -- all three print in the SAME left-margin column pdftotext + -layout preserves, glued onto the following content line as literal + leading tokens, the identical trap extract_lms_ordo.ml's own + [strip_left_column] already documents for the LMS PDFs' "Pl"/"Ind" + column. Found by tracing a real parse failure (8 December 2025's own + class marker split across two physical lines by "DFP" sitting between + "I" and "cl."), not assumed in advance: catalogued via a frequency + scan of every short capitalised token opening a continuation line, and + deliberately does NOT include "RM" (11 occurrences, ALSO short and + capitalised) -- checked directly, "RM" is a real citation abbreviation + ("Rubricae Missalis", e.g. "vide RM 440"), not a margin code, so + stripping it would corrupt real text for no parsing benefit. *) +let strip_left_column tokens = + let is_marker t = t = "Ind." || t = "Plen." || t = "DFP" in + let rec go = function t :: rest when is_marker t -> go rest | ts -> ts in + go tokens + +(* The malformed trailing entry's own distinctive two-token prefix, + "1st Jan" -- NOT a generic "first token is a bare 4-digit number" + check (extract_lms_ordo.ml's own approach): that generic shape false- + positived here, on real body content deep in October ("...20 augusti + / 1885, 26 augusti 1886..." -- an indulgence-decree date citation + whose line-wrap happens to put a 4-digit year token first on its own + physical line). This source's OWN tail artefact is reliably + distinguished only by its literal, unique "1st Jan" opening -- found + by tracing the false stop, not assumed in advance. *) +let is_stop_tail_line toks = match toks with "1st" :: "Jan" :: _ -> true | _ -> false + +let read_lines path = + let ic = open_in path in + let rec loop acc = match input_line ic with l -> loop (l :: acc) | exception End_of_file -> List.rev acc in + let ls = loop [] in + close_in ic; + ls + +(* --- per-block field extraction ------------------------------------------- *) + +(* First WHOLE-TOKEN hit of [word] in [tokens] starting at-or-after + [from], REJECTING a hit whose immediately-following token (stripped) + is [reject_next] -- the "Gloria Patri" trap, see the module header. + Returns the hit's own index and whether the token immediately BEFORE + it (stripped) is "sine" (a negation). *) +let find_word tokens ~from ~word ~reject_next = + let n = Array.length tokens in + let rec go i = + if i >= n then None + else if strip_trailing_punct tokens.(i) = word then + let next_is_rejected = i + 1 < n && strip_trailing_punct tokens.(i + 1) = reject_next in + if next_is_rejected then go (i + 1) + else + let negated = i > 0 && strip_trailing_punct tokens.(i - 1) = "sine" in + Some (i, negated) + else go (i + 1) + in + go from + +(* [class_]: the roman-numeral token immediately followed by a token + starting "cl" (covers "cl.", "cl.,"), whole-token matched -- never a + substring search (the same discipline the LMS extractor's own BVM + numeral anchor uses, for the identical reason: "I" is a substring of + "II"/"III"/"IV"). Also detects the trailing "(Priv.)" two tokens later. *) +let extract_class tokens = + let n = Array.length tokens in + let is_class_numeral t = t = "I" || t = "II" || t = "III" || t = "IV" in + let rec go i = + if i + 1 >= n then None + else if is_class_numeral tokens.(i) && has_prefix ~prefix:"cl" tokens.(i + 1) then + let base = tokens.(i) ^ " cl." in + if i + 2 < n && strip_trailing_punct tokens.(i + 2) = "(Priv" then Some (base ^ " (Priv.)") else Some base + else go (i + 1) + in + go 0 + +let extract_title tokens = + let n = Array.length tokens in + let is_class_numeral t = t = "I" || t = "II" || t = "III" || t = "IV" in + let rec find i = if i + 1 >= n then n else if is_class_numeral tokens.(i) && has_prefix ~prefix:"cl" tokens.(i + 1) then i else find (i + 1) in + let stop = find 0 in + String.concat " " (Array.to_list (Array.sub tokens 0 stop)) + +(* Te Deum: bounded to the "Ad Mat." .. "Ad Laudes" span specifically + (both casings occur: "Ad MAT."/"Ad Mat."/"ad Mat.", "Ad LAUDES"/ + "Ad Laudes") -- NOT the whole block, because a day can separately + mention "Te Deum" in an unrelated INDULGENCE note (31 December: "Hodie + ad solemnem recitationem hymni Te Deum, indulgentia plenaria lucrari + potest" -- about gaining an indulgence for the New Year's Eve Te Deum + of thanksgiving, not about whether it is sung at that day's own + Matins) that a whole-block search would wrongly read as a positive hit. *) +let extract_te_deum full_text = + let find_ci needles start = + List.fold_left + (fun acc needle -> + match acc with + | Some _ -> acc + | None -> ( + match index_of (String.sub full_text start (String.length full_text - start)) ~sub:needle with + | Some i -> Some (start + i) + | None -> None)) + None needles + in + match find_ci [ "Ad Mat."; "Ad MAT."; "ad Mat." ] 0 with + | None -> None + | Some mat_start -> ( + let laudes_start = + match find_ci [ "Ad Laudes"; "Ad LAUDES"; "ad Laudes" ] mat_start with + | Some i -> i + | None -> String.length full_text + in + let span = String.sub full_text mat_start (laudes_start - mat_start) in + (* TWO negative phrasings the source actually uses, found live + (celebrant-rubrics-phase1 Phase 2, 2026-08-22): "non dicitur Te + Deum" (e.g. ordinary Time-after-Pentecost ferias, 27/28 November) + AND, separately, "sine Te Deum" (e.g. every Sunday, every Ember + day, every privileged Lenten/Passiontide feria carrying a + commemoration -- Advent I, 30 November: "...3a de homilia (cum + suo R), sine Te Deum."). The ORIGINAL version of this function + checked only the first phrasing, so "sine Te Deum" fell through + to the bare "Te Deum" substring test and was wrongly read as a + POSITIVE hit -- confirmed by grepping the raw pdftotext dump + directly against a first, uncorrected run's own output: EVERY + date this bug affected showed "sine Te Deum" in the source and + [Some true] in the fixture, a 100% correlation, not a handful of + coincidences. This is the SAME "does the source negate the + hymn's own name with a DIFFERENT word than the one this parser + already checks for" shape [find_word]'s own "Gloria Patri" + substring trap already documents for Gloria -- this trap simply + went unnoticed until Phase 2 actually compared the extracted + values against colitur's own output and against the raw text by + hand, rather than only checking coverage counts. *) + if contains span ~sub:"non dicitur Te Deum" then Some false + else if contains span ~sub:"sine Te Deum" then Some false + else if contains span ~sub:"Te Deum" then Some true + else None) + +(* Gloria/Credo/praef.: bounded to the FIRST Mass option only -- from the + token "Missa" to whichever comes first: "Vel" immediately followed by + "Missa" (a real second option), or a token starting "VESPER" (Vespers + info -- a PREFIX match, not one or two hardcoded exact spellings, + found necessary by tracing a real over-capture: this source uses at + least four surface forms depending on grammatical case and whether + pdftotext renders the Æ ligature as one glyph or splits it -- + "VESPERÆ", "VESPERAS", "VESPERA" (Ad VESPERA, rare) and "VESPERÆ" + with the ligature reproduced as a single non-ASCII codepoint an exact- + string match against the two ASCII spellings alone could never catch, + which let a whole day's own trailing Vespers/Compline prose leak into + [praef] uncaught until checked against the task brief's own worked + example day, 19 September), or the end of the block. *) +let extract_missa_fields tokens = + let n = Array.length tokens in + (* [Missa] (singular, 549 of the corpus's own occurrences of any "Miss-" + word) anchors 398 of the 400 real days; the two genuine exceptions + are Good Friday and Holy Saturday, which have no Mass at all in the + 1955-restored Holy Week (matching extract_lms_ordo.ml's own + identically-shaped finding for the LMS corpus). CHRISTMAS DAY is a + THIRD, found by tracing a real false-None result: its own rubric + reads "Hodie celebrantur tres Missae pr., Gloria, Credo..." ("today + three Masses are celebrated..."), using the PLURAL "Missae"/"Missæ" + (both spellings occur across the fixture's two Christmas Days) -- + [tokens.(i) = "Missa"] alone never matches it, silently returning + [None] for Gloria/Credo/praef on the single most doctrinally + unambiguous day in the whole calendar. Widened to accept "Missae"/ + "Missæ" too, guarded against the ONE real collision risk: "Hodie + prohibentur omnes Missae defunctorum..." (a Requiem-Mass-prohibition + notice, common at the end of many day-blocks, unrelated to the + day's own Mass) also contains "Missae" -- rejected here by checking + the immediately FOLLOWING token is not "defunctorum". *) + let missa_idx = + let rec go i = + if i >= n then None + else if (tokens.(i) = "Missa" || tokens.(i) = "Missae" || tokens.(i) = "Missæ") + && not (i + 1 < n && strip_trailing_punct tokens.(i + 1) = "defunctorum") + then Some i + else go (i + 1) + in + go 0 + in + match missa_idx with + | None -> (None, None, None) + | Some m -> + let end_idx = + let rec go i = + if i >= n then n + else if tokens.(i) = "Vel" && i + 1 < n && tokens.(i + 1) = "Missa" then i + (* A THIRD, narrower alternate-Mass marker, found while auditing + for the "-VEL-" trap above (celebrant-rubrics-phase1 Phase 2 + correction, 2026-08-22): "Vel (sec. decretum <<Cum sanct.>>) + Missa ..." offers an alternate MASS FORMULARY under the 2020 + decree Cum Sanctissima WITHIN the same single printed office + (a narrower thing than [split_at_alt_office]'s own full + second-office split above -- there is no second "Ad Mat." set + of lessons here, just a second Mass choice). Checked against + the raw dump directly: 20 occurrences, ALL 20 of the + capitalised "Vel" + open-paren shape, zero false positives + (the ordinary lower-case "vel" conjunction, e.g. "praef. + comm. vel de Martyribus", never starts with an open-paren + token, so this check never fires on it). Every one of the 20 + real days already restates Gloria/Credo explicitly BEFORE + reaching this marker, so this was NEVER a live divergence + (confirmed by a direct diff of every field this fixture + compares, before and after this hardening: zero rows + changed) -- added defensively, so a FUTURE year whose + primary Mass clause happens not to restate Gloria/Credo + before this marker cannot silently read the Cum-Sanctissima + alternative's own value instead, the identical failure shape + as the "-VEL-" bug above, just not yet observed live here. *) + else if tokens.(i) = "Vel" && i + 1 < n && has_prefix ~prefix:"(" tokens.(i + 1) then i + else if has_prefix ~prefix:"VESPER" tokens.(i) then i + else go (i + 1) + in + go (m + 1) + in + let span = Array.sub tokens m (end_idx - m) in + let gloria = + match find_word span ~from:0 ~word:"Gloria" ~reject_next:"Patri" with + | Some (_, negated) -> Some (not negated) + | None -> None + in + let credo = + match find_word span ~from:0 ~word:"Credo" ~reject_next:"__never__" with + | Some (_, negated) -> Some (not negated) + | None -> None + in + let praef = + let sn = Array.length span in + let rec go i = if i >= sn then None else if strip_trailing_punct span.(i) = "praef" then Some i else go (i + 1) in + match go 0 with + | None -> None + | Some i -> + let rest = Array.to_list (Array.sub span (i + 1) (sn - i - 1)) in + if rest = [] then None else Some (String.concat " " rest) + in + (gloria, credo, praef) + +(* --- top level -------------------------------------------------------------- *) + +let () = + if Array.length Sys.argv <> 4 then + die "usage: extract_fiuv_ordo <pdftotext-layout.txt> <source.pdf> <dest.sexp>"; + let txt_path = Sys.argv.(1) in + let pdf_path = Sys.argv.(2) in + let dest = Sys.argv.(3) in + let all_lines = read_lines txt_path in + let arr = Array.of_list all_lines in + let n = Array.length arr in + let trimmed i = String.trim arr.(i) in + (* Anchor: the FIRST month-marker line carrying a parseable Roman year + -- established during characterisation to be line 47, "November + MMXXV". Search generically rather than hardcoding the line number, + so a re-extraction against a re-flowed pdftotext dump still finds it. *) + let anchor_idx, anchor_month, anchor_year = + let rec go i = + if i >= n then die "no month header with a parseable Roman-numeral year found (expected the book's own first header, e.g. \"November MMXXV\")" + else + let toks = split_ws (trimmed i) in + match toks with + | m :: y :: _ -> ( + match (month_index m, parse_roman y) with + | Some mi, Some yr when yr > 1000 -> (i, mi, yr) + | _ -> go (i + 1)) + | _ -> go (i + 1) + in + go 0 + in + let stop_idx = + let rec go i = if i >= n then n else if is_stop_tail_line (split_ws (trimmed i)) then i else go (i + 1) in + go (anchor_idx + 1) + in + Printf.printf "extract_fiuv_ordo: Ordo body lines %d..%d (of %d total), anchor %d/%d\n" anchor_idx stop_idx n + anchor_month anchor_year; + let cur_month = ref anchor_month and cur_year = ref anchor_year in + let blocks = ref [] in + let cur = ref None in + let flush () = match !cur with Some b -> blocks := b :: !blocks; cur := None | None -> () in + for i = anchor_idx + 1 to stop_idx - 1 do + let raw = trimmed i in + if raw = "" then () + else + let toks = split_ws raw in + if is_month_marker_line toks then ( + match toks with + | m :: _ -> ( + match month_index m with + | Some mi -> + if mi <> !cur_month then begin + if mi < !cur_month then incr cur_year; + cur_month := mi + end + | None -> ()) + | [] -> ()) + else + match is_day_start_line toks with + | Some day -> + flush (); + cur := Some { b_day = day; b_month = !cur_month; b_year = !cur_year; b_lines = toks } + | None -> ( + match !cur with + | None -> () + | Some b -> cur := Some { b with b_lines = b.b_lines @ strip_left_column toks }) + done; + flush (); + let blocks = List.rev !blocks in + Printf.printf "extract_fiuv_ordo: %d day-blocks parsed\n" (List.length blocks); + let rows = + List.map + (fun b -> + let date = + match Date.make ~year:b.b_year ~month:b.b_month ~day:b.b_day with + | Ok d -> d + | Error e -> die "%d/%d/%d: %s" b.b_year b.b_month b.b_day e + in + let tokens = Array.of_list b.b_lines in + (* [b_lines] tokens 0 is the day's own leading "<n>." marker -- + dropped before field extraction, kept for nothing (the day + number is already known from [b_day]). *) + let content = if Array.length tokens > 0 then Array.sub tokens 1 (Array.length tokens - 1) else tokens in + (* Cut at the "–VEL–" alternative-office boundary, if this day has + one, BEFORE any field extraction -- see [split_at_alt_office]'s + own citation. Every field below now reads the PRIMARY office + only; [alt_te_deum] alone also reads the second, when present. *) + let primary, alt = split_at_alt_office content in + let class_ = extract_class primary in + let title = extract_title primary in + let full_text = String.concat " " (Array.to_list primary) in + let te_deum = extract_te_deum full_text in + let alt_te_deum = + match alt with None -> None | Some alt_tokens -> extract_te_deum (String.concat " " (Array.to_list alt_tokens)) + in + let gloria, credo, praef = extract_missa_fields primary in + { date = Date.to_iso8601 date; class_; title; te_deum; gloria; credo; praef; alt_te_deum }) + blocks + in + let missing_class = List.filter (fun r -> r.class_ = None) rows in + let missing_gloria = List.filter (fun r -> r.gloria = None) rows in + let missing_credo = List.filter (fun r -> r.credo = None) rows in + let missing_te_deum = List.filter (fun r -> r.te_deum = None) rows in + if missing_class <> [] then + Printf.printf "extract_fiuv_ordo: WARNING %d rows with no class found: %s\n" (List.length missing_class) + (String.concat ", " (List.map (fun r -> r.date) missing_class)); + Printf.printf + "extract_fiuv_ordo: %d rows; %d with no Gloria found; %d with no Credo found; %d with no Te Deum found\n" + (List.length rows) (List.length missing_gloria) (List.length missing_credo) (List.length missing_te_deum); + (* CHARACTERISATION, Step C of the task brief, non-negotiable: probed + BEFORE trusting a single row of this fixture, and RE-VERIFIED here + against this run's own [rows] -- a failed probe is a hard [die], the + same self-verifying discipline extract_lms_ordo.ml already uses, + never a printed claim resting on a one-off manual check that could + silently rot on a re-extraction. Every date/expectation pair below + was confirmed directly against the raw pdftotext dump before being + encoded here. *) + let creed_of_date d = List.find_map (fun r -> if String.equal r.date d then r.credo else None) rows in + let probes = + [ ("2025-11-30", true, "Advent Sunday, I class, RG 475(a)"); + ("2025-12-01", false, "ordinary Advent feria, III class, RG 476(b)/(d)"); + ("2025-12-26", true, "St Stephen, II class, inside the Nativity octave, RG 475(d)"); + ("2026-08-10", false, "St Laurence, II class martyr, no Lord/BVM/apostle clause applies, RG 476(b)"); + ("2026-08-15", true, "the Assumption, I class, RG 475(b)") ] + in + List.iter + (fun (d, expected, desc) -> + match creed_of_date d with + | Some got when Bool.equal got expected -> () + | Some got -> die "characterisation probe FAILED: %s (%s) -- expected creed=%b, extracted creed=%b" d desc expected got + | None -> die "characterisation probe FAILED: %s (%s) -- no row extracted for this date at all" d desc) + probes; + Printf.printf "extract_fiuv_ordo: all %d characterisation probes confirmed\n" (List.length probes); + (* Second characterisation probe, same discipline: the "–VEL–" + alternative-office split (module header point 5) must fire on + EXACTLY these six dates, no more, no fewer -- a hard [die], not a + printed claim, so a future re-extraction against a re-flowed dump + silently gaining or losing an instance fails loudly rather than + quietly changing F3's own population. *) + let alt_office_dates = List.filter_map (fun r -> if r.alt_te_deum <> None then Some r.date else None) rows in + let expected_alt_office_dates = + [ "2026-03-06"; "2026-03-07"; "2026-03-09"; "2026-03-12"; "2026-03-21"; "2026-03-24" ] + in + if List.sort String.compare alt_office_dates <> expected_alt_office_dates then + die "alt-office-split characterisation probe FAILED: expected exactly %s, got %s" + (String.concat ", " expected_alt_office_dates) + (String.concat ", " (List.sort String.compare alt_office_dates)); + Printf.printf "extract_fiuv_ordo: alt-office-split characterisation probe confirmed (%d dates)\n" + (List.length expected_alt_office_dates); + let probe_lines = + String.concat "\n" + (List.map + (fun (d, expected, desc) -> Printf.sprintf "; %s (%s) -> %s" d desc (if expected then "TRUE" else "FALSE")) + probes) + in + let sha256_of_file path = + let cmd = Printf.sprintf "sha256sum %s" (Filename.quote path) in + let ic = Unix.open_process_in cmd in + let line = try input_line ic with End_of_file -> die "sha256sum produced no output for %s" path in + (match Unix.close_process_in ic with Unix.WEXITED 0 -> () | _ -> die "sha256sum failed for %s" path); + match String.index_opt line ' ' with Some i -> String.sub line 0 i | None -> die "unexpected sha256sum output: %S" line + in + let today () = + let tm = Unix.gmtime (Unix.time ()) in + Printf.sprintf "%04d-%02d-%02d" (tm.Unix.tm_year + 1900) (tm.Unix.tm_mon + 1) tm.Unix.tm_mday + in + let pdf_sha = sha256_of_file pdf_path in + let pdf_base = Filename.basename pdf_path in + let gloria_true = List.length (List.filter (fun r -> r.gloria = Some true) rows) in + let gloria_false = List.length (List.filter (fun r -> r.gloria = Some false) rows) in + let credo_true = List.length (List.filter (fun r -> r.credo = Some true) rows) in + let credo_false = List.length (List.filter (fun r -> r.credo = Some false) rows) in + let te_deum_true = List.length (List.filter (fun r -> r.te_deum = Some true) rows) in + let te_deum_false = List.length (List.filter (fun r -> r.te_deum = Some false) rows) in + let alt_te_deum_true = List.length (List.filter (fun r -> r.alt_te_deum = Some true) rows) in + let alt_te_deum_false = List.length (List.filter (fun r -> r.alt_te_deum = Some false) rows) in + let alt_te_deum_none = List.length (List.filter (fun r -> r.alt_te_deum = None) rows) in + let header = + Printf.sprintf + {|; %s -- Witnesses task (2026-08-22-colitur- +; celebrant-rubrics-phase1)'s SEVENTH validation layer, and the first +; UNIVERSAL (non-diocesan), SECOND-COMPILER witness: the FIUV (Foederatio +; Internationalis Una Voce) Ordo, compiled independently of the Latin Mass +; Society's own three editions (test/test_lms_ordo.ml) -- see +; docs/research/ordo/PROVENANCE-ordo-corpus.md for the full four-reasons +; account of why this source is the more valuable of the two newly- +; acquired ones. +; +; Generator: tools/extract_fiuv_ordo.ml -- do not hand-edit; re-run +; against a fresh pdftotext dump and commit the diff instead. +; +; Source: "Ordo Divini Officii recitandi sacrique peragendi secundum +; antiquam Ritus Romani formam pro anno Domini 2026", Foederatio +; Internationalis Una Voce, compiled by Joseph Shaw (Praefatio signed +; "Joseph Shaw, President", Feast of the Nativity of Our Lady [8 Sept] +; 2025) -- title page and Praefatio, verified directly against the PDF's +; own extracted text. 2025 is stated as the Federation's own 60th +; anniversary year. +; PDF metadata: Creator "TeX", Producer "pdfTeX-1.40.22", CreationDate +; 2025-11-08, 128 pages. +; URL: identified via web search as +; https://lms.org.uk/sites/default/files/u5374/fiuv_ordo_2025-2026_1.1_a5_format.pdf +; (hosted by the Latin Mass Society's own site alongside its own three +; editions -- Joseph Shaw is both FIUV President and LMS Chairman, which +; plausibly also explains why this PDF's own trailing malformed entry +; (see COVERAGE below) is structurally identical to the LMS PDFs' own, +; despite the two being compiled by different people); NOT independently +; re-downloaded and byte-compared in this session -- recorded honestly +; rather than presented as verified, the same discipline the LMS +; fixtures' own headers use. +; The local PDF (docs/research/ordo/%s) is gitignored (CLAUDE.md: "docs/ +; is gitignored"), so this header, not git, is this fixture's only record +; of where it came from. +; SHA-256 of docs/research/ordo/%s: %s +; Extracted (UTC): %s +; Exact commands: +; pdftotext -layout docs/research/ordo/%s /tmp/fiuv.txt +; dune exec tools/extract_fiuv_ordo.exe -- /tmp/fiuv.txt \ +; docs/research/ordo/%s %s +; +; COVERAGE: %d day-rows, %s through %s. Starts at the book's own first +; real content line ("November MMXXV", the FIRST month header found with +; a parseable Roman-numeral year -- used as this parser's sole date +; anchor, see the tool's own header on why no LATER header's year is ever +; read, the second one being a publisher typo, "December MMXV" for 2025). +; Stops before a malformed trailing entry, structurally the SAME artefact +; found in all three LMS editions (a stray, mislabelled duplicate of the +; fixture's own already-extracted 1 January row, headed "1st Jan / 2025." +; -- see extract_lms_ordo.ml's own COVERAGE section for the fuller +; account of this shared publisher-side quirk). +; +; CHARACTERISATION FINDINGS (non-negotiable per the task brief -- the +; extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; this Ordo was probed with the same discipline +; before a single divergence was adjudicated): +; +; 1. UNIVERSAL, not diocesan: unlike the three LMS editions (which had to +; exclude diocesan variants from every comparison, quantified in each +; of their own fixture headers), this Ordo carries ONE block per day, +; always. There is no [has_diocesan_variant] field in this fixture's +; own [row] at all -- there is nothing to exclude. +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN against its own extracted +; [rows] before this header was even written -- a failed probe is a +; hard [die], never a printed claim: +%s +; All %d predictions confirmed, both directions -- this source is +; discriminating, not a constant, on the Creed. +; +; 3. THE SUBSTRING TRAP this parser defends against, found live in this +; corpus: "Gloria" is also the first word of "Gloria Patri" (the psalm +; doxology), which can appear INSIDE the very Mass clause being +; scanned (Good Friday, 3 April 2026: "Missa pr., (omittuntur ps. +; Iudica me et Gloria Patri), Gloria, sine Credo, praef. comm." -- the +; real, standalone Gloria mention follows immediately after). See +; [find_word]'s own citation. +; +; 4. RAW SUBSTRING COUNTS measured against this session's own pdftotext +; dump, for comparison against the task brief's own figures (328 +; Gloria / 132 sine Gloria / 119 Credo / 260 sine Credo, 262 Te Deum): +; "sine Gloria" 132 (EXACT match), "sine Credo" 260 (EXACT match), raw +; "Te Deum" substring 262 (EXACT match, includes negated occurrences +; as substring hits -- 42 of them are "non dicitur Te Deum"). Raw +; "Gloria"/"Credo" substring totals (494/411) do NOT match the brief's +; implied positive totals (328/119) even after subtracting the 25 +; "Gloria Patri" occurrences (469, still 9 over) -- not chased further +; here; this extractor's own token-scoped, Missa-clause-bounded counts +; below are what this fixture actually asserts, not a forced match to +; the brief's approximate figures. +; +; 5. THE ALTERNATIVE-OFFICE TRAP (celebrant-rubrics-phase1 Phase 2 +; correction, 2026-08-22, closing F3): six real days print BOTH a +; strict-1962 reading and a complete SECOND office (the same saint +; kept outright under the 2020 decree Cum Sanctissima), separated by +; a literal "-VEL-" token. [extract_te_deum] used to scan the WHOLE +; block unbounded, so on these six days -- whose PRIMARY office states +; no "Ad Mat." of its own -- it silently read the SECOND office's own +; Te Deum instead, manufacturing a same-day contradiction with colitur +; that F3 first recorded as "colitur's own possible gap". Every field +; now reads the PRIMARY office only (module header point 5 has the +; full account); the alternative is captured, not discarded, in its +; own [alt_te_deum] field. Confirmed to fire on EXACTLY six dates by a +; hard characterisation probe (this run's own output, above), not +; merely asserted here. +; +; MEASURED DISTRIBUTION (this extraction, not the brief's figures): Gloria +; true=%d false=%d unresolved=%d; Credo true=%d false=%d unresolved=%d; +; Te Deum true=%d false=%d unresolved=%d; alt Te Deum (the six "-VEL-" +; Cum Sanctissima alternatives, point 5 above) true=%d false=%d none=%d +; (a day contributes to "none" here either because it has no "-VEL-" +; alternative at all -- 394 of 400 -- or, for a day that does, because +; that alternative's own text doesn't state Te Deum either; not +; distinguished by this one count). +; +; FIX HISTORY (fixed text, HISTORICAL counts from the run that found each +; bug, not re-verified live by every later run -- this section exists so +; regenerating this fixture from a fresh pdftotext dump, which rewrites +; this whole header from the template, does not silently erase either +; finding; earlier this header carried the first entry below as a +; hand-appended note that a regeneration between then and now had +; already dropped once): +; +; 1. RE-EXTRACTED (celebrant-rubrics-phase1 Phase 2, 2026-08-22): the FIRST +; extraction's own Te Deum parser recognised only ONE of the source's two +; negative phrasings ("non dicitur Te Deum") -- "sine Te Deum" (how the +; source actually negates a SUNDAY's own Te Deum, among others) fell +; through to a bare "Te Deum" substring match and was wrongly read +; [true]. Found by hand, comparing the raw pdftotext dump against this +; fixture's own values directly, not by any coverage check (both counted +; the same 127 unresolved rows before and after). Fixed in +; tools/extract_fiuv_ordo.ml's own [extract_te_deum] (see its own +; citation); this fixture re-extracted from the SAME pdftotext dump +; (SHA-256 of the source PDF unchanged, above). 24 of 400 rows changed, +; every one Te Deum true->false, every one independently confirmed +; against the raw text: true 231->207, false 42->66, unresolved 127 +; unchanged. See lib/rites/rite_ef/rubrics_ef.ml's own [te_deum] header +; (237(a)'s comment) for the full account of what this corrected, and +; the .superpowers task report for the complete before/after date list. +; +; 2. RE-EXTRACTED (celebrant-rubrics-phase1 Phase 2 correction, 2026-08-22): +; module header point 5 and CHARACTERISATION point 5 above have the +; full account of the "-VEL-" alternative-office bug this closes +; (data/ef/expected-divergences-fiuv.sexp's own F3). This fixture +; re-extracted from the SAME pdftotext dump (SHA-256 of the source PDF +; unchanged, above). 6 of 400 rows changed, every one Te Deum +; true->unresolved (2026-03-06/07/09/12/21/24), every one independently +; confirmed against the raw text: Te Deum true 207->201 (this run's own +; unresolved count went 127->133, consistent with those same 6 rows). +; Gloria/Credo/class_/title/praef are UNCHANGED on all 400 rows -- +; those fields were already correctly bounded to the primary office +; before this fix (a Vespers-line token always intervened before the +; "-VEL-" separator on all six real instances), confirmed by a direct +; diff of the fixture before and after, not merely by argument. +; +; 3. RE-EXTRACTED (celebrant-rubrics-phase1 same correction, defensive +; hardening, 2026-08-22): auditing for the SAME trap elsewhere (the +; task brief's own item 5) found a THIRD, narrower alternate-Mass +; marker, "Vel (sec. decretum <<Cum sanct.>>) Missa ...", offering a +; Cum-Sanctissima Mass FORMULARY choice within a single office +; (unlike point 5 above, no second "Ad Mat." set of lessons -- a +; narrower thing than a full alternate office). 20 occurrences in the +; whole corpus, confirmed by direct grep; on all 20, Gloria/Credo were +; ALREADY stated before reaching this marker, so this was NEVER a +; live divergence for those two fields (confirmed by this same diff: +; 0 Gloria/Credo/class_/title/alt_te_deum rows changed). [praef] +; alone changed on 20 of 400 rows (its own "rest of the primary +; clause" capture no longer runs past this marker into the +; alternative's own text) -- harmless in itself ([praef] is +; documented CAPTURED, NOT VALIDATED, compared by nothing), but added +; as a defensive boundary in [extract_missa_fields] so a FUTURE year +; whose primary clause does not restate Gloria/Credo before this +; marker cannot silently read the alternative's own value instead -- +; the identical failure shape as point 2 above, closed before it was +; ever observed live rather than after. +|} + dest pdf_base pdf_base pdf_sha (today ()) pdf_base pdf_base dest (List.length rows) + (match rows with r :: _ -> r.date | [] -> "?") + (match List.rev rows with r :: _ -> r.date | [] -> "?") + probe_lines (List.length probes) gloria_true gloria_false (List.length missing_gloria) credo_true credo_false + (List.length missing_credo) te_deum_true te_deum_false (List.length missing_te_deum) alt_te_deum_true + alt_te_deum_false alt_te_deum_none + in + let body = Sexplib.Sexp.to_string_hum ~indent:2 (sexp_of_list sexp_of_row rows) in + let oc = open_out dest in + Fun.protect + ~finally:(fun () -> close_out_noerr oc) + (fun () -> + output_string oc header; + output_string oc body; + output_string oc "\n"); + Printf.printf "extract_fiuv_ordo: wrote %d rows to %s\n" (List.length rows) dest diff --git a/tools/extract_lms_ordo.ml b/tools/extract_lms_ordo.ml new file mode 100644 index 0000000..582fb6e --- /dev/null +++ b/tools/extract_lms_ordo.ml @@ -0,0 +1,729 @@ +(* Task 6 (2026-08-21-colitur-celebrant-rubrics-phase1): turns pdftotext's + -layout dump of the Latin Mass Society's printed Ordo into + test/fixtures/lms-ordo-2024-2025.sexp, one row per UNIVERSAL-calendar + day (England & Wales diocesan variants are recorded as PRESENT via + [has_diocesan_variant] but their own text is discarded -- see the + fixture's own provenance header, and task-6-report.md's "how much of + the Ordo's year is comparable" accounting, for why). + + NOT a general Ordo parser: hand-rolled against ONE PDF's own column + layout (Author "Peter Day-Milne", Producer "LibreOffice 7.4", pdftotext + 1.6), verified line-by-line against the source before being trusted -- + see task-6-report.md for the full characterisation record (the + opposite-prediction probe technique CLAUDE.md's "burned twice" note + demands). Frozen deps forbid Str/regex; every match below is + String.sub/index/split_on_char, the same discipline tools/ + bootstrap_sanctoral.ml's own hand-rolled INI reader already uses for + someone else's format. + + THE KEY STRUCTURAL FACT this parser leans on, established during + characterisation: every day's UNIVERSAL entry (the General Roman + Calendar's own text) appears FIRST in reading order, before any + diocesan variant block (which is introduced by a line ending in ':', + e.g. "Westminster, Clifton, Plymouth:" or "In all Dioceses of ENGLAND + and WALES ... follows:"). So the FIRST "Gl"/"Cr" token pair and the + FIRST "Mass of ..."/roman-numeral-BVM line found within a day's block + are ALWAYS the universal entry's own, even if the colon-boundary + detection below is imperfect -- diocesan text can only ever appear + AFTER, never before, so it cannot introduce a false FIRST match. This + is why [scan_block] restricts its search to lines before the first + colon-terminated line (belt), while the ordering argument above is the + suspenders. + + Usage: + pdftotext -layout docs/research/ordo/lms-ordo-2024-2025.pdf /tmp/lms.txt + dune exec tools/extract_lms_ordo.exe -- /tmp/lms.txt \ + docs/research/ordo/lms-ordo-2024-2025.pdf \ + test/fixtures/lms-ordo-2024-2025.sexp *) + +open Sexplib0.Sexp_conv +module Date = Colitur_kernel.Date + +let die fmt = Printf.ksprintf (fun s -> prerr_endline ("extract_lms_ordo: " ^ s); exit 1) fmt + +(* Mirrored, not shared, by test/test_lms_ordo.ml -- tools/ and test/ have + no common .mli either could hang a shared type from, the same reasoning + test_oracle.ml's own header gives for duplicating [sha256_of_file]. *) +type row = { + date : string; (** ISO-8601 *) + weekday : string; + (** As printed ("Sat", "Sun", ...) -- cross-checked below against + [date]'s own computed weekday at extraction time (fatal on + mismatch: the whole point of carrying both is to catch a date- + resolution bug here, not paper over one). *) + title : string; (** the day's own title line: feast name, class, colour, votive codes *) + formulary_override : string option; + (** the literal "Mass of ..." text, when the universal block names + one; [None] = the day says its own Mass. *) + bvm_numeral : string option; + (** "I".."V" when [formulary_override] is one of the five anchored + "<N> Mass of BVM" lines (whole-line match, never a substring -- + see the module header on why "V Mass of BVM" must never be + matched as a substring of "IV Mass of BVM"). *) + gloria : bool option; (** [None] only if genuinely not found -- reported, not silently dropped *) + creed : bool option; + praef : string option; + (** RAW trailing text from the FIRST "Pr of ..." / "Common Pr" match + in the universal block's own reading order -- CAPTURED, NOT + CLASSIFIED here, the same discipline + tools/extract_fiuv_ordo.ml's own [row.praef] documents for a + different publisher's format. See the provenance header's own + "Pr of" characterisation bullet for what this column can and + cannot show: this Ordo prints OPTION LISTS ("Pr of X or Pr of Y + or Common Pr"), some of whose named options ("Martyrs", "All + Saints and Patron Saints", "the Dedication of a Church", "the + Most Holy Sacrament", "St John the Baptist", "the Angels") are + NOT among the fourteen the 1962 Missale Romanum's own RG 484-497 + enumerate -- ad libitum extras this publisher includes alongside + a genuine RG 482 answer, never the sole option on any row found + in this corpus. Classification into {!Colitur_kernel.Preface.t} + happens test-side (test/test_lms_ordo.ml), by MEMBERSHIP in the + parsed option set, not string equality -- see that file's own + [classify_praef] citation for the full account. *) + has_diocesan_variant : bool; + (** whether a diocese-specific block followed the universal one + anywhere in this day's raw text (informational only -- see the + module header on why correctness of the other fields does not + depend on this being exact). *) +} +[@@deriving sexp] + +(* --- tiny hand-rolled helpers, no Str/regex ------------------------------ *) + +let split_ws s = + String.split_on_char ' ' (String.map (fun c -> if c = '\t' then ' ' else c) s) + |> List.filter (fun t -> t <> "") + +let is_all_digits s = s <> "" && String.for_all (fun c -> c >= '0' && c <= '9') s + +let has_prefix ~prefix s = + String.length s >= String.length prefix && String.sub s 0 (String.length prefix) = prefix + +let ends_with_colon s = s <> "" && s.[String.length s - 1] = ':' + +let months = + [| "January"; "February"; "March"; "April"; "May"; "June"; "July"; "August"; "September"; "October"; + "November"; "December" |] + +let month_index name = + let rec go i = if i >= Array.length months then None else if months.(i) = name then Some (i + 1) else go (i + 1) in + go 0 + +let weekday_of_abbrev = function + | "Sun" -> Some Date.Sun + | "Mon" -> Some Date.Mon + | "Tue" -> Some Date.Tue + | "Wed" -> Some Date.Wed + | "Thu" -> Some Date.Thu + | "Fri" -> Some Date.Fri + | "Sat" -> Some Date.Sat + | _ -> None + +(* Left-column codes (Abbreviations, "Left column": "+EW"/"+"/"Pl"/"Ind") -- + printed in a dedicated margin column that pdftotext -layout reproduces + as literal leading tokens on an otherwise-ordinary content line. Strip + ALL that appear (there can be two, "Pl Ind" together -- the 31 Dec/ + 1 Jan examples in the source). *) +let strip_left_column tokens = + let is_marker = function "Pl" | "Ind" | "+EW" | "+" -> true | _ -> false in + let rec go = function t :: rest when is_marker t -> go rest | ts -> ts in + go tokens + +let bvm_numeral_strings = [ ("I", "I Mass of BVM"); ("II", "II Mass of BVM"); ("III", "III Mass of BVM"); + ("IV", "IV Mass of BVM"); ("V", "V Mass of BVM") ] + +(* Anchored WHOLE-LINE match against all five, never a substring test -- + this is the exact discipline the coordinator addendum records: "V Mass + of BVM" is a substring of "IV Mass of BVM", so any check here MUST + compare the full line, not search for the numeral's own string inside + it. *) +let bvm_numeral_of_line line = List.assoc_opt line (List.map (fun (n, s) -> (s, n)) bvm_numeral_strings) + +(* --- the day-block scanner ------------------------------------------------ *) + +(* [lines]: this day's own raw continuation lines, marker-stripped and + trimmed, title line NOT included (the title never carries Gl/Cr/"Mass + of" itself in this source). Returns (formulary_override, bvm_numeral, + gloria, creed, praef, has_diocesan_variant), each derived from the + portion BEFORE the first colon-terminated (diocesan) line -- see the + module header for why this is belt-and-suspenders, not load-bearing on + its own. *) +let scan_block lines = + let rec universal_prefix = function + | [] -> [] + | l :: _ when ends_with_colon l -> [] + | l :: rest -> l :: universal_prefix rest + in + let has_diocesan = List.exists ends_with_colon lines in + let universal = universal_prefix lines in + let formulary_override, bvm_numeral = + let rec find = function + | [] -> (None, None) + | l :: rest -> ( + match bvm_numeral_of_line l with + | Some n -> (Some l, Some n) + | None -> if has_prefix ~prefix:"Mass of " l then (Some l, None) else find rest) + in + find universal + in + let all_tokens = List.concat_map split_ws universal in + let rec find_flag word = function + | prev :: (cur :: _ as rest) -> if cur = word then Some (prev <> "No") else find_flag word rest + | [ cur ] -> if cur = word then Some true else None + | [] -> None + in + (* [find_flag] needs a sentinel predecessor for a match at position 0 + (never observed in this source -- Gl/Cr always follow at least "No" + or a preceding word on the same "Gl Cr Pr of ..." line -- but handled + rather than assumed: a bare leading "Gl"/"Cr" with no "No" before it + reads as [true], the same as any other non-"No" predecessor would). *) + let gloria = find_flag "Gl" ("" :: all_tokens) in + let creed = find_flag "Cr" ("" :: all_tokens) in + (* [praef]: LINE-SCOPED (not [all_tokens]'s flattened stream), because + the captured text runs to the END of whichever physical line carries + it -- flattening first would glue an unrelated following line's own + prose onto it. "Pr" always abbreviates "Preface" in this source's own + body text (checked directly: its only OTHER appearance is the front- + matter Abbreviations glossary entry "Pr Preface", outside the Ordo + body this tool scans), so a whole-token ("Pr","of") pair, or a bare + ("Common","Pr") pair when no proper/de-Tempore option is offered, is + the sole anchor needed -- no reject-list, unlike the BVM roman + numeral's own substring trap, because nothing else in this corpus's + body ever produces either two-token sequence. *) + let find_praef_in_line line = + let toks = Array.of_list (split_ws line) in + let n = Array.length toks in + let rec go i = + if i + 1 >= n then None + else if (toks.(i) = "Pr" && toks.(i + 1) = "of") || (toks.(i) = "Common" && toks.(i + 1) = "Pr") then + Some (String.concat " " (Array.to_list (Array.sub toks i (n - i)))) + else go (i + 1) + in + go 0 + in + let praef = + let rec find = function + | [] -> None + | l :: rest -> ( match find_praef_in_line l with Some s -> Some s | None -> find rest) + in + find universal + in + (formulary_override, bvm_numeral, gloria, creed, praef, has_diocesan) + +(* --- the top-level line scan --------------------------------------------- *) + +type block = { b_weekday : string; b_day : int; b_month : int; b_year : int; b_title : string; b_lines : string list } + +(* Generalised (Witnesses task, 2026-08-22) from a single hardcoded + sentinel ["End";"of";"November";"2024"], which assumed every edition + opens its Ordo body with an "End of November <year>" stub section. That + assumption FAILED characterisation against the two newly-acquired + editions: the 2023-2024 PDF has NO such stub -- Advent Sunday 2023 fell + on 3 December, so only 2 tail days of the old liturgical year remained + (1-2 December), and the compiler folded them directly into the + "December 2023" header rather than giving them their own mini-section. + So a start marker anchored to "End of November" cannot generalise. + + What DOES generalise, checked directly against all three editions' + pdftotext -layout dumps: exactly one line in the whole document begins + with the bare, all-uppercase token "ORDO" -- either alone ("ORDO", + 2024-2025/2025-2026, introducing an "End of <Month> <Year>" stub next) + or fused with the edition's own year range ("ORDO 2023-2024", + introducing the first REAL month header directly, no stub). This is + NEVER the Table of Contents' own entry, which prints title-case "Ordo + 20XX-20XX" followed by dot leaders and a page number -- a different + string ("Ordo", not "ORDO"), confirmed by grepping all three raw dumps + for both patterns before relying on either. *) +let is_ordo_marker tokens = match tokens with "ORDO" :: _ -> true | _ -> false + +(* The "End of <Month> <Year>" stub heading, when an edition has one -- + parsed directly (never hardcoded to November/a specific year) so the + edition's own initial (month, year) state comes from the text itself, + not an assumption baked into the tool. *) +let parse_end_of_month tokens = + match tokens with + | [ "End"; "of"; m; y ] when is_all_digits y -> ( match month_index m with Some mi -> Some (mi, int_of_string y) | None -> None) + | _ -> None + +let is_stop_tail_line tokens = + match tokens with tok :: _ -> String.length tok = 4 && is_all_digits tok | [] -> false + +let is_month_header tokens = + match tokens with + | m :: rest when month_index m <> None -> List.for_all is_all_digits rest + | _ -> false + +let read_lines path = + let ic = open_in path in + let rec loop acc = match input_line ic with l -> loop (l :: acc) | exception End_of_file -> List.rev acc in + let ls = loop [] in + close_in ic; + ls + +let () = + if Array.length Sys.argv <> 4 then + die "usage: extract_lms_ordo <pdftotext-layout.txt> <source.pdf> <dest.sexp>"; + let txt_path = Sys.argv.(1) in + let pdf_path = Sys.argv.(2) in + let dest = Sys.argv.(3) in + let all_lines = read_lines txt_path in + let arr = Array.of_list all_lines in + let n = Array.length arr in + let trimmed i = String.trim arr.(i) in + let ordo_marker_idx = + let rec go i = if i >= n then die "no line begins with the bare \"ORDO\" body marker (see the tool's own comment on [is_ordo_marker] -- this edition's format may have drifted)" + else if is_ordo_marker (split_ws (trimmed i)) then i else go (i + 1) + in + go 0 + in + (* The first non-blank line after the marker is either an "End of <Month> + <Year>" stub (consumed here as a pure sentinel, exactly as the old + hardcoded design did -- [start_idx] becomes ITS OWN index so the main + loop below begins right after it) or a real "<Month> <Year>" header + with an explicit year token (an edition with no stub, e.g. 2023-2024 -- + [start_idx] becomes the ORDO marker's own index instead, so the main + loop re-encounters this header line on its very first iteration and + [is_month_header]'s own existing per-line handling sets [cur_month]/ + [cur_year] from it normally). Either way [init_month]/[init_year] come + directly from parsed text, never a hardcoded constant -- a missing + explicit year on this FIRST header is a genuine format break, so it + dies loudly rather than silently seeding a wrong year. *) + let rec first_nonblank i = + if i >= n then die "no content found after the ORDO marker at line %d" ordo_marker_idx + else if trimmed i = "" then first_nonblank (i + 1) + else i + in + let content_idx = first_nonblank (ordo_marker_idx + 1) in + let content_toks = split_ws (trimmed content_idx) in + let start_idx, init_month, init_year = + match parse_end_of_month content_toks with + | Some (mi, y) -> (content_idx, mi, y) + | None -> ( + match content_toks with + | m :: (y :: _ as rest) when month_index m <> None && List.for_all is_all_digits rest -> + (ordo_marker_idx, (match month_index m with Some x -> x | None -> assert false), int_of_string y) + | _ -> + die "first content after the ORDO marker (%S) is neither an \"End of <Month> <Year>\" stub nor a \"<Month> <Year>\" header carrying an explicit year" + (String.concat " " content_toks)) + in + let stop_idx = + let rec go i = + if i >= n then n else if is_stop_tail_line (split_ws (trimmed i)) then i else go (i + 1) + in + go (start_idx + 1) + in + Printf.printf "extract_lms_ordo: Ordo body lines %d..%d (of %d total), initial month/year %d/%d\n" start_idx stop_idx n + init_month init_year; + (* --- the scan: month/year tracker + block accumulator ------------------ *) + let cur_month = ref init_month and cur_year = ref init_year in + let blocks = ref [] in + let cur = ref None in + let flush () = match !cur with Some b -> blocks := b :: !blocks; cur := None | None -> () in + for i = start_idx + 1 to stop_idx - 1 do + let raw = trimmed i in + if raw = "" then () + else if String.length raw >= 1 && (let rec contains s sub = + let ls = String.length s and lu = String.length sub in + if lu = 0 then true else if ls < lu then false + else if String.sub s 0 lu = sub then true + else contains (String.sub s 1 (ls - 1)) sub + in + contains raw "Latin Mass Society Ordo") + then () (* page footer *) + else + let toks = split_ws raw in + if is_month_header toks then begin + match toks with + | m :: rest -> ( + match month_index m with + | Some mi -> + if mi <> !cur_month then begin + if mi < !cur_month then incr cur_year; + cur_month := mi + end; + (* an explicit 4-digit year token, when present, overrides + the transition inference outright -- belt and + suspenders, same reasoning as [scan_block] above *) + List.iter (fun t -> if String.length t = 4 && is_all_digits t then cur_year := int_of_string t) rest + | None -> ()) + | [] -> () + end + else + match toks with + | wd :: dn :: _ when weekday_of_abbrev wd <> None && is_all_digits dn && int_of_string dn >= 1 + && int_of_string dn <= 31 -> + flush (); + let title = String.concat " " (List.tl (List.tl toks)) in + cur := Some { b_weekday = wd; b_day = int_of_string dn; b_month = !cur_month; b_year = !cur_year; + b_title = title; b_lines = [] } + | _ -> ( + match !cur with + | None -> () + | Some b -> + let stripped = strip_left_column toks in + if stripped = [] then () + else cur := Some { b with b_lines = b.b_lines @ [ String.concat " " stripped ] }) + done; + flush (); + let blocks = List.rev !blocks in + Printf.printf "extract_lms_ordo: %d day-blocks parsed\n" (List.length blocks); + let rows = + List.map + (fun b -> + let date = + match Date.make ~year:b.b_year ~month:b.b_month ~day:b.b_day with + | Ok d -> d + | Error e -> die "%s %d/%d/%d: %s" b.b_weekday b.b_year b.b_month b.b_day e + in + (match weekday_of_abbrev b.b_weekday with + | Some w when w = Date.weekday date -> () + | Some _ -> + die "%s: printed weekday %S does not match computed weekday %S -- date resolution bug" + (Date.to_iso8601 date) b.b_weekday (Date.weekday_to_string (Date.weekday date)) + | None -> die "%s: unrecognised weekday abbreviation %S" (Date.to_iso8601 date) b.b_weekday); + let formulary_override, bvm_numeral, gloria, creed, praef, has_diocesan_variant = scan_block b.b_lines in + { date = Date.to_iso8601 date; weekday = b.b_weekday; title = b.b_title; formulary_override; bvm_numeral; + gloria; creed; praef; has_diocesan_variant }) + blocks + in + let missing_gloria = List.filter (fun r -> r.gloria = None) rows in + let missing_creed = List.filter (fun r -> r.creed = None) rows in + let missing_praef = List.filter (fun r -> r.praef = None) rows in + if missing_gloria <> [] then + Printf.printf "extract_lms_ordo: WARNING %d rows with no Gloria found: %s\n" (List.length missing_gloria) + (String.concat ", " (List.map (fun r -> r.date) missing_gloria)); + if missing_creed <> [] then + Printf.printf "extract_lms_ordo: WARNING %d rows with no Creed found: %s\n" (List.length missing_creed) + (String.concat ", " (List.map (fun r -> r.date) missing_creed)); + if missing_praef <> [] then + Printf.printf "extract_lms_ordo: WARNING %d rows with no Pr-of/Common-Pr found: %s\n" (List.length missing_praef) + (String.concat ", " (List.map (fun r -> r.date) missing_praef)); + let with_variant = List.length (List.filter (fun r -> r.has_diocesan_variant) rows) in + let with_override = List.length (List.filter (fun r -> r.formulary_override <> None) rows) in + let with_bvm = List.length (List.filter (fun r -> r.bvm_numeral <> None) rows) in + Printf.printf "extract_lms_ordo: %d rows; %d with a diocesan variant present; %d with a formulary override; \ + %d with a BVM roman numeral; %d with no Pr-of/Common-Pr text\n" + (List.length rows) with_variant with_override with_bvm (List.length missing_praef); + (* --- provenance header + write ----------------------------------------- *) + let sha256_of_file path = + let cmd = Printf.sprintf "sha256sum %s" (Filename.quote path) in + let ic = Unix.open_process_in cmd in + let line = try input_line ic with End_of_file -> die "sha256sum produced no output for %s" path in + (match Unix.close_process_in ic with Unix.WEXITED 0 -> () | _ -> die "sha256sum failed for %s" path); + match String.index_opt line ' ' with Some i -> String.sub line 0 i | None -> die "unexpected sha256sum output: %S" line + in + let today () = + let tm = Unix.gmtime (Unix.time ()) in + Printf.sprintf "%04d-%02d-%02d" (tm.Unix.tm_year + 1900) (tm.Unix.tm_mon + 1) tm.Unix.tm_mday + in + let pdf_sha = sha256_of_file pdf_path in + (* --- per-edition provenance + characterisation, Witnesses task --------- + Generalised 2026-08-22 from Task 6's single hand-written header (which + named "lms-ordo-2024-2025.sexp" literally throughout). Facts 1/3/4 + below are STRUCTURAL -- true of the publisher's whole known corpus, + re-checked directly against the two new editions' own pdftotext dumps + before being asserted here again, not merely copied forward. Fact 2 + (the Creed opposite-prediction probes) is inherently edition-specific + (the actual calendar dates differ year to year, and one edition's own + calendar even breaks the standard pairing -- see the 2025-2026 note + below), so it is looked up per [dest] and, critically, RE-VERIFIED + against this run's own [rows] before being printed: a probe that + fails is a [die], not a silently-wrong "confirmed" claim in a fixture + header nobody will re-check by eye. *) + let base = Filename.basename dest in + let pdf_base = Filename.basename pdf_path in + let edition_label, isbn, copyright_year, pdf_meta, url, url_note, window_open_desc = + match base with + | "lms-ordo-2023-2024.sexp" -> + ( "2023-2024", + "978-1-7392096-2-9", + "2023", + {|Author "Peter Day-Milne", Producer "LibreOffice 6.4", CreationDate 2023-11-01, 140 pages|}, + "https://lms.org.uk/sites/default/files/u5374/ordo_2023-2024_2.2_final.pdf", + "identified 2026-08-22 via web search matching the PDF's own edition year to the publisher's own hosting path; NOT independently re-downloaded and byte-compared in this session -- recorded honestly rather than presented as verified", + {|1 December 2023 (this edition carries NO "End of November" stub section at all -- Advent Sunday 2023 fell on 3 December, so only 2 tail days of the prior liturgical year remained, and the compiler folded them directly into the "December 2023" header instead of giving them their own mini-section; see CHARACTERISATION below)|} + ) + | "lms-ordo-2025-2026.sexp" -> + ( "2025-2026", + "978-1-7392096-5-0", + "2025", + {|Author "Peter Day-Milne", Producer "LibreOffice 25.2.6.2 (X86_64) / LibreOffice Community", CreationDate 2025-10-23, 146 pages|}, + "(not found -- see the note on this line)", + "NOT found by URL-pattern web search this session (unlike the 2023-2024 and 2024-2025 editions, no exact download link matching this PDF's own filename/version turned up under lms.org.uk/sites/default/files/u5374/; several near-miss candidates were checked and rejected -- none matched this PDF's own metadata) -- left honestly blank rather than guessed; the file was supplied locally to this session, not fetched by this tool", + {|28 November 2025 ("End of November 2025", the same shape as the 2024-2025 edition -- Advent Sunday 2025 fell on 30 November, so only 3 tail days remained; note this excludes 27 November 2025, which the PRECEDING edition's own window (2024-2025, through 2025-12-31) already covers -- a one-day-short overlap between consecutive editions' own windows, not a gap or a bug in either extraction|} + ) + | "lms-ordo-2024-2025.sexp" -> + (* Preface-witnesses task (2026-08-23): brought into this same + auto-generated, probe-verified header template so all three + editions carry the identical characterisation discipline -- + Task 6's own original HAND-WRITTEN header (never regenerated by + the Witnesses task, which only added table entries for the two + NEW editions) is superseded by this run; every fact below is + re-derived from this PDF's own text/metadata, not copied + blind from that older header (though it agrees with it in + every particular checked). *) + ( "2024-2025", + "9781739209636", + "2024", + {|Author "Peter Day-Milne", Producer "LibreOffice 7.4", CreationDate 2024-11-06, 140 pages|}, + "https://lms.org.uk/sites/default/files/u5374/ordo_2.21_2024-2025.pdf", + "identified via web search matching the PDF's own version number and filename to the publisher's own hosting path (product page: https://lms.org.uk/product/latin-mass-society-ordo-2024-25); NOT independently re-downloaded and byte-compared in this session -- recorded honestly rather than presented as verified", + {|27 November 2024 ("End of November 2024", the same shape as the 2025-2026 edition -- Advent Sunday 2024 fell on 1 December, so 4 tail days remained (27-30 November))|} + ) + | _ -> die "no provenance/characterisation entry for %s -- add one to extract_lms_ordo.ml's own per-edition table before generating this fixture (the tool refuses to emit an under-characterised header)" base + in + let creed_of_date rows d = List.find_map (fun r -> if String.equal r.date d then r.creed else None) rows in + let probes = + match base with + | "lms-ordo-2023-2024.sexp" -> + [ ("2023-12-03", true, "Advent Sunday, RG 475(a)"); + ("2023-12-04", false, "St Peter Chrysologus, III class, ordinary Advent day, RG 476(b)/(d)"); + ("2023-12-26", true, "St Stephen, II class, inside the Nativity octave, RG 475(d)"); + ("2024-08-15", true, "the Assumption, I class, RG 475(b)"); + ("2024-08-16", false, "St Joachim, II class, no Lord/BVM/apostle clause applies, RG 476(b)") ] + | "lms-ordo-2025-2026.sexp" -> + [ ("2025-11-30", true, "Advent Sunday, RG 475(a)"); + ("2025-12-01", false, "ordinary Advent feria, RG 476(b)/(d)"); + ("2025-12-26", true, "St Stephen, II class, inside the Nativity octave, RG 475(d)"); + ( "2026-08-10", false, + "St Laurence, II class martyr, no Lord/BVM/apostle clause applies, RG 476(b) -- St Joachim (16 August) is IMPEDED by a Sunday in this edition's own calendar (12th Sunday after Pentecost), so this edition needed a DIFFERENT sharp non-octave II-class pairing than the 2023-2024/2024-2025 editions used; a real, edition-specific finding, not an extraction quirk" + ); + ("2026-08-15", true, "the Assumption, I class, RG 475(b)") ] + | "lms-ordo-2024-2025.sexp" -> + [ ("2024-12-01", true, "Advent Sunday, RG 475(a)"); + ("2024-12-02", false, "ordinary Advent feria, RG 476(b)/(d)"); + ("2024-12-26", true, "St Stephen, II class, inside the Nativity octave, RG 475(d)"); + ("2025-08-15", true, "the Assumption, I class, RG 475(b)"); + ("2025-08-16", false, "St Joachim, II class, no Lord/BVM/apostle clause applies, RG 476(b)") ] + | _ -> die "no probe list for %s" base + in + List.iter + (fun (d, expected, desc) -> + match creed_of_date rows d with + | Some got when Bool.equal got expected -> () + | Some got -> die "characterisation probe FAILED: %s (%s) -- expected creed=%b, extracted creed=%b" d desc expected got + | None -> die "characterisation probe FAILED: %s (%s) -- no row extracted for this date at all" d desc) + probes; + Printf.printf "extract_lms_ordo: all %d characterisation probes confirmed for %s\n" (List.length probes) edition_label; + (* Preface-witnesses task (2026-08-23): a SECOND opposite-prediction + probe set, over [praef] rather than [creed] -- the same discipline, + applied to the new column this task adds, per the task brief's own + "probe dates where the rule predicts OPPOSITE answers before + adjudicating anything" instruction. Three universal, unambiguous + fixed-date feasts per edition, each landing on a DIFFERENT named + preface (RG 484 Nativity, RG 497 Apostles, RG 499 Requiem) -- checked + directly against this run's own [rows] before this header is + written, a hard [die] on failure, not a printed claim. All Souls' + own date is edition-specific (2 November, TRANSFERRED to 3 November + in the one edition -- 2024-2025 -- where 2 November falls on a + Sunday; verified directly against each PDF's own text, not assumed + from RG 96 alone). *) + let praef_of_date rows d = List.find_map (fun r -> if String.equal r.date d then r.praef else None) rows in + let praef_probes = + match base with + | "lms-ordo-2023-2024.sexp" -> + [ ("2023-12-25", "Pr of the Nativity", "the Nativity of Our Lord, I class, RG 484(a)"); + ("2024-06-29", "Pr of the Apostles", "SS Peter & Paul, I class, RG 497"); + ("2024-11-02", "Pr of the Dead", "All Souls' Day, I class, RG 499") ] + | "lms-ordo-2024-2025.sexp" -> + [ ("2024-12-25", "Pr of the Nativity", "the Nativity of Our Lord, I class, RG 484(a)"); + ("2025-06-29", "Pr of the Apostles", "SS Peter & Paul, I class, RG 497"); + ( "2025-11-03", "Pr of the Dead", + "All Souls' Day, I class, RG 499 -- TRANSFERRED from 2 November, a Sunday in this edition's own calendar" ) + ] + | "lms-ordo-2025-2026.sexp" -> + [ ("2025-12-25", "Pr of the Nativity", "the Nativity of Our Lord, I class, RG 484(a)"); + ("2026-06-29", "Pr of the Apostles", "SS Peter & Paul, I class, RG 497"); + ("2026-11-02", "Pr of the Dead", "All Souls' Day, I class, RG 499") ] + | _ -> die "no praef probe list for %s" base + in + List.iter + (fun (d, expected_prefix, desc) -> + match praef_of_date rows d with + | Some got when has_prefix ~prefix:expected_prefix got -> () + | Some got -> + die "praef characterisation probe FAILED: %s (%s) -- expected prefix %S, extracted %S" d desc + expected_prefix got + | None -> die "praef characterisation probe FAILED: %s (%s) -- no praef extracted for this date at all" d desc) + praef_probes; + Printf.printf "extract_lms_ordo: all %d praef characterisation probes confirmed for %s\n" (List.length praef_probes) + edition_label; + let praef_probe_lines = + String.concat "\n" + (List.map (fun (d, expected_prefix, desc) -> Printf.sprintf "; %s (%s) -> %S" d desc expected_prefix) praef_probes) + in + let missing_praef_count = List.length missing_praef in + let probe_lines = + String.concat "\n" + (List.map + (fun (d, expected, desc) -> Printf.sprintf "; %s (%s) -> %s" d desc (if expected then "TRUE" else "FALSE")) + probes) + in + let header = + Printf.sprintf + {|; %s -- Witnesses task (2026-08-22-colitur-celebrant-rubrics-phase1), +; extending Task 6's single LMS fixture (2024-2025) to three editions of +; the Latin Mass Society's own printed Ordo for England & Wales -- a +; lineage independent of Divinum Officium/missalemeum/lectio (layers 3-4) +; and of the electronic LT.txt transcription (layers 1-2/5): a physically +; printed, professionally-compiled liturgical calendar with its own ISBN. +; +; Generator: tools/extract_lms_ordo.ml -- do not hand-edit; re-run against +; a fresh pdftotext dump and commit the diff instead. +; +; Source: "The Ordo %s", compiled by Peter Day-Milne, The Latin +; Mass Society, 9 Mallow Street, London EC1Y 8RQ (title page and +; colophon, verified directly against the PDF's own extracted text -- +; ISBN %s, Copyright (c) The Latin Mass Society, UK %s). +; PDF metadata: %s. +; URL (%s): +; %s +; The local PDF (docs/research/ordo/%s) is gitignored +; (CLAUDE.md: "docs/ is gitignored"), so this header, not git, is this +; fixture's only record of where it came from. +; SHA-256 of docs/research/ordo/%s: %s +; Extracted (UTC): %s +; Exact commands: +; pdftotext -layout docs/research/ordo/%s /tmp/lms.txt +; dune exec tools/extract_lms_ordo.exe -- /tmp/lms.txt \ +; docs/research/ordo/%s %s +; +; COVERAGE: %d day-rows, %s through %s (starting %s, +; through the day before a malformed trailing entry the extractor +; deliberately stops before -- see CHARACTERISATION below). +; +; CHARACTERISATION FINDINGS (Step 1, non-negotiable per the task brief -- +; the extraordinaryform.org Ordo silently omitted St Lawrence's vigil on +; EVERY date it covered, which nearly produced a false corroboration +; during the RG 33 work; every LMS edition, including this one, is probed +; with the same discipline before a single divergence is adjudicated): +; +; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed again for +; THIS edition: it carries many more Gl/Cr pairs than day-rows, because +; every diocesan variant repeats its own "Gl ... Cr ... Pr of ..." +; line). This extractor resolves the day's OWN office by taking the +; FIRST Gl/Cr pair in reading order, which the source's own layout +; guarantees is the universal entry's (diocesan variants are always +; introduced by a colon-terminated diocese-list line that comes AFTER +; the universal block, never before -- checked structurally, not +; assumed, in every sampled block during development, this edition +; included). +; +; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG +; 475-476), RE-CHECKED BY THIS TOOL RUN (not merely copied from a prior +; edition's findings) before a single row of this fixture is trusted -- +; the technique CLAUDE.md records as the one that catches a source +; silently omitting the very thing it is meant to witness. This run's +; own extracted [rows] were checked against every one of the following +; before this header was even written; a failure here is a hard [die], +; not a printed claim: +%s +; All %d predictions confirmed, both directions (TRUE and FALSE each +; independently witnessed) -- this edition is discriminating, not a +; constant, on the Creed. +; +; 3. The BVM-Saturday roman numeral (I-V, "Missae de sancta Maria in +; sabbato", RG 309(a)) is anchored by WHOLE-LINE match against the five +; literal strings below, NEVER by substring search: "V Mass of BVM" is +; a substring of "IV Mass of BVM", so a naive `contains` check +; misreads every fourth-Mass day as the fifth (the coordinator's own +; misreading, recorded and retracted in commit 27b07b4 before Task 6 +; existed; the same anchoring logic runs unchanged for every edition). +; +; 4. SCOPE EXCLUDED, quantified, not silently dropped: +; - Diocesan variants: present on %d of %d days (%s%%) -- their own +; text is read only far enough to set [has_diocesan_variant], +; never compared, because colitur computes the UNIVERSAL General +; Roman Calendar only, with no diocesan overlay loaded. +; - The single malformed trailing entry ("...The OCTAVE DAY of the +; NATIVITY..." with a bare 4-digit token where a weekday+day-number +; pair belongs) is excluded outright: the extractor's own stop +; marker (a line whose first token is a bare 4-digit token) halts +; the scan before it. CONFIRMED IDENTICAL, word for word, across +; ALL FOUR known editions of this publisher's Ordo (2023-2024, +; 2024-2025, 2025-2026, and the 2024-2025 fixture's own prior +; header) -- always the literal stray year token "2025", regardless +; of which edition or which real trailing year it should read: a +; stale copy-paste leftover the compiler's own master document +; carries forward unedited release to release (even the 2024-2025 +; PDF's own tail page footer nearby still reads "Latin Mass Society +; Ordo 2021-2022"), not something specific to this edition. +; - Front matter, the Abbreviations/Rubrical-Primer/Breviary sections, +; and the "When may I say...?"/Appendix tail are never scanned at +; all (the extractor's own start/stop markers bound it to the Ordo +; proper). +; +; 5. THE "Pr of" (PREFACE) COLUMN (Preface-witnesses task, 2026-08-23) -- +; [row.praef], the RAW text from the FIRST "Pr of ..." / "Common Pr" +; match in the universal block's own reading order (the same +; FIRST-in-reading-order discipline finding 1 above already +; establishes for Gl/Cr). CAPTURED, NOT CLASSIFIED by this tool -- +; classification into {!Colitur_kernel.Preface.t} and the comparison +; against {!Rite_ef.Rubrics_ef.preface} both happen test-side +; (test/test_lms_ordo.ml's own [classify_praef]). +; +; CHARACTERISATION FINDING, non-negotiable per the same discipline as +; finding 2: this Ordo prints OPTION LISTS ("Pr of X or Pr of Y or +; Common Pr"), not always a single value -- and several of the named +; options ("Martyrs", "All Saints and Patron Saints" [almost always +; diocesan -- a Patronal feast's own preface -- but checked directly to +; occur ONCE in THIS edition's own UNIVERSAL block too, All Saints' Day +; itself, 1 November, paired with "or Common Pr"/"or Pr of the +; Trinity" depending on whether 1 November falls on a Sunday that +; edition, exactly matching {!Rite_ef.Rubrics_ef.preface}'s own RG +; 494(b) Sunday-gated Trinity fallback either way -- see that +; function's own citation], "the Dedication of a Church", "the Most Holy +; Sacrament" [Corpus Christi's own universal entry], "St John the +; Baptist", "the Angels") are genuinely NOT among the fourteen the +; 1962 Missale Romanum's own RG 484-497 enumerate (docs/research/LT.txt, +; lines 3936-4020, checked directly: no "de Martyribus"/"de Angelis"/ +; "de Dedicatione"/"de Ss.mo Sacramento"/"de S. Ioanne Baptista" clause +; exists anywhere in 482-499). Every one of these extras, in every +; instance found in this edition's UNIVERSAL block, is printed +; ALONGSIDE a genuine RG 482 answer (most often "or Common Pr"; on 24 +; March-shaped days, "or Pr of Lent", the live RG 486(b) de-Tempore +; answer) -- never as the row's OWN AND ONLY option. This is why the +; test-side comparison checks colitur's single computed answer is a +; MEMBER of this row's own parsed option set (dropping any unmapped +; extra name from that set first), not string equality against +; whichever option happens to print first -- the same "capture, don't +; force a match invented at extraction time" discipline +; tools/extract_fiuv_ordo.ml's own [row.praef] doc comment already +; states for a different publisher's format. +; +; OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.preface (RG +; 482-499), the SAME discipline as finding 2, applied to this new +; column -- RE-CHECKED BY THIS TOOL RUN before this header was +; written; a failed probe is a hard [die]: +%s +; All %d predictions confirmed -- this column, too, is discriminating, +; not a constant, across three different RG-cited outcomes (Nativity/ +; Apostles/Requiem). +; +; COVERAGE: %d of %d rows have no "Pr of"/"Common Pr" text found at +; all -- checked directly against this window's own Good Friday +; (Easter-2): its block carries NO Gl/Cr/Pr line whatsoever in this +; source (the 1955-restored Holy Week's own liturgical action has no +; Mass that day at all -- the SAME structural fact +; {!test_creed_coverage}'s own [window_good_fridays] already asserts +; for Gl/Cr), so [praef] shares that single expected gap rather than +; having a coverage gap of its own. +|} + dest edition_label isbn copyright_year pdf_meta url_note url pdf_base pdf_base pdf_sha (today ()) pdf_base + pdf_base dest + (List.length rows) + (match rows with r :: _ -> r.date | [] -> "?") + (match List.rev rows with r :: _ -> r.date | [] -> "?") + window_open_desc probe_lines (List.length probes) with_variant (List.length rows) + (Printf.sprintf "%.1f" (100.0 *. float_of_int with_variant /. float_of_int (List.length rows))) + praef_probe_lines (List.length praef_probes) missing_praef_count (List.length rows) + in + let body = Sexplib.Sexp.to_string_hum ~indent:2 (sexp_of_list sexp_of_row rows) in + let oc = open_out dest in + Fun.protect + ~finally:(fun () -> close_out_noerr oc) + (fun () -> + output_string oc header; + output_string oc body; + output_string oc "\n"); + Printf.printf "extract_lms_ordo: wrote %d rows to %s\n" (List.length rows) dest |
