aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/ef/expected-divergences-lms.sexp55
-rw-r--r--test/dune2
-rw-r--r--test/fixtures/lms-ordo-2024-2025.sexp1513
-rw-r--r--test/test_colitur.ml3
-rw-r--r--test/test_lms_ordo.ml467
-rw-r--r--tools/dune13
-rw-r--r--tools/extract_lms_ordo.ml422
7 files changed, 2474 insertions, 1 deletions
diff --git a/data/ef/expected-divergences-lms.sexp b/data/ef/expected-divergences-lms.sexp
new file mode 100644
index 0000000..96c9e50
--- /dev/null
+++ b/data/ef/expected-divergences-lms.sexp
@@ -0,0 +1,55 @@
+; 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), fixture window 2024-11-27..2025-12-31.
+;
+; 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 -- 2025-11-03 (All Souls' Day, transferred from 2 November, a Sunday
+; that year, to the next available day -- RG's own transfer of a
+; Commemoration when it falls on a Sunday). colitur (Rite_ef.Rubrics_ef.
+; creed) says the Creed IS said (true): observed.rank = Class1, so RG
+; 475(b)'s "in festis I classis" branch fires with nothing to stop it.
+; The Ordo says it is NOT said (false): "Mon 3 ALL SOULS' DAY I Cl B / No
+; Gl Sequence No Cr Pr of the Dead No Blessing" -- confirmed directly
+; against the extracted pdftotext text, not merely the fixture row.
+;
+; The Ordo is right and colitur is not, on the rubric itself: RG 476(f),
+; "Non dicitur symbolum ... f) in Missis defunctorum" -- the Creed is
+; never said at a Requiem Mass, and All Souls' Day is definitionally one
+; (colour black in colitur's own output on this very date). This is NOT a
+; new defect this task found and is choosing to leave open -- it is
+; rubrics_ef.ml's OWN documented scope limit, stated in that file's header
+; comment before this task existed: "476(f) (Requiem Masses, also not
+; modelled) ... genuinely inapplicable to this implementation -- a
+; documented scope limit, not a defect." [creed] has no notion of "this
+; Mass is a Requiem" anywhere in its own inputs (temporal/observed/date),
+; so it cannot express 476(f) without a signature change this task's own
+; constraints do not authorise (lib/ is read-only here except for this
+; allow-list). Recorded here as the SPECIFIC real-world day the scope
+; limit is finally witnessed on, rather than left as an abstract note in
+; a doc comment nobody's data ever exercised.
+;
+; Domain-wide count: unmeasured (out of this task's scope -- would need a
+; sweep of every I-class Requiem-shaped day 1583-9999, which does not
+; exist as a distinct predicate in this codebase to sweep on). The two
+; days this WOULD also apply to in principle -- 2 November itself in any
+; year it does not fall on a Sunday, and the plain All Souls' Day office
+; whenever it is not transferred -- are outside this fixture's own
+; window's reach for a second occurrence, so only the one real day above
+; is witnessed and adjudicated here.
+((id L1)
+ (citation "RG 476(f): \"Non dicitur symbolum ... f) in Missis defunctorum\" -- the Creed is never said at a Mass of the dead; rubrics_ef.ml's own header already documents this Mass-type as unmodelled")
+ (verdict lms_ordo)
+ (note "colitur's [creed] has no notion of a Requiem Mass in its inputs (temporal/observed/date), so RG 475(b)'s I-class branch fires unopposed on All Souls' Day (Class1, black). A pre-existing, self-documented scope limit (rubrics_ef.ml's own header), witnessed here for the first time on a real date rather than left as an abstract note: 2025-11-03, All Souls' Day transferred from Sunday 2 November. The Ordo (\"No Gl Sequence No Cr Pr of the Dead\") is correct on the rubric.")
+ (expected_rows 1))
diff --git a/test/dune b/test/dune
index d883d2f..44318a2 100644
--- a/test/dune
+++ b/test/dune
@@ -9,6 +9,7 @@
../lang/traditions.ini
../data/ef/expected-divergences.sexp
../data/ef/expected-divergences-missalemeum.sexp
+ ../data/ef/expected-divergences-lms.sexp
../data/ef/lectionary.sexp
../data/ef/commons.sexp
../data/ef/examples/diocesan-example.sexp
@@ -16,6 +17,7 @@
fixtures/missalemeum-ef-2026-2027.txt
fixtures/missalemeum-ef-2038.txt
fixtures/missalemeum-ef-2035.txt
+ fixtures/lms-ordo-2024-2025.sexp
../templates/ef/ordo.tex
../templates/ef/ordo.ms
../templates/ef/ordo.html
diff --git a/test/fixtures/lms-ordo-2024-2025.sexp b/test/fixtures/lms-ordo-2024-2025.sexp
new file mode 100644
index 0000000..01c87b9
--- /dev/null
+++ b/test/fixtures/lms-ordo-2024-2025.sexp
@@ -0,0 +1,1513 @@
+; test/fixtures/lms-ordo-2024-2025.sexp -- Task 6 (2026-08-21-colitur-
+; celebrant-rubrics-phase1)'s sixth validation layer: the Latin Mass
+; Society's own printed Ordo, an England & Wales diocesan Ordo -- 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 2026-08-22 via web search matching the PDF's own
+; version number and filename 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_2.21_2024-2025.pdf
+; (product page: https://lms.org.uk/product/latin-mass-society-ordo-2024-25)
+; 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-22
+; 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 test/fixtures/lms-ordo-2024-2025.sexp
+;
+; COVERAGE: 400 day-rows, 2024-11-27 through 2025-12-31 (2024-11-27, "End of November 2024",
+; 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; this Ordo was probed with the same discipline
+; before a single divergence was adjudicated):
+;
+; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed: this PDF
+; alone -- not the multi-year corpus the task brief's own grep count
+; was measured against -- 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).
+;
+; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG
+; 475-476), checked BEFORE trusting a single row of this fixture --
+; the technique CLAUDE.md records as the one that catches a source
+; silently omitting the very thing it is meant to witness:
+; 2024-12-01 (Advent Sunday, RG 475(a)) -- Ordo "No Gl Cr" -> TRUE
+; 2024-12-02 (ordinary Advent feria) -- Ordo "Gl No Cr" -> FALSE
+; 2024-12-26 (St Stephen, II class, but inside the Nativity octave,
+; RG 475(d)) -- Ordo "Gl Cr" -> TRUE
+; 2025-08-15 (the Assumption, I class, RG 475(b))
+; -- Ordo "Gl Cr" -> TRUE
+; 2025-08-16 (St Joachim, II class, no Lord/BVM/apostle clause
+; applies, RG 476(b)) -- Ordo "Gl No Cr" -> FALSE
+; All five predictions confirmed, both directions (TRUE and FALSE each
+; independently witnessed, including the Stephen/Joachim pair, which
+; are BOTH II-class non-Sunday saints and differ ONLY on the octave
+; question) -- this source is discriminating, not a constant, on the
+; Creed. See task-6-report.md for the full record.
+;
+; 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 this
+; task existed).
+;
+; 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 ("2025 1 The OCTAVE DAY of
+; the NATIVITY..." printed with "Thu" wrapped onto the following
+; line and the year token "2025" where "2026" belongs -- a literal
+; duplicate, word for word, of the fixture's own already-extracted
+; 2025-01-01 row) is excluded outright: the extractor's own stop
+; marker (a line whose first token is a bare 4-digit year) halts
+; the scan before it, so this fixture's last row is 2025-12-31.
+; - 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 sentinels bound it to the
+; Ordo proper, "End of November 2024" through the stop marker
+; above).
+(((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))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2024-12-01) (weekday Sun) (title "ADVENT SUNDAY I Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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)) (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)) (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))
+ (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)) (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (has_diocesan_variant true))
+ ((date 2025-01-06) (weekday Mon) (title "The EPIPHANY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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)) (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)) (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)) (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)) (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (has_diocesan_variant false))
+ ((date 2025-02-16) (weekday Sun) (title "SEPTUAGESIMA SUNDAY II Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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)) (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)) (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)) (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)) (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)) (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))
+ (has_diocesan_variant false))
+ ((date 2025-02-23) (weekday Sun) (title "SEXAGESIMA SUNDAY II Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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))
+ (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)) (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)) (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))
+ (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)) (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)) (has_diocesan_variant true))
+ ((date 2025-03-02) (weekday Sun) (title "QUINQUAGESIMA SUNDAY II Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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)) (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-05) (weekday Wed) (title "ASH WEDNESDAY I Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-08) (weekday Sat) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-10) (weekday Mon) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-03-11) (weekday Tue) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-13) (weekday Thu) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-17) (weekday Mon) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-03-18) (weekday Tue) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-20) (weekday Thu) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-22) (weekday Sat) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-26) (weekday Wed) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-03-27) (weekday Thu) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-03-28) (weekday Fri) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant true))
+ ((date 2025-03-29) (weekday Sat) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-03-31) (weekday Mon) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-01) (weekday Tue) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-02) (weekday Wed) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant true))
+ ((date 2025-04-03) (weekday Thu) (title "FERIA III Cl V JCHP")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant true))
+ ((date 2025-04-04) (weekday Fri) (title "FERIA III Cl V SH")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-04-06) (weekday Sun) (title "PASSION SUNDAY I Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-04-07) (weekday Mon) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-08) (weekday Tue) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-09) (weekday Wed) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-10) (weekday Thu) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-04-12) (weekday Sat) (title "FERIA III Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-13) (weekday Sun) (title "PALM SUNDAY I Cl R")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-04-17) (weekday Thu) (title "MAUNDY THURSDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-18) (weekday Fri) (title "GOOD FRIDAY I Cl B")
+ (formulary_override ()) (bvm_numeral ()) (gloria ()) (creed ())
+ (has_diocesan_variant false))
+ ((date 2025-04-19) (weekday Sat) (title "HOLY SATURDAY I Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (false))
+ (has_diocesan_variant false))
+ ((date 2025-04-20) (weekday Sun) (title "EASTER I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant true))
+ ((date 2025-04-21) (weekday Mon) (title "EASTER MONDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-04-22) (weekday Tue) (title "EASTER TUESDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-04-23) (weekday Wed) (title "EASTER WEDNESDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-04-24) (weekday Thu) (title "EASTER THURSDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-04-27) (weekday Sun) (title "LOW SUNDAY I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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)) (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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)) (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)) (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)) (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))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant true))
+ ((date 2025-05-29) (weekday Thu) (title "The ASCENSION I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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)) (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))
+ (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))
+ (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)) (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)) (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))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-06-08) (weekday Sun) (title "PENTECOST I Cl R")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-06-09) (weekday Mon) (title "WHIT MONDAY I Cl R")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (has_diocesan_variant false))
+ ((date 2025-06-10) (weekday Tue) (title "WHIT TUESDAY I Cl R")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-06-12) (weekday Thu) (title "WHIT THURSDAY I Cl R")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false))
+ ((date 2025-06-19) (weekday Thu) (title "CORPUS CHRISTI I Cl W")
+ (formulary_override ()) (bvm_numeral ()) (gloria (true)) (creed (true))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (has_diocesan_variant true))
+ ((date 2025-11-30) (weekday Sun) (title "ADVENT SUNDAY I Cl V")
+ (formulary_override ()) (bvm_numeral ()) (gloria (false)) (creed (true))
+ (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)) (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))
+ (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))
+ (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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)) (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)) (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))
+ (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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)) (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)) (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (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))
+ (has_diocesan_variant false)))
diff --git a/test/test_colitur.ml b/test/test_colitur.ml
index 60b61fc..8d05f75 100644
--- a/test/test_colitur.ml
+++ b/test/test_colitur.ml
@@ -14,7 +14,8 @@ let () =
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_rubrics_ef.suite;
- Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; Test_golden.suite;
+ Test_differential.suite; Test_oracle.suite; Test_oracle.suite_2038; Test_oracle.suite_2035; Test_lms_ordo.suite;
+ Test_golden.suite;
("lectionary", Test_lectionary.suite);
("lectionary-ef", Test_lectionary_ef.suite);
Test_escape.suite;
diff --git a/test/test_lms_ordo.ml b/test/test_lms_ordo.ml
new file mode 100644
index 0000000..c5cae1a
--- /dev/null
+++ b/test/test_lms_ordo.ml
@@ -0,0 +1,467 @@
+(* Task 6 (2026-08-21-colitur-celebrant-rubrics-phase1): validation layer 6
+ -- the Latin Mass Society's own printed Ordo for England & Wales
+ (test/fixtures/lms-ordo-2024-2025.sexp; that file's own provenance
+ header carries the full source citation, SHA-256 and the
+ characterisation record demanded before trusting a single row of it).
+
+ 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, ISBN 9781739209636, 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.
+
+ SCOPE, decided after running the comparison against real data (not
+ guessed in advance -- see the fixture's own CHARACTERISATION section
+ and task-6-report.md for the measurements this scoping rests on):
+
+ - The CREED (RG 475-476, {!Rite_ef.Rubrics_ef.creed}): compared on
+ every day, full 1:1. One genuine day is EXCLUDED, not silently
+ skipped: 2025-04-18 (Good Friday) has no Mass in the 1955-restored
+ Holy Week, so the Ordo prints no Gl/Cr line at all -- [test_
+ creed_coverage] asserts this is the ONLY such day, so a future
+ parsing regression that swallowed a real row would fail loudly
+ here, not slip into "explained" silently.
+
+ - The BVM-SATURDAY SEASONAL SELECTION (RG 309(a), "iuxta temporum
+ diversitatem", {!Rite_ef.Lectionary_ef.bvm_saturday_citations}):
+ the coordinator addendum's own "sharper check" -- 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.
+ Built, because the extraction supports it (whole-line anchored
+ match against all five, see the fixture header on why substring
+ matching is wrong): every {!Colitur_kernel.Mass_formulary.Votive}
+ day inside the fixture's own 2024-11-27..2025-12-31 window is
+ checked against the numeral's implied season.
+
+ - 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, each independently
+ 100% clean against the real fixture:
+ [Proper] (179 of 400 days): the Ordo shows NO "Mass of ..." line.
+ [Preceding_sunday] (66 of 400): the Ordo ALWAYS shows one.
+ [Common] (2 of 400): the Ordo shows NO "Mass of ..." line either
+ -- a Common-routed saint (ubaldus, didacus) still keeps his OWN
+ title in the Ordo, borrowing only the Common's PREFACE ("Common
+ Pr" on the title line itself), never a separate override line.
+ [Votive] is covered by the BVM check above instead (its own
+ override line IS the roman-numeral line).
+ [Own_slug] (139 of 400) is DELIBERATELY EXCLUDED from this axis,
+ not silently -- a real, evidenced data-representation fact, not a
+ guess: 11 of its 139 days DO show a "Mass of ..." override
+ ("2nd Sunday of Advent", "the Epiphany", "1st Sunday after
+ Pentecost"), because data/ef/lectionary.sexp carries some ferial
+ slugs (e.g. [ef-advent-2-monday]) as an EXPLICIT entry whose
+ citations are byte-identical to the following Sunday's own
+ ([ef-advent-sunday-2]: both "Rom 15:4-13" / "Matt 11:2-10" --
+ checked directly against the shipped data), rather than resolving
+ through the {!Colitur_kernel.Mass_formulary.Preceding_sunday}
+ fallback path. Both representations name the SAME texts -- this is
+ a provenance-field ambiguity in colitur's own data, not a rubric
+ question the Ordo could adjudicate either way, so asserting on it
+ would manufacture exactly the kind of false divergence the
+ coordinator addendum's "collapsed to ~0 real ones" warning is
+ about. Recorded here rather than dropped silently, per the task
+ brief's own instruction for exactly this situation.
+
+ GLORIA is extracted into the 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 (the
+ design doc defers it explicitly), so there is nothing on colitur's own
+ side to compare it against. Comparing it would be comparing the Ordo
+ against nothing.
+
+ DIOCESAN SCOPE: colitur computes the UNIVERSAL General Roman Calendar
+ only (no diocesan overlay loaded by the differential/oracle harnesses
+ anywhere in this suite) -- the Ordo is an England & Wales diocesan
+ Ordo, and 156 of its 400 days (39%) carry at least one diocesan
+ variant. Every comparison in this file reads ONLY the fixture's own
+ universal-block fields ([formulary_override], [bvm_numeral], [gloria],
+ [creed] are all derived from the text BEFORE the first diocese-list
+ line -- see extract_lms_ordo.ml's own [scan_block]); the diocesan text
+ itself is never read at all, only its PRESENCE is recorded
+ ([has_diocesan_variant]), so no diocesan variant can leak into a
+ comparison here by construction, not merely by care. *)
+
+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 MF = Colitur_kernel.Mass_formulary
+module V = Rite_ef.Vocab_ef
+
+let sanctoral_path = "../data/ef/sanctoral.sexp"
+let adjustments_path = "../data/ef/adjustments.sexp"
+let fixture_path = "fixtures/lms-ordo-2024-2025.sexp"
+let allow_list_path = "../data/ef/expected-divergences-lms.sexp"
+
+(* Asserted, not merely documented -- test_oracle.ml's own [fixture_sha256]
+ comment explains why: a hand-edit or partial re-extraction would
+ otherwise silently turn the oracle into an unlabelled snapshot of
+ whatever someone last ran. Matches the fixture's own provenance header. *)
+let fixture_sha256 = "da817b75c5bf40ed3be1d5f6890b199705e02ce4d42111253ab8547bccabc3f7"
+
+(* 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;
+ has_diocesan_variant : bool;
+}
+[@@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
+
+(* The fixture's own real window -- 2024-11-27 ("End of November 2024")
+ through 2025-12-31 (the day before the extractor's own stop marker).
+ 400 = 4 (27-30 Nov 2024) + 31 (Dec 2024) + 365 (2025, not a leap year). *)
+let window_first = "2024-11-27"
+let window_last = "2025-12-31"
+
+(* ---------------------------------------------------------------------- *)
+(* The colitur side, over the same window. Mirrors test_oracle.ml's own *)
+(* [colitur_rows]: the resolution walk starts a year EARLY because a *)
+(* liturgical year is Advent-anchored and straddles two civil years. *)
+(* ---------------------------------------------------------------------- *)
+
+type colitur_row = {
+ c_date : string;
+ c_season : V.season;
+ c_formulary : MF.t option;
+ c_creed : bool;
+}
+
+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 = 2023 to 2025 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 y m d = match Date.make ~year:y ~month:m ~day:d with Ok t -> t | Error e -> failwith e in
+ let rows = ref [] in
+ let d = ref (mk 2024 11 27) in
+ let stop = mk 2025 12 31 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 }
+ :: !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 *)
+(* (private to that .ml, no .mli export, and re-deriving here is itself *)
+(* the more useful check: importing colitur's own function would make *)
+(* this axis tautological). Mirrors that function's own season match *)
+(* exactly -- see its citation in lectionary_ef.ml for the scan lines. *)
+(* ---------------------------------------------------------------------- *)
+
+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]. *)
+(* ---------------------------------------------------------------------- *)
+
+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 (2024-11-27..2025-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
+
+(* Good Friday (2025-04-18) has no Mass at all in the 1955-restored Holy
+ Week -- the Ordo prints no Gl/Cr line, confirmed directly against the
+ source (extract_lms_ordo's own row for that date, and the raw pdftotext
+ text: "The Solemn Liturgical Action is celebrated in the afternoon...",
+ no "Gl"/"Cr" token anywhere in the block). Asserted as the ONLY such
+ day, not merely observed once: a future parsing regression that
+ swallowed a real Gl/Cr line would otherwise silently join this
+ "not applicable" 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.creed = None) ordo in
+ Alcotest.(check (list string)) "only Good Friday has no Ordo Creed marker" [ "2025-04-18" ]
+ (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 (formulary=%s)" o.date o.title c.c_creed
+ (Option.get o.creed)
+ (match c.c_formulary with
+ | Some f -> Colitur_kernel.Slug.to_string f.MF.said
+ | None -> "NONE")
+
+(* The core assertion: every Creed divergence, over all 400 days (Good
+ Friday excluded per [test_creed_coverage] above -- it is not a
+ divergence, it is a day with nothing on the Ordo's side to compare),
+ falls in a named, cited, adjudicated allow-list entry. Zero
+ unexplained. *)
+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 l1_dates = [ "2025-11-03" ] 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 -> () (* Good Friday, see test_creed_coverage *)
+ | Some ocreed ->
+ if Bool.equal ocreed c.c_creed then ()
+ else if List.mem o.date l1_dates then
+ Hashtbl.replace explained_counts "L1" (1 + try Hashtbl.find explained_counts "L1" with Not_found -> 0)
+ else 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;
+ (* every declared entry must actually have fired, so the allow-list
+ cannot silently accumulate a dead entry nothing triggers any more *)
+ 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
+
+(* ---------------------------------------------------------------------- *)
+(* The BVM-Saturday seasonal selection -- the coordinator addendum's own *)
+(* "sharper check". Restricted to colitur's [Votive] days, which is *)
+(* exactly {!Rite_ef.Lectionary_ef.is_bvm_saturday_office}'s own domain. *)
+(* ---------------------------------------------------------------------- *)
+
+let test_bvm_seasonal_selection () =
+ let ordo = ordo_rows () in
+ let colitur = colitur_rows () 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) "14 BVM-Saturday (Votive) days fall inside the fixture's own window" 14
+ (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 -> 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
+
+(* Reverse direction: every Ordo BVM-numeral day is a colitur Votive day
+ too (rules out the Ordo naming a Saturday BVM Mass colitur never
+ computed the office for at all). *)
+let test_bvm_numeral_implies_votive () =
+ let ordo = ordo_rows () in
+ let colitur = colitur_rows () 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
+
+(* ---------------------------------------------------------------------- *)
+(* Formulary override, restricted to Proper/Preceding_sunday/Common -- *)
+(* see this file's own header for why Own_slug is excluded, and Votive is *)
+(* covered by the BVM checks above instead. *)
+(* ---------------------------------------------------------------------- *)
+
+let test_formulary_override_by_source () =
+ let ordo = ordo_rows () in
+ let colitur = colitur_rows () in
+ let pairs = List.combine ordo colitur in
+ let counts = Hashtbl.create 8 in
+ let bump k = Hashtbl.replace counts k (1 + try Hashtbl.find counts k with Not_found -> 0) in
+ let bad = ref [] in
+ List.iter
+ (fun (o, c) ->
+ match c.c_formulary with
+ | Some { MF.via = MF.Proper; _ } ->
+ bump "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; _ } ->
+ bump "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; _ } ->
+ bump "preceding_sunday";
+ if o.formulary_override = None then bad := Printf.sprintf "%s: Preceding_sunday day but Ordo shows no override" o.date :: !bad
+ | Some { MF.via = MF.Votive; _ } | Some { MF.via = MF.Own_slug; _ } | None -> ())
+ pairs;
+ Alcotest.(check (list string)) "no unexplained formulary-override mismatch on Proper/Common/Preceding_sunday days"
+ [] (List.rev !bad);
+ Alcotest.(check int) "179 Proper days in the window" 179 (try Hashtbl.find counts "proper" with Not_found -> 0);
+ Alcotest.(check int) "2 Common days in the window" 2 (try Hashtbl.find counts "common" with Not_found -> 0);
+ Alcotest.(check int) "66 Preceding_sunday days in the window" 66
+ (try Hashtbl.find counts "preceding_sunday" with Not_found -> 0)
+
+let test_via_distribution_totals_400 () =
+ let colitur = colitur_rows () 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 400-day window" 400 total
+
+let suite =
+ ( "lms-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 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 "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 matches on Proper/Common/Preceding_sunday days" `Quick
+ test_formulary_override_by_source;
+ Alcotest.test_case "the via distribution sums to the full window" `Quick test_via_distribution_totals_400
+ ] )
diff --git a/tools/dune b/tools/dune
index 0dd0937..487751e 100644
--- a/tools/dune
+++ b/tools/dune
@@ -23,6 +23,19 @@
(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)
+ (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
diff --git a/tools/extract_lms_ordo.ml b/tools/extract_lms_ordo.ml
new file mode 100644
index 0000000..b7c97fd
--- /dev/null
+++ b/tools/extract_lms_ordo.ml
@@ -0,0 +1,422 @@
+(* 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;
+ 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, 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
+ (formulary_override, bvm_numeral, gloria, creed, 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 }
+
+let start_sentinel = [ "End"; "of"; "November"; "2024" ]
+
+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 start_idx =
+ let rec go i = if i >= n then die "start sentinel %S not found" (String.concat " " start_sentinel)
+ else if split_ws (trimmed i) = start_sentinel then i else 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 (start_idx + 1)
+ in
+ Printf.printf "extract_lms_ordo: Ordo body lines %d..%d (of %d total)\n" start_idx stop_idx n;
+ (* --- the scan: month/year tracker + block accumulator ------------------ *)
+ let cur_month = ref 11 and cur_year = ref 2024 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, 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; 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
+ 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));
+ 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\n"
+ (List.length rows) with_variant with_override with_bvm;
+ (* --- 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
+ let header =
+ Printf.sprintf
+ {|; test/fixtures/lms-ordo-2024-2025.sexp -- Task 6 (2026-08-21-colitur-
+; celebrant-rubrics-phase1)'s sixth validation layer: the Latin Mass
+; Society's own printed Ordo, an England & Wales diocesan Ordo -- 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 2026-08-22 via web search matching the PDF's own
+; version number and filename 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_2.21_2024-2025.pdf
+; (product page: https://lms.org.uk/product/latin-mass-society-ordo-2024-25)
+; 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: %s
+; Extracted (UTC): %s
+; 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 test/fixtures/lms-ordo-2024-2025.sexp
+;
+; COVERAGE: %d day-rows, %s through %s (2024-11-27, "End of November 2024",
+; 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; this Ordo was probed with the same discipline
+; before a single divergence was adjudicated):
+;
+; 1. Gl/Cr are printed PER MASS-OPTION, not per day (confirmed: this PDF
+; alone -- not the multi-year corpus the task brief's own grep count
+; was measured against -- 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).
+;
+; 2. OPPOSITE-PREDICTION PROBES against Rite_ef.Rubrics_ef.creed (RG
+; 475-476), checked BEFORE trusting a single row of this fixture --
+; the technique CLAUDE.md records as the one that catches a source
+; silently omitting the very thing it is meant to witness:
+; 2024-12-01 (Advent Sunday, RG 475(a)) -- Ordo "No Gl Cr" -> TRUE
+; 2024-12-02 (ordinary Advent feria) -- Ordo "Gl No Cr" -> FALSE
+; 2024-12-26 (St Stephen, II class, but inside the Nativity octave,
+; RG 475(d)) -- Ordo "Gl Cr" -> TRUE
+; 2025-08-15 (the Assumption, I class, RG 475(b))
+; -- Ordo "Gl Cr" -> TRUE
+; 2025-08-16 (St Joachim, II class, no Lord/BVM/apostle clause
+; applies, RG 476(b)) -- Ordo "Gl No Cr" -> FALSE
+; All five predictions confirmed, both directions (TRUE and FALSE each
+; independently witnessed, including the Stephen/Joachim pair, which
+; are BOTH II-class non-Sunday saints and differ ONLY on the octave
+; question) -- this source is discriminating, not a constant, on the
+; Creed. See task-6-report.md for the full record.
+;
+; 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 this
+; task existed).
+;
+; 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 ("2025 1 The OCTAVE DAY of
+; the NATIVITY..." printed with "Thu" wrapped onto the following
+; line and the year token "2025" where "2026" belongs -- a literal
+; duplicate, word for word, of the fixture's own already-extracted
+; 2025-01-01 row) is excluded outright: the extractor's own stop
+; marker (a line whose first token is a bare 4-digit year) halts
+; the scan before it, so this fixture's last row is 2025-12-31.
+; - 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 sentinels bound it to the
+; Ordo proper, "End of November 2024" through the stop marker
+; above).
+|}
+ pdf_sha (today ()) (List.length rows)
+ (match rows with r :: _ -> r.date | [] -> "?")
+ (match List.rev rows with r :: _ -> r.date | [] -> "?")
+ with_variant (List.length rows)
+ (Printf.sprintf "%.1f" (100.0 *. float_of_int with_variant /. float_of_int (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