aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md123
-rw-r--r--data/ef/adjustments.sexp45
-rw-r--r--data/ef/expected-divergences-missalemeum.sexp37
-rw-r--r--lib/kernel/celebration.mli13
-rw-r--r--lib/kernel/precedence.ml22
-rw-r--r--lib/kernel/precedence.mli31
-rw-r--r--lib/kernel/validate.ml90
-rw-r--r--lib/kernel/validate.mli26
-rw-r--r--lib/rites/rite_ef/precedence_ef.ml333
-rw-r--r--lib/rites/rite_ef/precedence_ef.mli121
-rw-r--r--test/fixtures/missalemeum-ef-2026-2027.provenance43
-rw-r--r--test/fixtures/missalemeum-ef-2026-2027.txt1460
-rw-r--r--test/test_calendar.ml5
-rw-r--r--test/test_differential.ml10
-rw-r--r--test/test_golden.ml107
-rw-r--r--test/test_oracle.ml461
-rw-r--r--test/test_precedence.ml4
-rw-r--r--test/test_precedence_ef.ml357
-rw-r--r--test/test_rite_ef.ml94
-rw-r--r--test/test_validate.ml19
-rw-r--r--tools/extract_missalemeum_oracle.py21
21 files changed, 2440 insertions, 982 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 25d3339..4fb93f9 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -113,11 +113,54 @@ against missalemeum; layer 5 pins ~30 dates.
the week column. It also **shares colitur's own lineage**: colitur's data was
bootstrapped from lectio, so an error both inherited is invisible here. Proven:
Holy Thursday was violet in both because both were wrong.
-- Layer 4 is **two years wide** and compares rank, colour-membership and
- commemoration presence/count — **never celebration identity**.
-- Together they sleep through **commemoration identity**: reversing `admit`'s
- dignity sort, so the engine admits the *worst* commemorations, leaves all eight
- differential and oracle assertions green across 17 531 days.
+- **Layer 4's commemoration-identity gap is CLOSED** (2026-08-12, Task B, branch
+ `ef-rg16a`, two fix rounds): it used to compare presence/count only, never
+ *which* commemoration won — reversing `admit`'s dignity sort (the engine
+ admitting the *worst* commemoration, an outright RG 111 violation) left all
+ eight differential and oracle assertions green across 17 531 days. Layer 4 now
+ also compares **identity** — colitur's own resolved English name
+ (`Celebration.t.names`, `en`) against missalemeum's title text, for every day
+ both streams admit the same count. The mapping resolves **every
+ SANCTORAL-origin commemoration** (colitur's own name field, bootstrapped from
+ lectio, verified to match missalemeum's titles character-for-character); it
+ **cannot resolve a TEMPORAL-origin one** (an impeded feria/Ember/Rogation day —
+ `Rite_ef.Temporal_ef` never sets a celebration name) — that case is **never
+ silently skipped**: it is a separate, counted, allow-listed outcome
+ (`Comm_identity_unresolved`, 19 of 227 non-empty-commemoration days over
+ 2026–2027), not a silent pass. ONE genuine identity mismatch remains adjudicated
+ open (register §4/§6.1, `data/ef/expected-divergences-missalemeum.sexp` M16): a
+ known unimplemented office (the Seven Sorrows of Passion Friday). Proof of
+ teeth, reproduced twice: reversing `admit`'s *dignity*-based sort (the
+ historical defect shape) turns layer 4 red — an unexplained
+ `commemoration-identity-mismatch` day (colitur admitting "St. Thecla" where
+ both the rubric and missalemeum require "St. Linus"); separately, disabling
+ `band`'s own `Commemoration_only` guard (below) also turns it red, on the same
+ date this whole gap was originally found through — both reverted after
+ confirming.
+- **The `admit` same-rank tie-break is RG 113, not an uncited convention** (same
+ task, fix round 1): RG 113's own second sentence ("in admittendis et ordinandis
+ aliis commemorationibus, servetur ordo tabellae praecedentiae"), previously
+ quoted only in its first half, is the real rule — `admit` now orders/selects by
+ `Precedence_ef.band` (RG 91's own table), not RG 8's coarse four-class rank.
+ **`band` itself had a fidelity bug this exercise surfaced**: RG 91's table
+ enumerates only "dies liturgici" (real feasts), so a `Celebration.t.status =
+ Commemoration_only` candidate has NO row in it at all — `band` used to read
+ `rank` alone and silently lent such a candidate the same table entry as a
+ genuine `Feast` of its own rank, manufacturing ties RG 113 never created (the
+ original "Maurice vs Thomas of Villanova, both entry 24" example was this bug,
+ not a real RG 91 tie). Fixed at the source: `band` now returns `unclassified`
+ for any `Commemoration_only` candidate, checked first. Measured, independently,
+ twice (`compare_precedence`'s own ordering-criterion change, then `band`'s
+ fidelity fix): the ORDERING-CRITERION change alone is zero-blast-radius
+ (byte-identical across the whole 1583–9999 domain — a correctness-of-citation
+ fix, not an answer-changing one); the `band`-FIDELITY fix has a real, large,
+ fully-classified effect, **4 451 days across the whole domain, exactly 4
+ verified shapes, no surprises** (register §6.1). A genuine "two different
+ candidates on the identical REAL table entry" residual was searched for
+ exhaustively across the whole domain and found EMPTY — the tie-break `admit`
+ still breaks alphabetically is real but narrower than first thought: it is only
+ ever exercised between two `Commemoration_only` candidates, neither of which has
+ any RG 91 table position to compare in the first place.
## Current state (Plans 1–3 DONE — verify with `git log`)
@@ -186,8 +229,10 @@ dune exec colitur -- day 2026 | head
- **Plan 4 — OF rite module** (proves `RITE` generalizes) → the lectionary
bootstrap and citations → full output/rendering → hardening and a first tag.
- **Open Plan 4 with the two behaviour items below**, before OF: they are the
- places the five layers, taken together, currently sleep through a real error.
+ **Both behaviour items below are now RESOLVED** (RG 16(a) and commemoration
+ identity, closed on branch `ef-rg16a`) — kept here as the record of what the
+ five layers, taken together, used to sleep through, and as the shape a
+ future gap of the same kind would need to be caught by.
### Carried into Plan 4 (read before starting)
@@ -199,17 +244,59 @@ nowhere in git (`docs/` is gitignored).
**The two behaviour items, in order:**
-1. **RG 16(a) — the largest known-wrong output on the branch.** A Feast of the
- Lord occurring on a II-class Sunday takes the Sunday's place *"cum omnibus
- iuribus et privilegiis: de dominica, proinde, **nulla fit commemoratio**"*.
- colitur commemorates the Sunday anyway: **5 996 wrong days over 1583–9999**,
- 369 of them in 1583–2100. **Zero** instances fall in the oracle window and none
- is pinned, so all five layers miss it. Needs a signature change — `privilege_of`
- cannot currently see the winner's `subject`. Register §6.0.
-2. **Commemoration identity is unasserted** outside ~3 test rows (see the layer
- caveats above). Related: `compare_dignity` breaks same-rank ties
- **alphabetically**, with no RG warrant, and over 2005–2050 the admission cut
- falls between two same-rank candidates on **66 days**.
+1. **RG 16(a) — RESOLVED (RG16(a) task, branch `ef-rg16a`, 2026-08-12; ONE
+ FIX ROUND of review after the first pass — see register §6.0 for the full,
+ corrected account).** Was the largest known-wrong output on the branch: a
+ Feast of the Lord occurring on a II-class Sunday takes the Sunday's place
+ *"cum omnibus iuribus et privilegiis: de dominica, proinde, **nulla fit
+ commemoratio**"*, and colitur used to commemorate the Sunday anyway
+ (**5 996 wrong days over 1583–9999**, 369 of them in 1583–2100,
+ re-confirmed exactly, twice, independently). Fixed in
+ `Rite_ef.Precedence_ef.disposition` with **no signature change** —
+ `disposition` already took `winner:...` (RG 33's own vigil-omission branch
+ already read it). A SECOND, related bug needed a genuine kernel signature
+ change: `Precedence.rules.admit` gained a `~temporal` parameter, because
+ RG 16(a) also breaks the assumption that `observed` IS the day's own
+ temporal-cycle office for RG 111(b)'s Sunday rank-floor check (an
+ unrelated saint could otherwise be wrongly admitted into the freed slot —
+ confirmed on 1 178 real days, 6 August, before this second fix).
+ **The sanctoral data question was more contested than the first pass
+ found**: the Purification (2 Feb) was FIRST retagged `Bvm` (calendarium
+ title argument), then REVERTED to `Lord` in fix round 1 on the user's own
+ ruling — follow the oracle, which treats the Purification as taking an
+ occurring Sunday's place outright, unlike an ordinary Marian feast (real
+ primary-text counter-evidence, RG 120(b)'s colour rule, remains on record
+ as the argument the other way). Only `most-holy-name-of-mary` stays
+ retagged `Bvm`. A related, unresolved primary-source finding: the Common
+ of the Dedication of a Church's own classification (*"Festum
+ Dedicationis Ecclesiae est festum Domini"*) means St Michael's Dedication
+ (29 Sep) may also be `Lord`, not `Saint` — measured, not applied (1 200
+ days domain-wide if it were). Two further open items recorded, not fixed:
+ 13 January (Baptism of the Lord, mistagged `Saint`, and separately, RG 112
+ — a feast/mystery of one Divine Person excludes a commemoration of
+ another of the SAME Person — entirely unimplemented, confirmed live on 7
+ real years).
+2. **Commemoration identity — RESOLVED (Task B, branch `ef-rg16a`, 2026-08-12;
+ ONE FIX ROUND of review after the first pass — see register §6.1 for the
+ full, corrected account).** Was unasserted outside ~3 test rows — **the
+ exact gap the RG 16(a) fix round above had exploited**: the lectio
+ differential (layer 3) compares season/slug/rank/colour only, never
+ commemorations, BY DESIGN (lectio has no RG 111 admission logic of its
+ own) and still does not — that part of this item is unchanged and remains
+ the reason layer 4, not layer 3, had to close this gap. Layer 4
+ (missalemeum, 2026–2027) now compares commemoration IDENTITY, not only
+ presence/count (see the "know what each layer cannot see" section above
+ for the mapping and its limits). While building it, found and fixed a
+ SECOND, independent bug the exercise surfaced: `Precedence_ef.band` gave a
+ `Commemoration_only` candidate the same RG 91 table entry as a genuine
+ `Feast` of its own rank (RG 91's table has no row for a bare commemoration
+ at all) — **4 451 days wrong across the whole 1583–9999 domain**, exactly
+ 4 verified shapes, fixed at the source. The `admit` same-rank tie-break
+ itself is RG 113 (previously uncited), not the alphabetical convention
+ this item used to describe — reconciled against the Plan-3-era "66 days"
+ figure: 599 is the tie POPULATION, 65 (or 67) the real ADMITTED-SET
+ decisions within it, 149 order-only — all now independently reproduced
+ (register §6.1), not merely asserted.
**Structural items, cheapest to fix before OF exists:**
diff --git a/data/ef/adjustments.sexp b/data/ef/adjustments.sexp
index 85d7fa1..05ee401 100644
--- a/data/ef/adjustments.sexp
+++ b/data/ef/adjustments.sexp
@@ -10,4 +10,47 @@
; or special-cased in code, per the task brief -- an auditable, diagnosable
; removal (Overlay.apply's own diagnostic fires if this slug is ever absent,
; e.g. after a re-bootstrap that renames it), not a silent drop.
-((id ef-adjustments) (directives ((Suppress vigil-of-christmas))))
+;
+; RG16(a) task (docs/research/rules-register.md §6.0): corrects one of
+; data/ef/sanctoral.sexp's six `(subject Lord)` entries, inherited unchecked
+; from lectio's own `class = lord` field (tridentine-calendar.ini) --
+; `most-holy-name-of-mary` (12 Sep): calendarium line "Sanctissimi Nominis
+; Mariae, III classis" -- "Nominis Mariae", the Name of MARY, not of the
+; Lord, with no counter-evidence found anywhere (the "D. N. I. C." formula
+; the genuinely Lord-tagged entries carry, e.g. 6 Aug "IN TRANSFIGURATIONE
+; D. N. I. C.", is simply absent here, and nothing else in the calendarium
+; suggests otherwise). This tag has no behavioural effect either way today
+; ({!Precedence_ef.band}'s entry 14, the only place [subject] is tested for
+; a II-class candidate, requires [Class2]; this entry is [Class3]) -- kept
+; for the data's own accuracy, not because anything currently reads it.
+;
+; The tag [Bvm] itself carries no further systematic meaning in this
+; codebase beyond "not Lord" -- after this correction it exists on exactly
+; this one entry, while every other Marian feast (the Assumption, the
+; Immaculate Conception, the Nativity of the BVM, ...) stays `(subject
+; Saint)`. Nothing reads [Bvm] specifically; {!Subject.t}'s four-way split
+; is not fully exercised by this codebase's own logic, only [Lord] is.
+;
+; RG16(a) task, fix round 1 (CRITICAL finding, reverted): a companion Edit
+; here previously also retagged `purification-of-the-blessed-virgin-mary`
+; (2 Feb) to [Bvm], on the same calendarium-title argument ("B. Mariae
+; Virg.", not "D. N. I. C."). REVERTED -- the user has ruled: follow the
+; oracle. missalemeum (this project's designated EF oracle) treats the
+; Purification as taking an occurring II-class Sunday's place OUTRIGHT, with
+; NO commemoration of the Sunday (`2020-02-02`, `2014-02-02`: title
+; "Purification of the Blessed Virgin Mary", `"commemorations": []`),
+; exactly RG 16(a)'s own "festum Domini" treatment -- and NOT the treatment
+; it gives an ordinary Marian feast on a Sunday (`2019-09-08`, the Nativity
+; of the BVM: title "XIII Sunday after Pentecost", the FEAST demoted to a
+; commemoration, the Sunday observed -- the opposite pattern). Genuine
+; primary-text counter-evidence for the Marian reading remains on record
+; (RG 120(b): the white-colour rule groups 2 February under "B. Mariae
+; Virg.", a SEPARATE category from "Domini" -- register §6.0 quotes it in
+; full), so the calendarium TITLE and the oracle's BEHAVIOUR disagree here;
+; the user's ruling resolves that disagreement in the oracle's favour for
+; this codebase's own purposes, not by declaring the calendarium argument
+; wrong. See register §6.0 for the full account of both sides.
+((id ef-adjustments)
+ (directives
+ ((Suppress vigil-of-christmas)
+ (Edit most-holy-name-of-mary ((Set_subject Bvm))))))
diff --git a/data/ef/expected-divergences-missalemeum.sexp b/data/ef/expected-divergences-missalemeum.sexp
index f50898b..53e93d4 100644
--- a/data/ef/expected-divergences-missalemeum.sexp
+++ b/data/ef/expected-divergences-missalemeum.sexp
@@ -19,10 +19,21 @@
; absorbed as if colitur were right. TWO entries (M11 and M13) are
; [verdict open] -- corrected, final fix wave, item 7: this note previously
; said "one entry (M13)", missing M11 (whose own verdict changed from
-; [colitur] to [open] in fix round 1, see M11's own entry below). Both are
-; adjudicated as UNRESOLVED after real primary-source effort, not defaulted
-; past -- see each entry's own note and the task report for the full
-; search.
+; [colitur] to [open] in fix round 1, see M11's own entry below). Task B
+; (branch ef-rg16a) briefly added a THIRD, M17, adjudicated [open] as a
+; "genuine same-band tie RG 113 does not resolve" -- CORRECTED, Task B fix
+; round 1: M17 was wrong. The tie was manufactured by Precedence_ef.band
+; lending a Commemoration_only candidate the same table entry as a genuine
+; Feast of its own rank (RG 91's table has no row for a bare commemoration
+; at all); fixed in band itself, and the divergence disappears entirely --
+; M17 was REMOVED, not re-adjudicated to a different verdict. ONE entry
+; (M15) carries a fourth verdict, [unresolvable] -- a LIMIT of this
+; comparator (no English name exists on colitur's side for a temporal-
+; origin commemoration to compare), not a rubric dispute or a data gap
+; either engine is wrong about; see M15's own note. All remaining OPEN
+; entries are adjudicated as UNRESOLVED/UNRESOLVABLE after real
+; primary-source effort, not defaulted past -- see each entry's own note
+; and the task report for the full search.
;
; [expected_rows] is the exact row count this entry accounts for over the
; fixture's 2026-2027 span: a REGRESSION PIN, not documentation --
@@ -59,9 +70,9 @@
(note "Independently confirmed by the oracle, not a new finding: missalemeum's \"Pro rogationibus\" commemoration on St Mark's day (25 April, the Major Litanies' fixed date) is exactly the missing office register §6 already tracks. Only 2026 shows as a comparator MISMATCH: 25 April 2026 is a Saturday with Mark winning outright, so colitur's commemoration list is empty where the oracle's carries \"Pro rogationibus\" -- a real presence gap. 25 April 2027 is a Sunday: the Sunday wins on BOTH sides, and each side's own single commemoration slot goes to a DIFFERENT candidate (colitur: St Mark himself, an ordinary II-class sanctoral loser admitted under RG111(b)'s \"de festo II classis\" slot; missalemeum: the Major Litanies) -- both non-empty, same count, so this comparator's count-only axis (deliberately not slug-identity, see test_oracle.ml's own header) cannot see that mismatch; the underlying gap is the same, just invisible to this year's row.")
(expected_rows 1))
((id M6)
- (citation "1962 calendarium, 14 August row: \"Vigilia, II classis.\" -- nothing else listed -- primary-source-verified 2026-08-12")
- (verdict colitur)
- (note "The reverse of M4/M7/M9: no commemoration is listed for 14 August anywhere in the primary source this project treats as authoritative. data/ef/sanctoral.sexp agrees (a single entry, vigil-of-the-assumption). missalemeum's \"St. Eusebius\" for this date has no support found here -- a DIFFERENT St Eusebius (bishop and martyr) is genuinely commemorated 16 December, matching lectio's own [eusebius] entry at THAT date, not this one.")
+ (citation "CORRECTED 2026-08-12, transcription-audit task (branch ef-rg16a): the previous citation below read the ELECTRONIC TRANSCRIPTION (1962-06-23,_SS_Ioannes_XXIII,_Missale_Romanum,_LT.pdf), which silently drops calendarium commemorations, and mistook its silence for the calendarium's own. A photographic scan (missale-romanum-1962.pdf), 14 August row: \"Vigilia, II classis, Commemoratio S. Eusebii Conf.\", with its own proper immediately following (\"Eodem die ... Et fit commemoratio S. Eusebii Conf.\") -- independently confirmed in the second scan, Missale Romanum 1962_text.pdf. Primary-source-verified 2026-08-12.")
+ (verdict missalemeum)
+ (note "The same shape as M4/M7/M9/M14, not the reverse of them: a genuine commemoration -- S. Eusebius, Confessor, 14 August -- is present in the 1962 calendarium and in missalemeum's own data, but absent from data/ef/sanctoral.sexp and from lectio's own tridentine-calendar.ini (no 08-14 entry beyond vigil-of-the-assumption). This Eusebius Confessor (14 Aug) is a genuinely DIFFERENT saint from Eusebius Bishop and Martyr (16 Dec, already correctly in data/ef/sanctoral.sexp, matching lectio's own [eusebius] entry at THAT date) -- both exist, at their own separate dates; the calendarium carries both. Not fixed here: single-source data, the same bootstrap-reach constraint as M4/M7/M9/M14 (would require touching ~/git/projects/lectio). Register docs/research/rules-register.md, Decisions item 4 and the transcription-audit record in section 6, has the full account and the wider calendarium sweep this correction came from.")
(expected_rows 2))
((id M7)
(citation "1962 calendarium, 26 October row: \"Com. S. Evaristi Papæ et Mart.\" -- primary-source-verified 2026-08-12")
@@ -101,5 +112,15 @@
((id M13)
(citation "OPEN -- not adjudicated. 1962 calendarium's March table: \"Feria VI post dominicam I Passionis: Commemoratio septem Dolorum B. Mariæ Virg.\" (confirmed real, every year) -- but RG 91's plain table (entry 11-13, Joseph, I class, vs entry 22, an ordinary III-class Passiontide feria) gives Joseph the day outright, with no RG 96 collision requiring a transfer, so the primary text found here does not by itself explain missalemeum's result")
(verdict open)
- (note "19 March 2027: St Joseph (I class) falls on the Friday of Passion Week. missalemeum shows Joseph entirely displaced, with the Friday's own III-class violet office observed and the Seven Sorrows commemorated instead. Three possibilities, none confirmed: (a) colitur's plain RG 91 reading is right and missalemeum is wrong; (b) a more specific rubric attached to St Joseph's own Proprium Sanctorum entry (the same shape as the Annunciation's own Attamen clause) overrides the general table for this exact collision, and this task did not find its text; (c) the Seven Sorrows commemoration itself outranks an ordinary I-class feast on this one Friday, unsupported by anything found here either. Extensive but non-exhaustive primary-source search did not settle it -- register §6 open item, explicitly unresolved rather than defaulted to either side. Separately, but confirmed regardless: colitur does not implement the Seven-Sorrows-of-Passion-Friday commemoration at all, in any year -- a real, primary-attested gap on its own.")
+ (note "19 March 2027: St Joseph (I class) falls on the Friday of Passion Week. missalemeum shows Joseph entirely displaced, with the Friday's own III-class violet office observed and the Seven Sorrows commemorated instead. Three possibilities, none confirmed: (a) colitur's plain RG 91 reading is right and missalemeum is wrong; (b) a more specific rubric attached to St Joseph's own Proprium Sanctorum entry (the same shape as the Annunciation's own Attamen clause) overrides the general table for this exact collision, and this task did not find its text; (c) the Seven Sorrows commemoration itself outranks an ordinary I-class feast on this one Friday, unsupported by anything found here either. Extensive but non-exhaustive primary-source search did not settle it -- register §6 open item, explicitly unresolved rather than defaulted to either side. Separately, but confirmed regardless: colitur does not implement the Seven-Sorrows-of-Passion-Friday commemoration at all, in any year -- a real, primary-attested gap on its own. CORRECTED 2026-08-12 (Task B, branch ef-rg16a, commemoration-identity comparison): this date now ALSO trips [Comm_identity_unresolved] (colitur's own commemorated candidate there, [ef-passiontide-1-friday], is temporal-origin and carries no English name) -- the SAME root cause as M15 below, folded into this entry's own subset check rather than a separate id, since it is the identical Seven-Sorrows gap this note already names, not a new finding.")
+ (expected_rows 1))
+ ((id M15)
+ (citation "docs/research/rules-register.md §4's own \"THE MAPPING, AND EXACTLY WHAT IT CANNOT RESOLVE\" note (test_oracle.ml's own header) -- not an RG citation, a comparator LIMIT: Rite_ef.Temporal_ef never sets an English [names] field on any candidate it builds (temporal_ef.ml has no \"en ...\" string anywhere in it)")
+ (verdict unresolvable)
+ (note "19 rows where colitur's own admitted commemoration is TEMPORAL-origin (an impeded Advent or Lent feria) -- there is no English name on colitur's side to compare against missalemeum's title text at all, so identity cannot be attempted, only reported as unresolved. Not a rubric dispute and not a data gap either engine is wrong about. Every oracle title on these 19 rows reads as a plain prose description of the SAME temporal ferial slot colitur independently computes for that date (e.g. 2 Dec 2026: oracle \"Feria IV after I Sunday of Advent\" against colitur's own ef-advent-1-wednesday; 4 Dec 2027: oracle \"Sabbato after I Sunday of Advent\" against ef-advent-1-saturday) -- suggestive corroboration, recorded for a human reader, NOT claimed as a verified match: this comparator has no mechanism to verify English prose against an opaque slug. Fixing this at the root (an English name on every temporal-cycle candidate) is a data/lectionary-bootstrap task, not something this comparator can do for itself -- register §6, neighbouring the RG 113 tie-break section, records it as an open item. The 19 dates: 2026-02-24, 2026-03-19, 2026-03-25, 2026-12-02, 2026-12-03, 2026-12-04, 2026-12-07, 2026-12-11, 2026-12-21, 2027-02-24, 2027-12-02, 2027-12-03, 2027-12-04, 2027-12-06, 2027-12-07, 2027-12-11, 2027-12-13, 2027-12-16, 2027-12-21.")
+ (expected_rows 19))
+ ((id M16)
+ (citation "1962 calendarium's March table (same primary text as M13's own citation): \"Feria VI post dominicam I Passionis: Commemoratio septem Dolorum B. Mariae Virg.\" -- a fixed commemoration of Our Lady's Seven Sorrows for the Friday of Passion Week, every year, confirmed real")
+ (verdict missalemeum)
+ (note "27 March 2026 (Friday of Passion Week): colitur admits \"St. John Damascene\" (a real Class3 universal feast that genuinely falls that day, data/ef/sanctoral.sexp's own john-damascene entry, 27 March); missalemeum shows \"For Our Lady of the Seven Sorrows\" instead. The SAME standing gap M13 already names: the Seven-Sorrows-of-Passion-Friday commemoration is confirmed real in the primary text but not implemented anywhere in temporal_ef.ml, so colitur has no candidate for it and falls back to whichever ordinary Class3 saint actually wins that Friday. Verdict missalemeum: colitur is missing a real, primary-cited office, not differently opinioned. Register §6 open item (the same one M13's own note already tracks). Only 2026 shows here as an IDENTITY mismatch -- 2027's Friday of Passion Week IS 19 March, M13's own date, where identity comparison cannot even be reached (M13's own rank/colour mismatch already excludes that day from count-matched identity comparison, folded into M13's own widened subset above). NOTE for whoever builds the office (fix round 1, coordinator finding 7): 27 March 2026 is a III-class day, where RG 111(d) admits TWO commemorations -- yet missalemeum admits only the Seven Sorrows and DISPLACES John Damascene entirely, not merely drops him to second place. A naive implementation (one more ordinary III-class commemoration competing for the day's two slots) would give colitur two commemorations where missalemeum shows one; whatever privilege the Seven Sorrows carries must itself explain the exclusion, not just win admission.")
(expected_rows 1))
diff --git a/lib/kernel/celebration.mli b/lib/kernel/celebration.mli
index a3c2960..85f7af4 100644
--- a/lib/kernel/celebration.mli
+++ b/lib/kernel/celebration.mli
@@ -1,7 +1,14 @@
(** Whether this celebration can be the observed day at all. The 1960 reform
- reduced many feasts to a bare commemoration; they retain a rank (RG 111
- orders admitted commemorations by dignity) but can never be observed. NOT
- a fifth rank: RG 8 fixes the classes at four. *)
+ reduced many feasts to a bare commemoration; they retain a rank but can
+ never be observed. NOT a fifth rank: RG 8 fixes the classes at four.
+
+ What the retained rank is FOR (corrected 2026-08-12): this line formerly
+ read "RG 111 orders admitted commemorations by dignity". Ordering is no
+ longer done by rank at all -- it moved to the rite's own table of
+ precedence (RG 113) in commit ea22ad2, and a bare commemoration has no
+ row in that table. The rank remains load-bearing for ADMISSION: RG 111(b)
+ reserves a II-class Sunday's single slot "de festo II classis", a floor
+ read off this rank directly. *)
type status = Feast | Commemoration_only [@@deriving sexp]
(** A celebration. Parameterised by the rite's rank type only. *)
diff --git a/lib/kernel/precedence.ml b/lib/kernel/precedence.ml
index 05ad69f..2c55817 100644
--- a/lib/kernel/precedence.ml
+++ b/lib/kernel/precedence.ml
@@ -17,8 +17,14 @@ type ('s, 'r) rules = {
disposition : winner:'r candidate -> loser:'r candidate -> disposition;
admit :
observed:'r candidate ->
- ('r candidate * privilege) list ->
+ temporal:'r candidate ->
+ ('r candidate * privilege * int) list ->
('r candidate * privilege) list;
+ (** the trailing [int] on each input triple is that candidate's own
+ [band] value, computed once by {!resolve} below (a rite's [admit]
+ has no [context] of its own to compute it with) -- see [resolve]'s
+ own comment for why this is a KERNEL-level policy, not a rite-
+ specific rule threaded in as data. *)
}
type 'r resolution = {
@@ -55,7 +61,19 @@ let resolve rules ctx ~temporal ~sanctoral =
([], [], []) losers
in
let comms = List.rev comms and deferred = List.rev deferred in
- let admitted = rules.admit ~observed comms in
+ (* RG 113 (EF; docs/research/rules-register.md §4 "Commemorations"): "in
+ admittendis et ordinandis aliis commemorationibus, servetur ordo
+ tabellae praecedentiae" -- admitting AND ordering commemorations both
+ run on the rite's own table of precedence, the same [band] already
+ used above to pick [observed]. Computed here, once, generically (a
+ rite's own [admit] has no [ctx] of its own to call [band] with) rather
+ than inside every rite's [admit] separately -- a kernel-level POLICY
+ ("commemorations are ordered by the rite's own band"), not a
+ rite-specific RULE baked into the kernel: the actual [band] function,
+ and whether a rite's [admit] even uses the value it is handed, both
+ stay entirely rite-supplied. *)
+ let comms_by_precedence = List.map (fun (c, p) -> (c, p, rules.band ctx c)) comms in
+ let admitted = rules.admit ~observed ~temporal comms_by_precedence in
let dropped =
List.filter (fun c -> not (List.exists (fun a -> fst a == fst c) admitted)) comms
in
diff --git a/lib/kernel/precedence.mli b/lib/kernel/precedence.mli
index ae054dd..09376d7 100644
--- a/lib/kernel/precedence.mli
+++ b/lib/kernel/precedence.mli
@@ -34,12 +34,41 @@ type ('s, 'r) rules = {
(** RG 92-95: the loser's fate, which depends on the loser's own rank. *)
admit :
observed:'r candidate ->
- ('r candidate * privilege) list ->
+ temporal:'r candidate ->
+ ('r candidate * privilege * int) list ->
('r candidate * privilege) list;
(** RG 108-111: how many commemorations are admitted, and in what order;
anything filtered out here is recorded in {!resolution.omitted}, not
dropped.
+ Each input triple's trailing [int] is that candidate's own {!band}
+ value, computed once by {!resolve} (RG 113: "in admittendis et
+ ordinandis aliis commemorationibus, servetur ordo tabellae
+ praecedentiae" -- ADMITTING and ORDERING commemorations is governed
+ by the same table-of-precedence order {!band} already supplies for
+ picking the day's own winner; docs/research/rules-register.md §4
+ "Commemorations"). Supplied rather than left for [admit] to compute
+ itself because [admit] has no [context] (date/season/weekday) of
+ its own -- {!resolve} already holds one and calls {!band} with it
+ for every candidate regardless. A rite's [admit] is free to ignore
+ the value entirely (e.g. fall back to [Vocab.rank] alone), the same
+ as it may ignore [temporal] below.
+
+ [temporal] is {!resolve}'s own [~temporal] argument, passed through
+ unchanged -- the day's temporal-cycle candidate, regardless of
+ whether it won. Fix round 1 (RG16(a) task): before this, a rite's
+ [admit] could only infer properties of the CIVIL DAY (chiefly "is
+ this a Sunday", RG 111(b)'s own two-tier admission rule) from
+ [observed]'s own fields -- a proxy that breaks the moment something
+ OTHER than the day's own temporal candidate can be [observed], the
+ exact shape RG 16(a) introduces (a Feast of the Lord standing in
+ the impeded Sunday's place "cum omnibus iuribus et privilegiis",
+ RG 91 entry 14). This is NOT a kernel definition of "Sunday" --
+ the kernel does not gain any rite-specific knowledge by this
+ parameter, it only threads through a value {!resolve} already
+ holds; a rite's own [admit] is free to ignore it entirely, the
+ same as [observed].
+
OBLIGATION ON THE IMPLEMENTATION, not enforced by this type: every
candidate this function returns must be a value taken UNCHANGED
from its input list, never rebuilt (e.g. via a [{ c with ... }]
diff --git a/lib/kernel/validate.ml b/lib/kernel/validate.ml
index cc8bdce..ffeb89e 100644
--- a/lib/kernel/validate.ml
+++ b/lib/kernel/validate.ml
@@ -293,26 +293,96 @@ let run (rite : ('s, 'r) Rite.t) (layer : 'r Layer.t) ~year =
"transfer placement did not reach a fixed point within the round guard (RG 96-98)";
(* "admission": re-offer this day's own admitted commemorations
back to [rite.rules.admit] and require the exact same set back.
- [origin] is reconstructed as [Sanctoral] uniformly:
- {!Liturgical_day.t} does not retain a commemoration's original
- origin, and the real EF [admit] (precedence_ef.ml) reads only
- rank and slug from a candidate, never [origin], so this
- reconstruction is exact for it; documented in validate.mli as
- the one place a rite whose [admit] DOES consult [origin] could
- see a false negative from this check. *)
+ [origin] is RECOVERED, not fabricated -- see the fuller note
+ below on [as_candidates]. It was formerly reconstructed as
+ [Sanctoral] uniformly, justified by the claim that the real EF
+ [admit] reads only rank and slug and never [origin]. That claim
+ is now FALSE: since ea22ad2 the EF [admit] orders by [band]
+ (RG 113), and [band] does read [origin] via [is_temporal], so a
+ temporal-origin commemoration relabelled [Sanctoral] would be
+ scored on the wrong table entry. The recovery below is exact,
+ not a heuristic: [resolve] builds exactly one temporal
+ candidate per day, so a slug match against the day's own
+ temporal office identifies it unambiguously. *)
let observed_candidate : 'r Precedence.candidate =
{ Precedence.cel = d.Liturgical_day.observed; origin = Precedence.Sanctoral }
in
+ (* [~temporal] (fix round 1, RG16(a) task): {!Precedence.rules.admit}
+ now also takes the day's own temporal-cycle candidate, reused
+ here from {!Liturgical_day.t}'s own embedded [Temporal.t] --
+ the exact same value {!Calendar} passed to {!Precedence.resolve}
+ in the first place, so re-offering is against the SAME inputs,
+ not a reconstruction that could itself introduce a false
+ negative. [origin] is [Precedence.Temporal], genuinely (this IS
+ the temporal candidate, not a reconstructed sanctoral one). *)
+ let temporal_candidate : 'r Precedence.candidate =
+ { Precedence.cel = d.Liturgical_day.temporal.Temporal.office;
+ origin = Precedence.Temporal }
+ in
+ (* [band]'s own [context] (RG 113, docs/research/rules-register.md
+ §4 "Commemorations" -- {!Precedence.rules.admit}'s own new
+ [int] parameter, added alongside RG 113's fix: [admit] now
+ orders/selects by the rite's table-of-precedence value
+ {!resolve} attaches to each candidate, not by [Vocab.rank]
+ alone). Reconstructed from {!Liturgical_day.t}'s own embedded
+ [Temporal.t], the same source [temporal_candidate] above
+ already draws its [cel] from, so this is the exact [ctx]
+ {!Calendar} passed to {!Precedence.resolve} for this date in
+ the first place, not a re-derivation that could itself drift. *)
+ let day_ctx : 's Precedence.context =
+ { Precedence.date;
+ season = d.Liturgical_day.temporal.Temporal.season;
+ weekday = d.Liturgical_day.temporal.Temporal.weekday }
+ in
+ (* CORRECTED (Task B fix round 1, coordinator finding 5): [origin]
+ used to be reconstructed as [Sanctoral] UNCONDITIONALLY, which
+ was harmless while nothing here called [band] on the result
+ (the comment this replaces was correct about [PE.admit] itself:
+ it never reads [origin]) -- but this function ALSO now calls
+ [rite.rules.Precedence.band day_ctx cand] on every one of these
+ reconstructed candidates (the line just below), and [band] DOES
+ read [origin] (its own [is_temporal] test) to choose between its
+ temporal- and sanctoral-keyed branches. A genuinely
+ TEMPORAL-origin commemoration (a privileged Advent/Lent/
+ Passiontide feria, an Ember day, an impeded Sunday) mislabelled
+ [Sanctoral] would score the WRONG band entry (e.g. a Lent feria
+ scoring entry 23, "III-class feasts in particular calendars",
+ instead of its real entry 22) -- inert today only because
+ nothing currently asserts on the SCORE [band] returns here, only
+ on whether re-offering [admit] the same values round-trips
+ (which happens not to depend on getting [origin] right for any
+ case this codebase's data reaches -- unverified in general).
+ [Liturgical_day.t] itself still does not retain a
+ commemoration's original origin, so it is recovered the only
+ way available: a commemoration whose SLUG matches the day's own
+ temporal office is temporal-origin; every other commemoration
+ is sanctoral-origin. This is exact whenever slugs cannot
+ collide across the two streams (Task 12's own "observed" check
+ already assumes this for a different purpose), which is the
+ same assumption the rest of this codebase already leans on. *)
+ let temporal_office_slug = d.Liturgical_day.temporal.Temporal.office.Celebration.slug in
let as_candidates comms =
- List.map (fun (c, p) -> ({ Precedence.cel = c; origin = Precedence.Sanctoral }, p)) comms
+ List.map
+ (fun (c, p) ->
+ let origin =
+ if Slug.equal c.Celebration.slug temporal_office_slug then Precedence.Temporal
+ else Precedence.Sanctoral
+ in
+ let cand : 'r Precedence.candidate = { Precedence.cel = c; origin } in
+ (cand, p, rite.Rite.rules.Precedence.band day_ctx cand))
+ comms
in
let offered = as_candidates d.Liturgical_day.commemorations in
- let readmitted = rite.Rite.rules.Precedence.admit ~observed:observed_candidate offered in
+ let readmitted =
+ rite.Rite.rules.Precedence.admit ~observed:observed_candidate
+ ~temporal:temporal_candidate offered
+ in
let norm l =
List.map (fun (c, p) -> (Slug.to_string c.Precedence.cel.Celebration.slug, p)) l
|> List.sort compare
in
- if norm readmitted <> norm offered then
+ let offered_pairs = List.map (fun (c, p, _) -> (c, p)) offered in
+ if norm readmitted <> norm offered_pairs then
fail date "admission"
(Printf.sprintf
"admit is not a fixed point on this day's own commemorations: re-offering %d \
diff --git a/lib/kernel/validate.mli b/lib/kernel/validate.mli
index 5e55fc5..b46ca30 100644
--- a/lib/kernel/validate.mli
+++ b/lib/kernel/validate.mli
@@ -59,14 +59,24 @@ val failure_to_string : failure -> string
fixed point.
- ["admission"]: the rite's own [rules.admit] is a fixed point on what it
already admitted -- re-offering a day's [commemorations] back to
- [admit] (reconstructed with {!Precedence.Sanctoral} origin; the real EF
- admit reads only rank and slug, never origin, so this reconstruction is
- exact for it) must return exactly that same set. A cap-enforcing
- selector that is not idempotent on its own output has, by definition,
- admitted something its own rule would not admit if asked again -- the
- rite-agnostic form of "the admission limit was not exceeded" available
- without embedding a rite's specific numeric caps (RG 111's, for EF)
- into kernel code.
+ [admit] (with [observed]'s own origin reconstructed as
+ {!Precedence.Sanctoral}; the real EF admit reads only rank and slug
+ from [observed], never origin, so this reconstruction is exact for
+ it) must return exactly that same set. Each offered commemoration's
+ own origin -- CORRECTED, Task B fix round 1 -- is recovered by
+ comparing its slug against the day's own temporal office, not
+ reconstructed as [Sanctoral] uniformly: {!Precedence.rules.admit}
+ (since Task B) is handed each candidate's own {!Precedence.rules.band}
+ value, computed here exactly as {!Precedence.resolve} computes it, and
+ [band] DOES read a candidate's origin (temporal- vs sanctoral-keyed
+ branches) even though EF's own [admit] itself still does not -- a
+ mislabelled origin would silently score the wrong table entry for a
+ genuinely temporal-origin commemoration (e.g. a Lent feria) before
+ this fix. A cap-enforcing selector that is not idempotent on its own
+ output has, by definition, admitted something its own rule would not
+ admit if asked again -- the rite-agnostic form of "the admission limit
+ was not exceeded" available without embedding a rite's specific
+ numeric caps (RG 111's, for EF) into kernel code.
Total over the whole 1583..9999 domain, including [year] = 9999: the
liturgical year opening there continues into out-of-domain civil year
diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml
index db7e708..750da8b 100644
--- a/lib/rites/rite_ef/precedence_ef.ml
+++ b/lib/rites/rite_ef/precedence_ef.ml
@@ -110,6 +110,7 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc
int =
let cel = c.Precedence.cel in
let rank = cel.Celebration.rank in
+ let status = cel.Celebration.status in
let subject = cel.Celebration.subject in
let layer = cel.Celebration.layer in
let slug = Slug.to_string cel.Celebration.slug in
@@ -129,8 +130,48 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc
binding, not a second literal, so the two can never drift apart. *)
let entry_15_band = 15 in
let open Vocab_ef in
- (* 1: Nativity, Easter Sunday, Pentecost Sunday (I class w/ octave). *)
- if is_temporal && rank = Class1 && ((m = 12 && d = 25) || off = 0 || off = 49) then 1
+ (* CORRECTED (Task B fix round 1, ef-rg16a): a [Commemoration_only]
+ celebration has NO row in RG 91's table at all, checked FIRST, ahead of
+ every rank-keyed branch below -- RG 91's own text enumerates only "dies
+ liturgici" (entry 24's own wording, e.g., "Festa III classis, in
+ calendario Ecclesiae universae inscripta" -- FEASTS, inscribed in the
+ calendar), and the calendarium itself marks the difference in its own
+ notation: 22 September's row reads "S. Thomae de Villanova Ep. et
+ Conf., III classis. / Commemoratio Ss. Mauritii et Soc. Mm." -- Thomas
+ gets a class number (a "festum"); Maurice gets "Commemoratio" and NO
+ class number at all, because he never had a row in the table for that
+ occasion to begin with. Before this fix, [band] read [rank] alone, so
+ a [Commemoration_only] entry silently borrowed the SAME entry number
+ as a genuine [Feast] of its own rank (a Class3 Commemoration_only
+ entry banded to 24, indistinguishable from a real Class3 universal
+ feast) -- manufacturing a "tie" at {!compare_precedence}/RG 113's own
+ admission ordering that the primary text never creates: RG 113 does
+ not run out of instruction between two same-rank commemorations;
+ [band] ran out of fidelity, handing out a table row that does not
+ exist for one of them. [unclassified] (worse than every real entry) is
+ the same value already used for a candidate this table's 28 branches
+ otherwise fail to describe, which is exactly the right answer here
+ too: "not in this table" for a different reason, same table-position
+ consequence. Confirmed by the oracle: missalemeum's own commemoration
+ id embeds a rank that AGREES with the demoted status this represents
+ (e.g. sancti:09-22o:4:r for Maurice, rank 4, against Thomas's own
+ sancti:09-22:3:w, rank 3, on the day Thomas is observed -- test_oracle
+ .ml's own [test_identity_rank_corroboration]). Restricted to [status];
+ [rank] itself is untouched, and stays load-bearing for a demoted feast:
+ RG 111(b)'s "scilicet de festo II classis" floor ({!admit} below) reads
+ [rank] directly, and it is exactly that floor which excludes these
+ Class3 entries from a II-class Sunday's single slot. Only ORDERING among
+ candidates already offered to {!admit} changes here.
+ NOTE, corrected: this comment previously cited {!Celebration.status}'s
+ own doc comment as saying a demoted feast retains its rank for RG 111's
+ admission-COUNT purposes. That misquotes it -- celebration.mli says RG
+ 111 "orders admitted commemorations by dignity", i.e. it names the
+ ORDERING use this guard removes, not a counting one. celebration.mli's
+ line is itself now stale: ordering moved from dignity to [band] in
+ ea22ad2. The guard is right; its former justification was not. *)
+ if status = Celebration.Commemoration_only then unclassified
+ (* 1: Nativity, Easter Sunday, Pentecost Sunday (I class w/ octave). *)
+ else if is_temporal && rank = Class1 && ((m = 12 && d = 25) || off = 0 || off = 49) then 1
(* 2: Sacred Triduum (Thu-Sat of Holy Week). *)
else if is_temporal && rank = Class1 && off >= -3 && off <= -1 then 2
(* 3: Epiphany, Ascension, Holy Trinity, Corpus Christi, Sacred Heart,
@@ -244,13 +285,14 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc
(* Task 8: what happens to the day's LOSING candidate (docs/research/
rules-register.md §4, "Occurrence" RG 92-95 and "Vigils" RG 33, plus RG
- 94). [band] above decides who wins; this decides the loser's fate, which
- turns on the LOSER's own rank and status (RG 95), except RG 33's vigil
- omission, which also has to read the winner. Nothing here ever returns
- [Precedence.Repose]: that disposition denotes RG 100-102's *repositio*
- (perpetual impediment from a proper/diocesan calendar), out of this
- plan's scope -- see calendar.mli's own note that nothing in the EF
- ruleset currently emits it. *)
+ 94; also §6.0/Caput III "De Dominicis" RG 16(a), below). [band] above
+ decides who wins; this decides the loser's fate, which turns on the
+ LOSER's own rank and status (RG 95), except RG 33's vigil omission and RG
+ 16(a)'s Sunday-suppression, which also have to read the winner. Nothing
+ here ever returns [Precedence.Repose]: that disposition denotes RG
+ 100-102's *repositio* (perpetual impediment from a proper/diocesan
+ calendar), out of this plan's scope -- see calendar.mli's own note that
+ nothing in the EF ruleset currently emits it. *)
(* RG 33 -- CORRECTED 2026-08-12 (Task 16, primary-source-verified against
docs/research/1962-06-23,_SS_Ioannes_XXIII,_Missale_Romanum,_LT.pdf, the
@@ -605,6 +647,91 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate)
register's own §4 "Vigils" entry states RG 32 only as "same pattern
[as RG 31]", not verbatim -- now closed here). *)
Precedence.Omit
+ else if
+ is_temporal
+ && cel.Celebration.rank = Class2
+ && is_sunday_slug (Slug.to_string cel.Celebration.slug)
+ && (let wcel = winner.Precedence.cel in
+ (wcel.Celebration.rank = Class1 || wcel.Celebration.rank = Class2)
+ && wcel.Celebration.subject = Subject.Lord)
+ then
+ (* RG 16(a) (docs/research/rules-register.md §6.0, Caput III "De
+ Dominicis", primary text): "Dominica II classis, in occurrentia,
+ festis II classis praefertur. Attamen: a) festum Domini I aut II
+ classis, in dominica II classis occurrens, locum tenet ipsius
+ dominicae cum omnibus iuribus et privilegiis: de dominica, proinde,
+ NULLA FIT COMMEMORATIO" -- a Feast of the Lord, I or II class,
+ occurring on a II-class Sunday, takes the Sunday's own place with all
+ its rights and privileges: OF THE SUNDAY, THEREFORE, NO
+ COMMEMORATION IS MADE. {!band} entry 14 already ranks such a feast
+ above the Sunday (RG 91 entry 14 < entry 15), so the feast is
+ correctly [observed]; this is [disposition]'s own answer for what
+ becomes of the SUNDAY once it has lost -- [Omit], not the [Commemorate]
+ every other impeded II-class Sunday gets via RG 109(a)/RG 111(b)
+ below. This is the ONE place in this function that needs the WINNER's
+ [subject], not only the loser's own fields -- like RG 33's vigil
+ omission above, not a new kind of signature: [Precedence.rules.disposition]
+ already takes [~winner], this is simply its first other reader.
+
+ Both winner-side conjuncts are load-bearing, proved by
+ [test_precedence_ef.ml]'s own paired rows (the brief's "one without
+ the other proves nothing"):
+ - [rank = Class1 || rank = Class2]: {!band} entries 11-13 admit ANY
+ I-class feast -- Lord or Saint alike, no subject test at all (entry
+ 14's own comment: unlike entry 16, entries 11-13 draw no such
+ line) -- ahead of a II-class Sunday. REACHABLE at Class1 on real
+ data: e.g. the Nativity of St John the Baptist (24 June, I class,
+ Saint) landing on a Time-after-Pentecost Sunday already wins the
+ day under {!band} alone; without this conjunct RG 16(a) would
+ wrongly fire for it too. (At Class2 this conjunct adds no further
+ cases beyond what the [subject = Lord] conjunct below already
+ requires -- entry 16's ordinary II-class feasts never outrank a
+ Sunday in {!band} in the first place, 16 > 15 -- so it is only
+ independently reachable at Class1.)
+ - [subject = Lord]: at Class2 this is what {!band} entry 14 already
+ requires of its own winners, so it adds no further restriction
+ there; at Class1 it is independently reachable and necessary, per
+ the St John Baptist example above -- dropping it would fire RG
+ 16(a) for any winning I-class feast at all, exactly the
+ over-wide branch the task brief warns against.
+
+ The SUNDAY-side conjuncts: [rank = Class2] excludes a I-class Sunday
+ (Advent/Lent/Passiontide, Low Sunday, {!band} entry 6) -- RG 16(a)'s
+ own text says "Dominica II classis", not "any Sunday", and a I-class
+ Sunday can never actually reach here as a [loser] against a
+ Class1-or-2 Lord winner in the first place, for TWO DIFFERENT reasons
+ depending on the winner's shape (CORRECTED, fix round 1: the previous
+ version of this comment claimed "entry 6's own band value (6) is
+ lower than every entry [3, 11-14]" as a single numeric argument --
+ WRONG on its face, 6 is not lower than 3, and the claim would in any
+ case prove the opposite of what it was cited for: if a band-3
+ candidate really did contest a Class1 Sunday, the LOWER number (3)
+ would win, i.e. the Sunday would LOSE, not "always win outright" as
+ claimed):
+ - Against entries 11-14 (SANCTORAL-origin Lord feasts, e.g. the
+ Transfiguration): the numeric argument genuinely holds here --
+ entry 6 (6) IS lower than 11-14, so a I-class Sunday always wins
+ outright against these.
+ - Against entry 3 (TEMPORAL-origin Lord feasts -- Epiphany,
+ Ascension, Trinity, Corpus Christi, Sacred Heart, Christ the King):
+ not a numeric argument at all, but a STRUCTURAL one -- every
+ band-3 celebration is [is_temporal], and {!Precedence.resolve}
+ takes exactly ONE temporal candidate per day ([~temporal], not a
+ list), so a band-3 Lord feast IS that date's own single temporal
+ candidate, never a SEPARATE candidate contesting an
+ independently-produced Sunday on the same date. There is no
+ collision to resolve by band comparison in the first place.
+ Either way, no I-class Sunday can reach here as a loser against a
+ Class1-or-2 Lord winner -- this is exactly why the rubric restricts
+ itself to II class. [is_sunday_slug]
+ (the same marker RG 33's [impedes_vigil] and RG 109(a)'s
+ [privilege_of] already use, with no [is_temporal] guard there either
+ -- no sanctoral slug this codebase's data produces contains
+ {!sunday_marker}) is the "Dominica" half; [is_temporal] is kept
+ alongside it anyway, the same explicit-but-not-load-bearing defence
+ the RG26 branch above gives its own [not is_vigil] guard, rather than
+ relying on that absence silently. *)
+ Precedence.Omit
else
(* RG 95's other branch: "aut commemorantur aut penitus omittuntur" --
commemorated or wholly omitted. Reached by every SANCTORAL loser
@@ -642,42 +769,105 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate)
classis", "dominicis II classis", "aliis diebus II classis", "diebus III
et IV classis") -- read here off [observed]'s own [rank] and, for the
Sunday/non-Sunday II-class split, the same slug marker [privilege_of] and
- RG 33's [impedes_vigil] already use ([is_sunday_slug]). No [context]
- (date/season/weekday) is available to [admit] (see precedence.mli's
- [rules.admit]) or needed: [observed] IS the day's own celebration, so its
- rank and slug already carry everything RG 111's own four categories test. *)
+ RG 33's [impedes_vigil] already use ([is_sunday_slug]).
+
+ CORRECTED (fix round 1, RG16(a) task): the previous version of this
+ comment claimed "[observed] IS the day's own celebration, so its rank and
+ slug already carry everything RG 111's own four categories test" --
+ WRONG once RG 16(a) exists. RG 16(a)'s own text says the winning Feast of
+ the Lord holds the Sunday's place "cum omnibus iuribus et privilegiis"
+ (with ALL its rights and privileges) -- the day remains a "dominica II
+ classis" for RG 111(b)'s own purposes even though [observed] is now the
+ FEAST, not the Sunday, so [observed]'s own slug is no longer a reliable
+ signal of "is this a Sunday" once something can legitimately observe in
+ the Sunday's place. Confirmed wrong for real data by the oracle: 6 August
+ falling on a Sunday shows the Transfiguration observed and NO
+ commemoration (missalemeum: `commemorations: []`, Pope Sixtus II et al.
+ `displaced`); the pre-fix code, reading Sunday-ness off [observed]'s own
+ slug ("transfiguration-of-our-lord", no Sunday marker), wrongly took the
+ [Class2, false] "other II class: one" branch below and admitted Sixtus
+ (Class3) regardless of RG 111(b)'s own "de festo II classis" rank floor.
+ Control, also oracle-confirmed: 6 August on an ordinary WEEKDAY (no
+ Sunday collision) correctly admits Sixtus -- being a Sunday is exactly
+ what excludes him, and [observed]'s own identity cannot tell the two
+ cases apart on its own.
+
+ Fixed by reading Sunday-ness off [temporal] instead -- {!Precedence.rules.admit}'s
+ own [~temporal] parameter, {!Precedence.resolve}'s [~temporal] argument
+ passed straight through, unaffected by whether it won the day. [context]
+ (date/season/weekday) is still not needed: [temporal]'s own slug already
+ carries everything this split needs, the same way [observed]'s used to
+ before a competing office could occupy the Sunday's place. *)
-(* RG 8's four-class dignity order, Class1 highest. Deliberately NOT [band]
- (RG 91's much finer 28-entry table): [band] needs a [context] [admit]
- does not have (see above), and Celebration.mli's own comment on [status]
- -- "RG 111 orders admitted commemorations by dignity" -- names [rank]
- itself as that dignity, not the finer occurrence-table entry. *)
-let dignity = function
- | Vocab_ef.Class1 -> 1
- | Vocab_ef.Class2 -> 2
- | Vocab_ef.Class3 -> 3
- | Vocab_ef.Class4 -> 4
+(* RG 113 -- CORRECTED, Task B (branch ef-rg16a): docs/research/rules-
+ register.md §4's RG 113 entry previously quoted only its FIRST sentence
+ ("commemoratio de Tempore fit primo loco"); its SECOND, load-bearing
+ sentence, primary-source-verified against two independent scans, is the
+ real rule for this function: *"In admittendis et ordinandis aliis
+ commemorationibus, servetur ordo tabellae praecedentiae"* -- in ADMITTING
+ and ORDERING the other commemorations, the order of the table of
+ precedence (RG 91, {!band}'s own 28-entry table) is to be kept.
-(* Deterministic selection order for RG 111: dignity first, then slug --
- the same tie-break {!Precedence.compare_by} uses for [band] itself (the
- brief: "break ties on slug"), so which candidate wins a shared rank never
- depends on the order [comms] arrives in. *)
-let compare_dignity (a, _) (b, _) =
- let da = dignity a.Precedence.cel.Celebration.rank
- and db = dignity b.Precedence.cel.Celebration.rank in
- if da <> db then Int.compare da db
+ This REPLACES a previous [compare_dignity], which sorted by RG 8's coarse
+ four-class [rank] ("dignity") and broke same-rank ties alphabetically by
+ slug -- an engineering convention with no rubrical warrant. Measured,
+ fix round 1 (2005-2050, a temporary pre-fix [git worktree]): a
+ same-[rank] tie existed on 599 days, most never reaching a real
+ decision; reversing the slug tie-break alone changed the ADMITTED SET on
+ 65 of them and the printed ORDER of an already-admitted pair on a
+ further 149 (docs/research/rules-register.md §6.1's full account,
+ correcting this comment's own earlier, unreproduced "66 days" claim).
+
+ CORRECTED, fix round 1 (coordinator finding 1): checking every one of
+ those 65+149 real decisions against data/ef/sanctoral.sexp found the
+ SAME underlying shape in all of them, no exceptions -- one candidate is
+ always [Cel.Commemoration_only] (e.g. "maurice-and-companions-martyrs",
+ 22 September) and the other always a genuine [Cel.Feast] or a temporal
+ office of the SAME [rank] (e.g. "thomas-of-villanova", same day; or a
+ Lent feria, {!band} entry 22, against "paul", 22 February). That is
+ {!band}'s OWN fidelity bug, fixed separately at its source (see [band]'s
+ own top-of-branch guard, RG 91's table has no row for a bare
+ commemoration at all) -- NOT a case RG 113's table-order alone resolves,
+ since a [Commemoration_only] candidate never had a real table entry to
+ compare in the first place. With that fixed, none of these 599 days'
+ real decisions any longer depend on THIS function's own slug fallback:
+ {!band} alone (a real entry vs {!unclassified}) already decides every
+ one. What remains genuinely open -- two DIFFERENT candidates landing on
+ the IDENTICAL real table entry, e.g. two different Class3 universal
+ feasts both at entry 24 -- was checked and found EMPTY across
+ 2005-2050 (register §6.1): RG 113's own table-order, once {!band} is
+ accurate, already decides every real case this codebase's current data
+ produces; the slug fallback below is exercised only between two
+ [Commemoration_only] candidates tied at {!unclassified} (138 of the 599,
+ all order/count-invisible -- RG 91 has no table position for either of
+ them to compare, so there is nothing more specific RG 113 could supply
+ here either). {!band} needs a [context] this function itself does not
+ have (date/season/weekday) -- unlike [dignity], which read [rank] alone
+ -- so {!Precedence.resolve} now computes each candidate's own [band]
+ value once, generically, and hands it to [admit] as the trailing [int]
+ on each input triple (see {!Precedence.rules.admit}'s own doc). [comms]
+ below is [(candidate * privilege * int) list], not the pair it used to
+ be. *)
+let compare_precedence (a, _, ba) (b, _, bb) =
+ if ba <> bb then Int.compare (ba : int) bb
else Slug.compare a.Precedence.cel.Celebration.slug b.Precedence.cel.Celebration.slug
let rec take n = function
| [] -> []
| x :: xs -> if n <= 0 then [] else x :: take (n - 1) xs
+(* [comms]'s own candidate/privilege pair, its [band] value dropped once a
+ selection has been made -- {!Precedence.rules.admit}'s return type is
+ still the pair, not the triple; only the INPUT carries [band]. *)
+let drop_band (c, p, (_ : int)) = (c, p)
+
let admit ~(observed : Vocab_ef.rank Precedence.candidate)
- (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list) :
+ ~(temporal : Vocab_ef.rank Precedence.candidate)
+ (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege * int) list) :
(Vocab_ef.rank Precedence.candidate * Precedence.privilege) list =
- (* Sorted once, by dignity then slug (see [compare_dignity]); every branch
- below either takes a prefix of this list or filters it, so the RESULT
- is always a sub-list of [comms] with its elements untouched -- never
+ (* Sorted once, by {!band} then slug (see [compare_precedence]); every
+ branch below either takes a prefix of this list or filters it, so the
+ RESULT is always built from [comms]'s own elements, untouched -- never
rebuilt -- which matters beyond determinism: {!Precedence.resolve}'s
own [dropped] computation tells an admitted candidate from a dropped
one by physical equality (==) on the candidate value (Task 2's own
@@ -689,21 +879,29 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate)
celebration would surface TWICE in the same day -- once in
[commemorations] (the rebuilt copy) and once in [omitted] (the original,
which nothing admitted matches). One admission, double-reported, and no
- crash to announce it, which is exactly why this comment exists. *)
- let sorted = List.stable_sort compare_dignity comms in
- let is_privileged (_, p) = p = Precedence.Privileged in
+ crash to announce it, which is exactly why this comment exists.
+ [drop_band] only unwraps the pair back out of the triple -- it does not
+ rebuild [c] or [p] themselves, so this obligation still holds. *)
+ let sorted = List.stable_sort compare_precedence comms in
+ let is_privileged (_, p, _) = p = Precedence.Privileged in
let observed_rank = observed.Precedence.cel.Celebration.rank in
- let observed_is_sunday =
- is_sunday_slug (Slug.to_string observed.Precedence.cel.Celebration.slug)
+ (* CORRECTED (fix round 1, RG16(a) task): read off [temporal], not
+ [observed] -- see this function's own doc comment above for the full
+ argument and the oracle evidence. [temporal] is the day's own
+ temporal-cycle candidate regardless of who is [observed]; RG 16(a)
+ makes that distinction live for the first time (a Feast of the Lord
+ can now be [observed] on a day whose [temporal] candidate is a Sunday). *)
+ let day_is_sunday =
+ is_sunday_slug (Slug.to_string temporal.Precedence.cel.Celebration.slug)
in
let open Vocab_ef in
- match (observed_rank, observed_is_sunday) with
+ match (observed_rank, day_is_sunday) with
| Class1, _ ->
(* RG 111: "I class: none save one privileged." Ordinary commemorations
never get a slot at all on a I-class day, no matter how many are
- due; at most one privileged one does, the highest-dignity one if
- several are. *)
- (match List.filter is_privileged sorted with [] -> [] | best :: _ -> [ best ])
+ due; at most one privileged one does, the highest-precedence one
+ (RG 113: {!band}'s own table order) if several are. *)
+ (match List.filter is_privileged sorted with [] -> [] | best :: _ -> [ drop_band best ])
| Class2, true ->
(* RG 111(b), primary text, RE-VERIFIED word for word against the scan
(final fix wave; this sentence is the sole textual basis for the
@@ -717,17 +915,18 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate)
dropped if a privileged commemoration is due." Two clauses, not
one: (i) a privileged
commemoration, whenever due, categorically takes the day's one slot
- -- not by comparing its dignity against the ordinary contender's,
+ -- not by comparing its precedence against the ordinary contender's,
so an ordinary commemoration that would otherwise win on raw
- dignity is still dropped once any privileged one is also due (the
- asymmetric clause the brief and task report flag as deliberate, not
- present at "other II class" below); (ii) failing that, the slot is
- reserved SPECIFICALLY for a [Class2] candidate -- "de festo II
- classis" is a RANK restriction, not merely "whichever ordinary
- candidate has the best dignity": a III- or IV-class ordinary loser
- (a plain commemoration-only saint with no privilege of its own) has
- NO standing for this slot at all and must be entirely omitted, even
- when it is the only candidate present.
+ table order is still dropped once any privileged one is also due
+ (the asymmetric clause the brief and task report flag as
+ deliberate, not present at "other II class" below); (ii) failing
+ that, the slot is reserved SPECIFICALLY for a [Class2] candidate --
+ "de festo II classis" is a RANK restriction, not merely "whichever
+ ordinary candidate has the best table position": a III- or
+ IV-class ordinary loser (a plain commemoration-only saint with no
+ privilege of its own) has NO standing for this slot at all and
+ must be entirely omitted, even when it is the only candidate
+ present.
Fix, Task 16 (primary-source-verified + missalemeum-confirmed):
previously this fell back to "the best of [sorted], whatever its
@@ -739,21 +938,21 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate)
shows him "displaced" (omitted), never commemorated; the
pre-fix code admitted him regardless. *)
(match List.filter is_privileged sorted with
- | best :: _ -> [ best ]
+ | best :: _ -> [ drop_band best ]
| [] -> (
- match List.filter (fun (c, _) -> c.Precedence.cel.Celebration.rank = Class2) sorted with
+ match List.filter (fun (c, _, _) -> c.Precedence.cel.Celebration.rank = Class2) sorted with
| [] -> []
- | best :: _ -> [ best ]))
+ | best :: _ -> [ drop_band best ]))
| Class2, false ->
(* RG 111: "other II class: one" -- no privilege-override clause here,
unlike the Sunday case immediately above, so the day's one slot
- goes to whichever candidate outranks the rest by dignity alone,
- privileged or not. *)
- (match sorted with [] -> [] | best :: _ -> [ best ])
+ goes to whichever candidate outranks the rest by RG 113's own
+ table-of-precedence order ({!band}), privileged or not. *)
+ (match sorted with [] -> [] | best :: _ -> [ drop_band best ])
| (Class3 | Class4), _ ->
- (* RG 111: "III-IV class: at most two" -- by dignity, same as the
- non-Sunday II-class case, just with room for two. *)
- take 2 sorted
+ (* RG 111: "III-IV class: at most two" -- by RG 113's table order, same
+ as the non-Sunday II-class case, just with room for two. *)
+ List.map drop_band (take 2 sorted)
(* Task 11: RG 96 -- where an impeded I-class feast lands (docs/research/
rules-register.md §4, "Transfer/translation"). [band] decides who is
@@ -766,9 +965,11 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate)
RG 96's own text, register-transcribed: "the next following day that is
not I or II class." [is_blocking] reads that off [Vocab_ef.rank] --
- RG 96 speaks of the day's CLASS (RG 8's four-way dignity), not [band]'s
- finer 28-entry occurrence-table row, the same distinction {!admit} above
- already draws for RG 111 ({!dignity}, not [band]). *)
+ RG 96 speaks of the day's CLASS (RG 8's four-way "dignity"), not [band]'s
+ finer 28-entry occurrence-table row -- unlike {!admit} above, which (RG
+ 113, Task B/ef-rg16a) now DOES use [band] itself for its own selection
+ order; RG 96's own text has no such finer-table reading, so [is_blocking]
+ stays on [Vocab_ef.rank] alone. *)
let is_blocking (rank : Vocab_ef.rank) = rank = Vocab_ef.Class1 || rank = Vocab_ef.Class2
(* RG 96's own named exception (docs/research/rules-register.md §4,
diff --git a/lib/rites/rite_ef/precedence_ef.mli b/lib/rites/rite_ef/precedence_ef.mli
index 55f947e..b283a17 100644
--- a/lib/rites/rite_ef/precedence_ef.mli
+++ b/lib/rites/rite_ef/precedence_ef.mli
@@ -68,10 +68,21 @@ val unclassified : int
text states an exception: entry 8 (All Souls) reads "yields to an
occurring Sunday", so on a Sunday this returns a value that
loses to entry 15 rather than the literal integer 8 (see the comment on
- entry 8 in precedence_ef.ml for the exact value and why). Total over
- every candidate {!Precedence.resolve} or {!Calendar} can construct,
- including shapes the 1962 table itself does not describe (see
- {!unclassified}). *)
+ entry 8 in precedence_ef.ml for the exact value and why). ALSO
+ {!unclassified} for any [Cel.Commemoration_only] candidate, checked
+ first, ahead of every rank-keyed branch -- CORRECTED, Task B fix round
+ 1 (coordinator finding 1): RG 91's own table enumerates only "dies
+ liturgici" (entry 24's own text, "Festa III classis..." -- FEASTS), so
+ a celebration reduced to a bare commemoration was never a row in the
+ table to begin with, confirmed by the calendarium's own notation (a
+ genuine feast carries a class number on its occurrence line; a bare
+ "Commemoratio" carries none). Before this fix, a [Commemoration_only]
+ candidate silently borrowed the SAME entry number as a genuine [Feast]
+ of its own [rank] -- manufacturing ties {!Precedence.compare_by} and
+ {!compare_precedence} both then had to break some other way, that RG 91
+ itself never created. Total over every candidate {!Precedence.resolve}
+ or {!Calendar} can construct, including shapes the 1962 table itself
+ does not describe (see {!unclassified}). *)
val band : Vocab_ef.season Precedence.context -> Vocab_ef.rank Precedence.candidate -> int
(** RG 33's marker: every Sunday slug this rite's temporal cycle produces
@@ -164,33 +175,82 @@ val nativity_octave_prefix : string
so the two cannot silently drift apart. *)
val september_ember_prefix : string
-(** [admit ~observed comms]: RG 108-111 (docs/research/rules-register.md §4,
- "Commemorations"). How many of [comms] -- each already tagged with its
- real RG 109 privilege by {!disposition} -- RG 111 admits, and which,
- given the day actually observed:
+(** [admit ~observed ~temporal comms]: RG 108-111 (docs/research/rules-register.md
+ §4, "Commemorations"). How many of [comms] -- each already tagged with
+ its real RG 109 privilege by {!disposition}, and its own {!band} value
+ (RG 91's table-of-precedence entry, computed once by
+ {!Precedence.resolve} -- see {!Precedence.rules.admit}'s own doc) -- RG
+ 111 admits, and which, given the day actually observed:
- [observed] a [Class1] day: none, except at most one privileged
- commemoration (the highest-dignity one, if several are due) -- an
- ordinary one is never admitted here, no matter how many are due;
- - [observed] a [Class2] Sunday (its slug carries {!sunday_marker}): one,
- subject to TWO conditions, not one -- (i) a privileged commemoration,
- whenever due, categorically takes the day's one slot over any
- ordinary one, not by comparing dignity, so an ordinary commemoration
- that would otherwise win on dignity is still dropped; (ii) failing
- that, the slot is reserved for a [Class2] candidate SPECIFICALLY
- ("de festo II classis", RG 111(b)'s own wording -- a RANK FLOOR, not
- "whichever ordinary candidate has the best dignity"): a III- or
- IV-class ordinary loser has no standing for this slot at all and is
- admitted nothing, even when it is the only candidate due;
- - [observed] any other [Class2] day: one, by dignity alone -- no
- privilege override and no rank floor, unlike the Sunday case
- immediately above;
- - [observed] a [Class3] or [Class4] day: at most two, by dignity alone.
+ commemoration (the highest-{!band}-precedence one, if several are
+ due) -- an ordinary one is never admitted here, no matter how many
+ are due;
+ - the CIVIL DAY is a [Class2] Sunday ([temporal]'s slug carries
+ {!sunday_marker} -- CORRECTED, fix round 1, RG16(a) task: read off
+ [temporal], not [observed]; see below): one, subject to TWO
+ conditions, not one -- (i) a privileged commemoration, whenever due,
+ categorically takes the day's one slot over any ordinary one, not by
+ comparing table position, so an ordinary commemoration that would
+ otherwise win on table order is still dropped; (ii) failing that, the
+ slot is reserved for a [Class2] candidate SPECIFICALLY ("de festo II
+ classis", RG 111(b)'s own wording -- a RANK FLOOR, not "whichever
+ ordinary candidate has the best table position"): a III- or IV-class
+ ordinary loser has no standing for this slot at all and is admitted
+ nothing, even when it is the only candidate due;
+ - the civil day is any other [Class2] day: one, by {!band}'s table order
+ alone -- no privilege override and no rank floor, unlike the Sunday
+ case immediately above;
+ - [observed] a [Class3] or [Class4] day: at most two, by {!band}'s table
+ order alone.
- "Dignity" here is [Vocab_ef.rank] (RG 8's four classes), NOT {!band}'s
- finer RG 91 entry number -- {!band} needs a [context] (date/season/
- weekday) this function does not receive (see {!Precedence.rules.admit}).
- Ties break on slug, matching {!Precedence.compare_by}, so the result
- never depends on the order [comms] arrives in.
+ CORRECTED, Task B (branch ef-rg16a): this used to sort by
+ [Vocab_ef.rank] (RG 8's coarse four-class "dignity") and break same-rank
+ ties alphabetically by slug -- an engineering convention with no
+ rubrical warrant, cited nowhere. Measured, fix round 1 (2005-2050,
+ reproducible via a temporary [git worktree] at the pre-fix commit):
+ a same-[rank] tie existed in the candidate pool offered to [admit] on
+ 599 days, most never reaching a real decision (RG 111's own admission
+ count often has room for both, e.g. a III-class day admits two); of
+ those, reversing the slug tie-break ALONE actually changed the ADMITTED
+ SET on 65 days and only the printed ORDER of an already-admitted pair
+ on a further 149 (docs/research/rules-register.md §6.1's own full
+ account, superseding this comment's earlier, unreproduced "66 days"
+ claim). RG 113's own second sentence, previously uncited
+ (docs/research/rules-register.md §4's RG 113 entry), is the real rule:
+ *"in admittendis et ordinandis aliis commemorationibus, servetur ordo
+ tabellae praecedentiae"* -- admitting and ordering commemorations both
+ run on {!band}'s own finer RG 91 table, not RG 8's four classes.
+ {!band} needs a [context] (date/season/weekday) this function does not
+ receive on its own, so {!Precedence.resolve} computes it once,
+ generically, and hands each candidate its own value as the trailing
+ [int] on [comms]'s triples (see {!Precedence.rules.admit}). Ties break
+ on slug ONLY within one identical [band] value -- CORRECTED, fix round
+ 1 (coordinator finding 1): [band] itself used to hand a
+ [Cel.Commemoration_only] candidate the same table entry as a genuine
+ [Cel.Feast] of its own rank (RG 91's table has no row for a bare
+ commemoration at all), manufacturing most of the "identical [band]
+ value" ties this comment used to describe as RG 113's own residual.
+ Fixed in [band] itself; checked afterward (2005-2050 and the full
+ 1583-9999 domain, register §6.1) and found EMPTY of any remaining
+ "two different real table entries tied" case -- the slug fallback below
+ is exercised only between two [Commemoration_only] candidates both at
+ {!unclassified}, still an uncited engineering convention (register §6
+ "RG 113 tie-break"), matching {!Precedence.compare_by}'s own fallback,
+ so the result never depends on the order [comms] arrives in.
+
+ [temporal] -- CORRECTED, fix round 1 (RG16(a) task): this function used
+ to read the Sunday/non-Sunday split off [observed]'s own slug, which
+ silently assumed [observed] IS the day's temporal-cycle office. RG 16(a)
+ breaks that assumption on purpose: a Feast of the Lord holds an impeded
+ II-class Sunday's own place "cum omnibus iuribus et privilegiis"
+ (RG 16(a)'s own text), so the day still counts as a "dominica II
+ classis" for RG 111(b) even though [observed] is now the FEAST.
+ [temporal] -- {!Precedence.rules.admit}'s own parameter, the day's
+ temporal-cycle candidate regardless of who won -- is the reliable
+ signal; oracle-confirmed (6 August: Sunday excludes a Class3 saint
+ Sixtus II from the freed slot, an ordinary weekday admits him). Every
+ row of the previous behaviour where [observed] and [temporal] coincide
+ (no RG 16(a) displacement occurred) is unaffected.
Every candidate this returns is a value taken unchanged from [comms],
never rebuilt: {!Precedence.resolve}'s own [dropped]/[omitted]
@@ -202,7 +262,8 @@ val september_ember_prefix : string
itself total over an empty or arbitrarily long [comms]. *)
val admit :
observed:Vocab_ef.rank Precedence.candidate ->
- (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list ->
+ temporal:Vocab_ef.rank Precedence.candidate ->
+ (Vocab_ef.rank Precedence.candidate * Precedence.privilege * int) list ->
(Vocab_ef.rank Precedence.candidate * Precedence.privilege) list
(** The Annunciation's own bootstrapped slug (data/ef/sanctoral.sexp, Task
diff --git a/test/fixtures/missalemeum-ef-2026-2027.provenance b/test/fixtures/missalemeum-ef-2026-2027.provenance
index 576093d..adae533 100644
--- a/test/fixtures/missalemeum-ef-2026-2027.provenance
+++ b/test/fixtures/missalemeum-ef-2026-2027.provenance
@@ -1,20 +1,30 @@
Fixture: missalemeum-ef-2026-2027.txt
Task: 2026-08-11-colitur-plan3-resolution-engine, Task 16 (oracle harness +
-data audit)
+data audit); field 9 (commemoration_ids) added 2026-08-12, Task B
+(branch ef-rg16a, commemoration-identity comparison).
Source: missalemeum.com (Divinum Officium data), archived by the sibling
project ~/git/projects/lectio at:
commit d7da4b0 "sources: store the snapshot as one compressed archive"
path sources/snapshot.tar.gz, entries missalemeum/en/YYYY-MM-DD.json
(lectio/sources/README.md: "First archived 2026-07-29")
+Re-verified 2026-08-12 (Task B): sources/snapshot.tar.gz is still at commit
+d7da4b0 (git log -1 -- sources/snapshot.tar.gz, working tree clean for that
+path) -- the underlying data has not moved. Re-extracted into a scratch
+copy OUTSIDE ~/git/projects/lectio (that repo was not read via its own
+working commands and was not modified -- another agent was working there
+concurrently), and confirmed the first 8 fields are byte-identical to the
+fixture's own prior content before field 9 was appended.
-SHA-256 of the extracted fixture: 718eff1a03fa09c3927ef18d19fe7921c2d4d7611890c22566058b81fd7cc5ea
-(same digest as [fixture_sha256] in test/test_oracle.ml, ASSERTED by that
-suite's own "fixture SHA-256 matches its provenance note" test -- this line
-documents the pin for a reader who never runs the suite; that test is what
-actually enforces it. Regenerate both together, deliberately, after
-re-running the exact command below -- never by copying a mismatch's actual
-value back in, which would defeat the pin's purpose.)
+SHA-256 of the extracted fixture: 4162e79d7a0bc03b81a34ce6cd3b074e2d32570217759bc3b4058ada75ea8781
+(previously 718eff1a03fa09c3927ef18d19fe7921c2d4d7611890c22566058b81fd7cc5ea,
+before field 9 was appended -- same digest as [fixture_sha256] in
+test/test_oracle.ml, ASSERTED by that suite's own "fixture SHA-256 matches
+its provenance note" test -- this line documents the pin for a reader who
+never runs the suite; that test is what actually enforces it. Regenerate
+both together, deliberately, after re-running the exact command below --
+never by copying a mismatch's actual value back in, which would defeat the
+pin's purpose.)
Exact commands:
cd ~/git/projects/lectio && sh scripts/snapshot-sources.sh unpack
@@ -24,16 +34,17 @@ Exact commands:
Output: one line per civil day, 2026-01-01 through 2027-12-31 inclusive
(730 lines = 365 + 365, both non-leap years), pipe-separated:
- date|rank|colors|title|tempora|commemorations|displaced|n_masses
+ date|rank|colors|title|tempora|commemorations|displaced|n_masses|commemoration_ids
See tools/extract_missalemeum_oracle.py's own header for the exact field
semantics (info.rank/colors/title/tempora/commemorations/displaced,
-verbatim English strings, not translated or slugified) and the two things
-verified during extraction, not merely assumed: no field collides with the
-"|"/";" delimiters, and all 4 multi-Mass days (info is an array on
-2026-11-02, 2026-12-25, 2027-11-02, 2027-12-25) carry an IDENTICAL info
-block (rank/colors/tempora/commemorations/displaced) across every Mass of
-the day, so taking entry[0] throughout (this fixture's own convention)
-loses nothing the comparator or a human auditor needs.
+verbatim English strings, not translated or slugified; commemoration_ids is
+info.commemorations[*].id, ";"-joined, index-aligned with commemorations)
+and the two things verified during extraction, not merely assumed: no
+field collides with the "|"/";" delimiters, and all 4 multi-Mass days (info
+is an array on 2026-11-02, 2026-12-25, 2027-11-02, 2027-12-25) carry an
+IDENTICAL info block (rank/colors/tempora/commemorations/displaced) across
+every Mass of the day, so taking entry[0] throughout (this fixture's own
+convention) loses nothing the comparator or a human auditor needs.
Regenerate with the same commands if the missalemeum snapshot is refreshed
and the fixture needs updating; do not hand-edit this file or the fixture.
diff --git a/test/fixtures/missalemeum-ef-2026-2027.txt b/test/fixtures/missalemeum-ef-2026-2027.txt
index d000212..50057a6 100644
--- a/test/fixtures/missalemeum-ef-2026-2027.txt
+++ b/test/fixtures/missalemeum-ef-2026-2027.txt
@@ -1,730 +1,730 @@
-2026-01-01|1|w|Octave Day of Christmas|-|-|-|1
-2026-01-02|4|w|Feria|-|-|-|1
-2026-01-03|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1
-2026-01-04|2|w|Holy Name of Jesus|-|-|-|1
-2026-01-05|4|w|Feria|-|St. Telesphorus Pope and Martyr|-|1
-2026-01-06|1|w|Epiphany of the Lord|-|-|-|1
-2026-01-07|4|w|Feria|-|-|-|1
-2026-01-08|4|w|Feria|-|-|-|1
-2026-01-09|4|w|Feria|-|-|-|1
-2026-01-10|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1
-2026-01-11|2|w|The Holy Family: Jesus, Mary & Joseph|-|-|St. Hyginus Pope and Martyr|1
-2026-01-12|4|w|Feria|Feria_II_after_Epiphany|-|-|1
-2026-01-13|2|w|Commemoration of the Baptism of the Lord|Feria_III_after_Epiphany|-|-|1
-2026-01-14|3|w|St. Hilary|Feria_IV_after_Epiphany|S. Felicis|-|1
-2026-01-15|3|w|St. Paul, the First Hermit|Feria_V_after_Epiphany|St. Maur, Abbot|-|1
-2026-01-16|3|r|St. Marcellus I|Feria_VI_after_Epiphany|-|-|1
-2026-01-17|3|w|St. Anthony|Saturday_after_Epiphany|-|-|1
-2026-01-18|2|g|II Sunday after Epiphany|-|-|St. Prisca|1
-2026-01-19|4|g|Feria|Feria_II_after_II_Sunday_after_Epiphany|Sts. Marius, Martha, Audifax & Abachum;St. Canute, Martyr|-|1
-2026-01-20|3|r|Sts. Fabian & Sebastian|Feria_III_after_II_Sunday_after_Epiphany|-|-|1
-2026-01-21|3|r|St. Agnes|Feria_IV_after_II_Sunday_after_Epiphany|-|-|1
-2026-01-22|3|r|Sts. Vincent & Anastasius|Feria_V_after_II_Sunday_after_Epiphany|-|-|1
-2026-01-23|3|w|St. Raymond of Peñafort|Feria_VI_after_II_Sunday_after_Epiphany|St. Emerentiana|-|1
-2026-01-24|3|r|St. Timothy|Saturday_after_II_Sunday_after_Epiphany|-|-|1
-2026-01-25|2|g|III Sunday after Epiphany|-|-|Conversion of St. Paul;St. Peter|1
-2026-01-26|3|r|St. Polycarp|Feria_II_after_III_Sunday_after_Epiphany|-|-|1
-2026-01-27|3|w|St. John Chrysostom|Feria_III_after_III_Sunday_after_Epiphany|-|-|1
-2026-01-28|3|w|St. Peter Nolasco|Feria_IV_after_III_Sunday_after_Epiphany|St. Agnes|-|1
-2026-01-29|3|w|St. Francis de Sales|Feria_V_after_III_Sunday_after_Epiphany|-|-|1
-2026-01-30|3|r|St. Martina|Feria_VI_after_III_Sunday_after_Epiphany|-|-|1
-2026-01-31|3|w|St. John Bosco|Saturday_after_III_Sunday_after_Epiphany|-|-|1
-2026-02-01|2|v|Septuagesima Sunday|-|-|St. Ignatius of Antioch|1
-2026-02-02|2|w|Purification of the Blessed Virgin Mary|Feria_II_after_Septuagesima|-|-|1
-2026-02-03|4|v|Feria|Feria_III_after_Septuagesima|St. Blaise|-|1
-2026-02-04|3|w|St. Andrew Corsini|Feria_IV_after_Septuagesima|-|-|1
-2026-02-05|3|r|St. Agatha|Feria_V_after_Septuagesima|-|-|1
-2026-02-06|3|w|St. Titus|Feria_VI_after_Septuagesima|St. Dorothy|-|1
-2026-02-07|3|w|St. Romuald|Saturday_after_Septuagesima|-|-|1
-2026-02-08|2|v|Sexagesima Sunday|-|-|St. John of Matha|1
-2026-02-09|3|w|St. Cyril of Alexandria|Feria_II_after_Sexagesima|St. Appollonia|-|1
-2026-02-10|3|w|St. Scholastica|Feria_III_after_Sexagesimæ|-|-|1
-2026-02-11|3|w|Our Lady of Lourdes|Feria_IV_after_Sexagesimæ|-|-|1
-2026-02-12|3|w|Seven Holy Servite Founders|Feria_V_after_Sexagesimæ|-|-|1
-2026-02-13|4|v|Feria|Feria_VI_after_Sexagesimæ|-|-|1
-2026-02-14|4|w|III Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_Sexagesimæ|St. Valentine|-|1
-2026-02-15|2|v|Quinquagesima Sunday|-|-|Sts. Faustinus & Jovita|1
-2026-02-16|4|v|Feria|Feria_II_after_Quinquagesima|-|-|1
-2026-02-17|4|v|Feria|Feria_III_after_Quinquagesima|-|-|1
-2026-02-18|1|v|Ash Wednesday|-|-|St. Simeon|1
-2026-02-19|3|v|Feria V after Ash Wednesday|-|-|-|1
-2026-02-20|3|v|Feria VI after Ash Wednesday|-|-|-|1
-2026-02-21|3|v|Saturday after Ash Wednesday|-|-|-|1
-2026-02-22|1|v|I Sunday of Lent|-|-|Chair of St. Peter;St. Paul|1
-2026-02-23|3|v|Feria II after the I Sunday of Lent|-|St. Peter Damien|-|1
-2026-02-24|2|r|St. Matthias|Feria_III_after_the_I_Sunday_of_Lent|Feria III after the I Sunday of Lent|-|1
-2026-02-25|2|v|Ember Wednesday of Lent|-|-|-|1
-2026-02-26|3|v|Feria V after the I Sunday of Lent|-|-|-|1
-2026-02-27|2|v|Ember Friday of Lent|-|St. Gabriel of Our Lady of Sorrows|-|1
-2026-02-28|2|v|Ember Saturday of Lent|-|-|-|1
-2026-03-01|1|v|II Sunday of Lent|-|-|-|1
-2026-03-02|3|v|Feria II after the II Sunday of Lent|-|-|-|1
-2026-03-03|3|v|Feria III after the II Sunday of Lent|-|-|-|1
-2026-03-04|3|v|Feria IV after the II Sunday of Lent|-|St. Casimir;St. Lucius|-|1
-2026-03-05|3|v|Feria V after the II Sunday of Lent|-|-|-|1
-2026-03-06|3|v|Feria VI after the II Sunday of Lent|-|Sts. Felicitas & Perpetua|-|1
-2026-03-07|3|v|Saturday after the II Sunday of Lent|-|St. Thomas Aquinas|-|1
-2026-03-08|1|v|III Sunday of Lent|-|-|St. John of God|1
-2026-03-09|3|v|Feria II after the III Sunday of Lent|-|St. Frances Rome|-|1
-2026-03-10|3|v|Feria III after the III Sunday of Lent|-|Forty Holy Martyrs of Sebaste|-|1
-2026-03-11|3|v|Feria IV after the III Sunday of Lent|-|-|-|1
-2026-03-12|3|v|Feria V after the III Sunday of Lent|-|St. Gregory the Great|-|1
-2026-03-13|3|v|Feria VI after the III Sunday of Lent|-|-|-|1
-2026-03-14|3|v|Saturday after the III Sunday of Lent|-|-|-|1
-2026-03-15|1|pv|IV Sunday of Lent|-|-|-|1
-2026-03-16|3|v|Feria II after the IV Sunday of Lent|-|-|-|1
-2026-03-17|3|v|Feria III after the IV Sunday of Lent|-|St. Patrick|-|1
-2026-03-18|3|v|Feria IV after the IV Sunday of Lent|-|St. Cyril of Jerusalem|-|1
-2026-03-19|1|w|St. Joseph, Spouse of the Bl. Virgin Mary|Feria_V_after_the_IV_Sunday_of_Lent|Feria V after the IV Sunday of Lent|-|1
-2026-03-20|3|v|Feria VI after the IV Sunday of Lent|-|-|-|1
-2026-03-21|3|v|Saturday after the IV Sunday of Lent|-|St. Benedict|-|1
-2026-03-22|1|v|Passion Sunday|-|-|-|1
-2026-03-23|3|v|Feria II of Passion Week|-|-|-|1
-2026-03-24|3|v|Feria III of Passion Week|-|St. Gabriel the Archangel|-|1
-2026-03-25|1|w|Annunciation of the Blessed Virgin Mary|Feria_IV_of_Passion_Week|Feria IV of Passion Week|-|1
-2026-03-26|3|v|Feria V of Passion Week|-|-|-|1
-2026-03-27|3|v|Feria VI of Passion Week|-|For Our Lady of the Seven Sorrows|St. John Damascene|1
-2026-03-28|3|v|Saturday of Passion Week|-|St. John of Capistrano|-|1
-2026-03-29|1|rv|Palm Sunday|-|-|-|1
-2026-03-30|1|v|Feria II of Holy Week|-|-|-|1
-2026-03-31|1|v|Feria III of Holy Week|-|-|-|1
-2026-04-01|1|v|Feria IV of Holy Week|-|-|-|1
-2026-04-02|1|w|Holy Thursday|-|-|St. Francis of Paola|1
-2026-04-03|1|bv|Good Friday|-|-|-|1
-2026-04-04|1|vw|Holy Saturday|-|-|St. Isidore of Seville|1
-2026-04-05|1|w|Easter Sunday|-|-|St. Vincent Ferrer|1
-2026-04-06|1|w|Monday in the Octave of Easter|-|-|-|1
-2026-04-07|1|w|Tuesday in the Octave of Easter|-|-|-|1
-2026-04-08|1|w|Wednesday in the Octave of Easter|-|-|-|1
-2026-04-09|1|w|Thursday in the Octave of Easter|-|-|-|1
-2026-04-10|1|w|Friday in the Octave of Easter|-|-|-|1
-2026-04-11|1|w|Saturday in the Octave of Easter|-|-|St. Leo the Great|1
-2026-04-12|1|w|Low Sunday|-|-|-|1
-2026-04-13|3|r|St. Hermenegild|Monday_after_I_Sunday_after_Easter|-|-|1
-2026-04-14|3|r|St. Justin|Tuesday_after_I_Sunday_after_Easter|Sts. Tiburtius, Valerian et Maximus, Martyrs|-|1
-2026-04-15|4|w|Feria|Wednesday_after_I_Sunday_after_Easter|-|-|1
-2026-04-16|4|w|Feria|Thursday_after_I_Sunday_after_Easter|-|-|1
-2026-04-17|4|w|Feria|Friday_after_I_Sunday_after_Easter|St. Anicetus|-|1
-2026-04-18|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_I_Sunday_after_Easter|-|-|1
-2026-04-19|2|w|II Sunday after Easter|-|-|-|1
-2026-04-20|4|w|Feria|Monday_after_II_Sunday_after_Easter|-|-|1
-2026-04-21|3|w|St. Anselm|Tuesday_after_II_Sunday_after_Easter|-|-|1
-2026-04-22|3|r|Sts. Soter & Caius|Wednesday_after_II_Sunday_after_Easter|-|-|1
-2026-04-23|4|w|Feria|Thursday_after_II_Sunday_after_Easter|St. George|-|1
-2026-04-24|3|r|St. Fidelis of Sigmaringen|Friday_after_II_Sunday_after_Easter|-|-|1
-2026-04-25|2|r|St. Mark|Saturday_after_II_Sunday_after_Easter|Pro rogationibus|-|1
-2026-04-26|2|w|III Sunday after Easter|-|-|Sts. Cletus & Marcellinus|1
-2026-04-27|3|w|St. Peter Canisius|Monday_after_III_Sunday_after_Easter|-|-|1
-2026-04-28|3|w|St. Paul of the Cross|Tuesday_after_III_Sunday_after_Easter|-|-|1
-2026-04-29|3|r|St. Peter of Verona|Wednesday_after_III_Sunday_after_Easter|-|-|1
-2026-04-30|3|w|St. Catherine of Siena|Thursday_after_III_Sunday_after_Easter|-|-|1
-2026-05-01|1|w|St. Joseph the Workman|Friday_after_III_Sunday_after_Easter|-|-|1
-2026-05-02|3|w|St. Athanasius|Saturday_after_III_Sunday_after_Easter|-|-|1
-2026-05-03|2|w|IV Sunday after Easter|-|-|Sts. Alexander & Companions|1
-2026-05-04|3|w|St. Monica|Monday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-05|3|w|St. Pius V|Tuesday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-06|4|w|Feria|Wednesday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-07|3|r|St. Stanislaus|Thursday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-08|4|w|Feria|Friday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-09|3|w|St. Gregory of Nazianzen|Saturday_after_IV_Sunday_after_Easter|-|-|1
-2026-05-10|2|w|V Sunday after Easter|-|-|St. Antoninus;St. Gordiano and Epimacho|1
-2026-05-11|2|r|Sts. Philip & James|The_Minor_Litanies_–_Rogations|-|-|1
-2026-05-12|3|r|Sts. Nereus, Achilleus, Domitilla, & Pancras|The_Minor_Litanies_–_Rogations|-|-|1
-2026-05-13|2|w|Vigil of the Ascension|-|St. Robert Bellarmine|-|1
-2026-05-14|1|w|Ascension of the Lord|-|-|St. Boniface|1
-2026-05-15|3|w|St. John Baptist de la Salle|Feria_VI_after_the_Ascension|-|-|1
-2026-05-16|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_the_Ascension|St. Ubaldus|-|1
-2026-05-17|2|w|Sunday after the Ascension|-|-|St. Paschal Baylon|1
-2026-05-18|3|r|St. Venantius|Feria_II_after_the_Ascension|-|-|1
-2026-05-19|3|w|St. Peter Celestine|Feria_III_after_the_Ascension|St. Pudentiana Virginis|-|1
-2026-05-20|3|w|St. Bernardine of Siena|Feria_IV_after_the_Ascension|-|-|1
-2026-05-21|4|w|Feria|Feria_V_after_the_Ascension|-|-|1
-2026-05-22|4|w|Feria|Feria_VI_after_the_Ascension|-|-|1
-2026-05-23|1|r|Saturday after the Ascension|-|-|-|1
-2026-05-24|1|r|Pentecost Sunday|-|-|-|1
-2026-05-25|1|r|Monday after Pentecost|-|-|St. Gregory VII;St. Urban, Pope and Martyr|1
-2026-05-26|1|r|Tuesday after Pentecost|-|-|St. Philip Neri;S. Eleutherius|1
-2026-05-27|1|r|Ember Wednesday of Pentecost|-|-|St. Bede the Venerable;St. John I|1
-2026-05-28|1|r|Thursday after Pentecost|-|-|St. Augustine of Canterbury|1
-2026-05-29|1|r|Ember Friday of Pentecost|-|-|St. Mary Magdalene de Pazzi|1
-2026-05-30|1|r|Ember Saturday of Pentecost|-|-|St. Felix I|1
-2026-05-31|1|w|Trinity Sunday|-|-|Queenship of the Blessed Virgin Mary;St. Petronilla|1
-2026-06-01|3|w|St. Angela Merici|Feria_II_after_I_Sunday_after_Pentecost|-|-|1
-2026-06-02|4|g|Feria|Feria_III_after_I_Sunday_after_Pentecost|Sts. Marcellinus, Peter, & Erasmus|-|1
-2026-06-03|4|g|Feria|Feria_IV_after_I_Sunday_after_Pentecost|-|-|1
-2026-06-04|1|w|Corpus Christi|-|-|St. Francis Caracciolo|1
-2026-06-05|3|r|St. Boniface|Feria_V_after_I_Sunday_after_Pentecost|-|-|1
-2026-06-06|3|w|St. Norbert|Saturday_after_I_Sunday_after_Pentecost|-|-|1
-2026-06-07|2|g|II Sunday after Pentecost|-|-|-|1
-2026-06-08|4|g|Feria|Feria_II_after_II_Sunday_after_Pentecost|-|-|1
-2026-06-09|4|g|Feria|Feria_III_after_II_Sunday_after_Pentecost|Sts. Primus & Felicianus|-|1
-2026-06-10|3|w|St. Margaret of Scotland|Feria_IV_after_II_Sunday_after_Pentecost|-|-|1
-2026-06-11|3|r|St. Barnabas|Feria_V_after_II_Sunday_after_Pentecost|-|-|1
-2026-06-12|1|w|Sacred Heart of Jesus|-|-|St. John of San Fecundo;St. Basilidus|1
-2026-06-13|3|w|St. Anthony of Padua|Saturday_after_II_Sunday_after_Pentecost|-|-|1
-2026-06-14|2|g|III Sunday after Pentecost|-|-|St. Basil the Great|1
-2026-06-15|4|g|Feria|Feria_II_after_III_Sunday_after_Pentecost|St. Vitus|-|1
-2026-06-16|4|g|Feria|Feria_III_after_III_Sunday_after_Pentecost|-|-|1
-2026-06-17|3|w|St. Gregory Barbarigo|Feria_IV_after_III_Sunday_after_Pentecost|-|-|1
-2026-06-18|3|r|St. Ephrem of Syria|Feria_V_after_III_Sunday_after_Pentecost|Ss. Marcus and Marcellianus|-|1
-2026-06-19|3|r|St. Julia of Falconieri|Feria_VI_after_III_Sunday_after_Pentecost|Sts. Gervasius and Protasius|-|1
-2026-06-20|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_III_Sunday_after_Pentecost|St. Silverius|-|1
-2026-06-21|2|g|IV Sunday after Pentecost|-|-|St. Aloysius Gongzaga|1
-2026-06-22|3|w|St. Paulinus of Nola|Feria_II_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-23|2|v|Vigil of the Nativity of St. John the Baptist|Feria_III_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-24|1|w|Nativity of St. John the Baptist|Feria_IV_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-25|3|w|St. William|Feria_V_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-26|3|r|Sts. John & Paul|Feria_VI_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-27|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IV_Sunday_after_Pentecost|-|-|1
-2026-06-28|2|g|V Sunday after Pentecost|-|Vigil of Sts. Peter & Paul|-|1
-2026-06-29|1|r|Sts. Peter & Paul|Feria_II_after_V_Sunday_after_Pentecost|-|-|1
-2026-06-30|3|r|In Commemoratione Sancti Pauli Apostoli|Feria_III_after_V_Sunday_after_Pentecost|-|-|1
-2026-07-01|1|r|The Precious Blood of Our Lord Jesus Christ|Feria_IV_after_V_Sunday_after_Pentecost|-|-|1
-2026-07-02|2|w|Visitation of the Blessed Virgin Mary|Feria_V_after_V_Sunday_after_Pentecost|SS. Processus and Martinian|-|1
-2026-07-03|3|r|St. Irenaeus|Feria_VI_after_V_Sunday_after_Pentecost|-|-|1
-2026-07-04|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_V_Sunday_after_Pentecost|-|-|1
-2026-07-05|2|g|VI Sunday after Pentecost|-|-|St. Anthony Mary Zaccariah|1
-2026-07-06|4|g|Feria|Feria_II_after_VI_Sunday_after_Pentecost|-|-|1
-2026-07-07|3|w|Sts. Cyril & Methodius|Feria_III_after_VI_Sunday_after_Pentecost|-|-|1
-2026-07-08|3|w|St. Elizabeth of Portugal|Feria_IV_after_VI_Sunday_after_Pentecost|-|-|1
-2026-07-09|4|g|Feria|Feria_V_after_VI_Sunday_after_Pentecost|-|-|1
-2026-07-10|3|r|Seven Holy Brothers and Sts. Rufina & Secunda|Feria_VI_after_VI_Sunday_after_Pentecost|-|-|1
-2026-07-11|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_VI_Sunday_after_Pentecost|St. Pius I|-|1
-2026-07-12|2|g|VII Sunday after Pentecost|-|-|St. John Gualbert;Ss. Naboris et Felicis|1
-2026-07-13|4|g|Feria|Feria_II_after_VII_Sunday_after_Pentecost|-|-|1
-2026-07-14|3|w|St. Bonaventure|Feria_III_after_VII_Sunday_after_Pentecost|-|-|1
-2026-07-15|3|w|St. Henry the Emperor|Feria_IV_after_VII_Sunday_after_Pentecost|-|-|1
-2026-07-16|4|g|Feria|Feria_V_after_VII_Sunday_after_Pentecost|Our Lady of Mt. Carmel|-|1
-2026-07-17|4|g|Feria|Feria_VI_after_VII_Sunday_after_Pentecost|St. Alexis|-|1
-2026-07-18|3|r|Camillus de Lellis|Saturday_after_VII_Sunday_after_Pentecost|Ss. Symphorosa and sons|-|1
-2026-07-19|2|g|VIII Sunday after Pentecost|-|-|St. Vincent de Paul|1
-2026-07-20|3|r|St. Jerome Emiliani|Feria_II_after_VIII_Sunday_after_Pentecost|St. Margaret|-|1
-2026-07-21|3|w|St. Laurence of Brindisi|Feria_III_after_VIII_Sunday_after_Pentecost|St. Praxedis Virginis|-|1
-2026-07-22|3|w|St. Mary Magdalene|Feria_IV_after_VIII_Sunday_after_Pentecost|-|-|1
-2026-07-23|3|w|St. Apollinaris|Feria_V_after_VIII_Sunday_after_Pentecost|S. Liborii|-|1
-2026-07-24|4|g|Feria|Feria_VI_after_VIII_Sunday_after_Pentecost|St. Christina|-|1
-2026-07-25|2|r|St. James the Greater|Saturday_after_VIII_Sunday_after_Pentecost|St. Christopher|-|1
-2026-07-26|2|g|IX Sunday after Pentecost|-|St. Anne, Mother of the Blessed Virgin|-|1
-2026-07-27|4|g|Feria|Feria_II_after_IX_Sunday_after_Pentecost|St. Pantaleon|-|1
-2026-07-28|3|r|Sts. Nazarius & Celsus, St. Victor I & St. Innocent I|Feria_III_after_IX_Sunday_after_Pentecost|-|-|1
-2026-07-29|3|r|St. Martha|Feria_IV_after_IX_Sunday_after_Pentecost|Ss. Felicis, Simplicii, Faustini et Beatricis|-|1
-2026-07-30|4|g|Feria|Feria_V_after_IX_Sunday_after_Pentecost|Sts. Abdon & Sennen|-|1
-2026-07-31|3|w|St. Ignatius Loyola|Feria_VI_after_IX_Sunday_after_Pentecost|-|-|1
-2026-08-01|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IX_Sunday_after_Pentecost|Holy Machabees|-|1
-2026-08-02|2|g|X Sunday after Pentecost|-|-|St. Alphonsus Liguori;St. Stephen I, Pope and Martyr|1
-2026-08-03|4|g|Feria|Feria_II_after_X_Sunday_after_Pentecost|-|-|1
-2026-08-04|3|w|St. Dominic|Feria_III_after_X_Sunday_after_Pentecost|-|-|1
-2026-08-05|3|w|Dedication of the Basilica of St. Mary Major|Feria_IV_after_X_Sunday_after_Pentecost|-|-|1
-2026-08-06|2|w|Transfiguration of Our Lord|Feria_V_after_X_Sunday_after_Pentecost|Pope Sixtus II, Felicissimus and Agapitus, Martyrs|-|1
-2026-08-07|3|w|St. Cajetan|Feria_VI_after_X_Sunday_after_Pentecost|St. Donatus|-|1
-2026-08-08|3|w|St. John Mary Vianney|Saturday_after_X_Sunday_after_Pentecost|Ss. Cyriacus, Largus and Smaragdus, Martyrs|-|1
-2026-08-09|3|r|Vigil of St. Lawrence|XI_Sunday_after_Pentecost|St. Romanus|-|1
-2026-08-10|2|r|St. Lawrence|Feria_II_after_XI_Sunday_after_Pentecost|-|-|1
-2026-08-11|4|g|Feria|Feria_III_after_XI_Sunday_after_Pentecost|Sts. Tiburtius & Susanna|-|1
-2026-08-12|3|w|St. Clare|Feria_IV_after_XI_Sunday_after_Pentecost|-|-|1
-2026-08-13|4|g|Feria|Feria_V_after_XI_Sunday_after_Pentecost|Sts. Hippolytus & Cassian|-|1
-2026-08-14|2|w|Vigil of the Assumption|Feria_VI_after_XI_Sunday_after_Pentecost|St. Eusebius|-|1
-2026-08-15|1|w|Assumption of the Blessed Virgin Mary|Saturday_after_XI_Sunday_after_Pentecost|-|-|1
-2026-08-16|2|g|XII Sunday after Pentecost|-|St. Joachim, Father of the Blessed Virgin|-|1
-2026-08-17|3|w|St. Hyacinth|Feria_II_after_XII_Sunday_after_Pentecost|-|-|1
-2026-08-18|4|g|Feria|Feria_III_after_XII_Sunday_after_Pentecost|St. Agapitus|-|1
-2026-08-19|3|w|St. John Eudes|Feria_IV_after_XII_Sunday_after_Pentecost|-|-|1
-2026-08-20|3|w|St. Bernard of Clairvaux|Feria_V_after_XII_Sunday_after_Pentecost|-|-|1
-2026-08-21|3|w|St. Jane Frances de Chantal|Feria_VI_after_XII_Sunday_after_Pentecost|-|-|1
-2026-08-22|2|w|Immaculate Heart of Mary|Saturday_after_XII_Sunday_after_Pentecost|Sts. Timothy, Hippolytus and Symphorianus, Martyrs|-|1
-2026-08-23|2|g|XIII Sunday after Pentecost|-|-|St. Philip Benizi|1
-2026-08-24|2|r|St. Bartholomew|Feria_II_after_XIII_Sunday_after_Pentecost|-|-|1
-2026-08-25|3|w|St. Louis IX|Feria_III_after_XIII_Sunday_after_Pentecost|-|-|1
-2026-08-26|4|g|Feria|Feria_IV_after_XIII_Sunday_after_Pentecost|St. Zephyrinus|-|1
-2026-08-27|3|w|St. Joseph Calasance|Feria_V_after_XIII_Sunday_after_Pentecost|-|-|1
-2026-08-28|3|r|St. Augustine|Feria_VI_after_XIII_Sunday_after_Pentecost|St. Hermes|-|1
-2026-08-29|3|r|Beheading of St. John the Baptist|Saturday_after_XIII_Sunday_after_Pentecost|St. Sabina|-|1
-2026-08-30|2|g|XIV Sunday after Pentecost|-|-|St. Rose of Lima;Sts. Felix and Adauctus|1
-2026-08-31|3|w|St. Raymond Nonnatus|Feria_II_after_XIV_Sunday_after_Pentecost|-|-|1
-2026-09-01|4|g|Feria|Feria_III_after_XIV_Sunday_after_Pentecost|St. Giles;Twelve Holy Brothers, Martyrs|-|1
-2026-09-02|3|w|St. Stephen of Hungary|Feria_IV_after_XIV_Sunday_after_Pentecost|-|-|1
-2026-09-03|3|w|St. Pius X|Feria_V_after_XIV_Sunday_after_Pentecost|-|-|1
-2026-09-04|4|g|Feria|Feria_VI_after_XIV_Sunday_after_Pentecost|-|-|1
-2026-09-05|3|w|St. Lawrence Justinian|Saturday_after_XIV_Sunday_after_Pentecost|-|-|1
-2026-09-06|2|g|XV Sunday after Pentecost|-|-|-|1
-2026-09-07|4|g|Feria|Feria_II_after_XV_Sunday_after_Pentecost|-|-|1
-2026-09-08|2|w|Nativity of the Blessed Virgin Mary|Feria_III_after_XV_Sunday_after_Pentecost|S. Hadriani|-|1
-2026-09-09|4|g|Feria|Feria_IV_after_XV_Sunday_after_Pentecost|St. Gorgonius|-|1
-2026-09-10|3|w|St. Nicholas of Tolentino|Feria_V_after_XV_Sunday_after_Pentecost|-|-|1
-2026-09-11|4|g|Feria|Feria_VI_after_XV_Sunday_after_Pentecost|Sts. Protus & Hyacinth|-|1
-2026-09-12|3|w|Most Holy Name of Mary|Saturday_after_XV_Sunday_after_Pentecost|-|-|1
-2026-09-13|2|g|XVI Sunday after Pentecost|-|-|-|1
-2026-09-14|2|r|Exaltation of the Holy Cross|Feria_II_after_XVI_Sunday_after_Pentecost|-|-|1
-2026-09-15|2|w|Seven Sorrows of the Blessed Virgin Mary|Feria_III_after_XVI_Sunday_after_Pentecost|S. Nicomedes|-|1
-2026-09-16|3|r|Sts. Cornelius & Cyprian|Feria_IV_after_XVI_Sunday_after_Pentecost|Sts. Euphemia, Lucy and Geminianus|-|1
-2026-09-17|4|g|Feria|Feria_V_after_XVI_Sunday_after_Pentecost|Stigmata of St. Francis|-|1
-2026-09-18|3|w|St. Joseph of Cupertino|Feria_VI_after_XVI_Sunday_after_Pentecost|-|-|1
-2026-09-19|3|r|St. Januarius & Companions|Saturday_after_XVI_Sunday_after_Pentecost|-|-|1
-2026-09-20|2|g|XVII Sunday after Pentecost|-|-|Sts. Eustace & Companions|1
-2026-09-21|2|r|St. Matthew|Feria_II_after_XVII_Sunday_after_Pentecost|-|-|1
-2026-09-22|3|w|St. Thomas of Villanova|Feria_III_after_XVII_Sunday_after_Pentecost|St. Maurice and Companions, Martyrs|-|1
-2026-09-23|2|v|Ember Wednesday of September|-|St. Linus|St. Thecla|1
-2026-09-24|4|g|Feria|Feria_V_after_XVII_Sunday_after_Pentecost|Our Lady of Ransom|-|1
-2026-09-25|2|v|Ember Friday of September|-|-|-|1
-2026-09-26|2|v|Ember Saturday of September|-|Sts. Cyprian & Justina|-|1
-2026-09-27|2|g|XVIII Sunday after Pentecost|-|-|Sts. Cosmas & Damian|1
-2026-09-28|3|r|St. Wenceslaus|Feria_II_after_XVIII_Sunday_after_Pentecost|-|-|1
-2026-09-29|1|w|Dedication of St. Michael the Archangel|Feria_III_after_XVIII_Sunday_after_Pentecost|-|-|1
-2026-09-30|3|w|St. Jerome|Feria_IV_after_XVIII_Sunday_after_Pentecost|-|-|1
-2026-10-01|4|g|Feria|Feria_V_after_XVIII_Sunday_after_Pentecost|St. Remigius|-|1
-2026-10-02|3|w|Holy Guardian Angels|Feria_VI_after_XVIII_Sunday_after_Pentecost|-|-|1
-2026-10-03|3|w|St. Theresa of the Infant Jesus|Saturday_after_XVIII_Sunday_after_Pentecost|-|-|1
-2026-10-04|2|g|XIX Sunday after Pentecost|-|-|St. Francis of Assisi|1
-2026-10-05|4|g|Feria|Feria_II_after_XIX_Sunday_after_Pentecost|St. Placid & Companions|-|1
-2026-10-06|3|w|St. Bruno|Feria_III_after_XIX_Sunday_after_Pentecost|-|-|1
-2026-10-07|2|w|Our Lady of the Rosary|Feria_IV_after_XIX_Sunday_after_Pentecost|St. Mark I|-|1
-2026-10-08|3|w|St. Bridget of Sweden|Feria_V_after_XIX_Sunday_after_Pentecost|Ss. Sergio, Baccho, Marcello and Apulejo Martyrs|-|1
-2026-10-09|3|w|St. John Leonardi|Feria_VI_after_XIX_Sunday_after_Pentecost|St. Dionysius and companions|-|1
-2026-10-10|3|w|St. Francis Borgia|Saturday_after_XIX_Sunday_after_Pentecost|-|-|1
-2026-10-11|2|g|XX Sunday after Pentecost|-|Maternity of the Blessed Virgin Mary|-|1
-2026-10-12|4|g|Feria|Feria_II_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-13|3|w|St. Edward|Feria_III_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-14|3|r|St. Callistus I|Feria_IV_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-15|3|w|St. Teresa of Avila|Feria_V_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-16|3|w|St. Hedwig|Feria_VI_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-17|3|w|St. Margaret Mary Alacoque|Saturday_after_XX_Sunday_after_Pentecost|-|-|1
-2026-10-18|2|g|XXI Sunday after Pentecost|-|St. Luke the Evangelist|-|1
-2026-10-19|3|w|St. Peter of Alcantara|Feria_II_after_XXI_Sunday_after_Pentecost|-|-|1
-2026-10-20|3|w|St. John Cantius|Feria_III_after_XXI_Sunday_after_Pentecost|-|-|1
-2026-10-21|4|g|Feria|Feria_IV_after_XXI_Sunday_after_Pentecost|St. Hilarion;St. Ursula and Companions|-|1
-2026-10-22|4|g|Feria|Feria_V_after_XXI_Sunday_after_Pentecost|-|-|1
-2026-10-23|3|w|St. Anthony Mary Claret|Feria_VI_after_XXI_Sunday_after_Pentecost|-|-|1
-2026-10-24|3|w|St. Raphael the Archangel|Saturday_after_XXI_Sunday_after_Pentecost|-|-|1
-2026-10-25|1|w|Christ the King|XXII_Sunday_after_Pentecost|-|Sts. Chrysanthus & Daria|1
-2026-10-26|4|g|Feria|Feria_II_after_XXII_Sunday_after_Pentecost|St. Evaristus|-|1
-2026-10-27|4|g|Feria|Feria_III_after_XXII_Sunday_after_Pentecost|-|-|1
-2026-10-28|2|r|Sts. Simon & Jude|Feria_IV_after_XXII_Sunday_after_Pentecost|-|-|1
-2026-10-29|4|g|Feria|Feria_V_after_XXII_Sunday_after_Pentecost|-|-|1
-2026-10-30|4|g|Feria|Feria_VI_after_XXII_Sunday_after_Pentecost|-|-|1
-2026-10-31|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXII_Sunday_after_Pentecost|-|-|1
-2026-11-01|1|w|All Saints|XXIII_Sunday_after_Pentecost|-|-|1
-2026-11-02|1|b|Commemoration of All Souls|Feria_II_after_XXIII_Sunday_after_Pentecost|-|-|3
-2026-11-03|4|g|Feria|Feria_III_after_XXIII_Sunday_after_Pentecost|-|-|1
-2026-11-04|3|w|St. Charles Borromeo|Feria_IV_after_XXIII_Sunday_after_Pentecost|Sts. Vitalis and Agricola, Martyrs|-|1
-2026-11-05|4|g|Feria|Feria_V_after_XXIII_Sunday_after_Pentecost|-|-|1
-2026-11-06|4|g|Feria|Feria_VI_after_XXIII_Sunday_after_Pentecost|-|-|1
-2026-11-07|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIII_Sunday_after_Pentecost|-|-|1
-2026-11-08|2|g|V Sunday after Epiphany|-|-|Four Holy Crowned Martyrs|1
-2026-11-09|2|w|Dedication of the Archbasilica of Our Holy Savior|Feria_II_after_V_Sunday_after_Epiphany|St. Theodore|-|1
-2026-11-10|3|w|St. Andrew Avellino|Feria_III_after_V_Sunday_after_Epiphany|Sts. Tryphonis, Respicii, et Nymphae|-|1
-2026-11-11|3|w|St. Martin of Tours|Feria_IV_after_V_Sunday_after_Epiphany|St. Menna|-|1
-2026-11-12|3|r|St. Martin I|Feria_V_after_V_Sunday_after_Epiphany|-|-|1
-2026-11-13|4|g|Feria|Feria_VI_after_V_Sunday_after_Epiphany|St. Didacus|-|1
-2026-11-14|3|w|St. Josaphat|Saturday_after_V_Sunday_after_Epiphany|-|-|1
-2026-11-15|2|g|VI Sunday after Epiphany|-|-|St. Albert the Great|1
-2026-11-16|3|w|St. Gertrude the Great|Feria_II_after_VI_Sunday_after_Epiphany|-|-|1
-2026-11-17|3|w|St. Gregory the Wonderworker|Feria_III_after_VI_Sunday_after_Epiphany|-|-|1
-2026-11-18|3|w|Dedication of the Basilicas of Sts. Peter & Paul|Feria_IV_after_VI_Sunday_after_Epiphany|-|-|1
-2026-11-19|3|w|St. Elizabeth of Hungary|Feria_V_after_VI_Sunday_after_Epiphany|St. Pontian|-|1
-2026-11-20|3|w|St. Felix of Valois|Feria_VI_after_VI_Sunday_after_Epiphany|-|-|1
-2026-11-21|3|w|Presentation of the Blessed Virgin Mary|Saturday_after_VI_Sunday_after_Epiphany|-|-|1
-2026-11-22|2|g|XXIV Sunday after Pentecost|-|-|St. Cecilia|1
-2026-11-23|3|r|St. Clement I|Feria_II_after_XXIV_Sunday_after_Pentecost|St. Felicity|-|1
-2026-11-24|3|w|St. John of the Cross|Feria_III_after_XXIV_Sunday_after_Pentecost|St. Chrysogonus|-|1
-2026-11-25|3|r|St. Catherine of Alexandria|Feria_IV_after_XXIV_Sunday_after_Pentecost|-|-|1
-2026-11-26|3|w|St. Sylvester|Feria_V_after_XXIV_Sunday_after_Pentecost|St. Peter of Alexandria|-|1
-2026-11-27|4|g|Feria|Feria_VI_after_XXIV_Sunday_after_Pentecost|-|-|1
-2026-11-28|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIV_Sunday_after_Pentecost|-|-|1
-2026-11-29|1|v|I Sunday of Advent|-|-|St. Saturninus|1
-2026-11-30|2|r|St. Andrew|Feria_II_after_I_Sunday_of_Advent|-|-|1
-2026-12-01|3|v|Feria III after I Sunday of Advent|-|-|-|1
-2026-12-02|3|r|St. Vivian|Feria_IV_after_I_Sunday_of_Advent|Feria IV after I Sunday of Advent|-|1
-2026-12-03|3|w|St. Francis Xavier|Feria_V_after_I_Sunday_of_Advent|Feria V after I Sunday of Advent|-|1
-2026-12-04|3|w|St. Peter Chrysologus|Feria_VI_after_I_Sunday_of_Advent|Feria VI after I Sunday of Advent|-|1
-2026-12-05|3|v|Sabbato after I Sunday of Advent|-|St. Sabbas|-|1
-2026-12-06|1|v|II Sunday of Advent|-|-|St. Nicholas|1
-2026-12-07|3|w|St. Ambrose|Feria_II_after_II_Sunday_of_Advent|Feria II after II Sunday of Advent|-|1
-2026-12-08|1|w|Immaculate Conception of the Blessed Virgin Mary|Feria_III_after_II_Sunday_of_Advent|-|-|1
-2026-12-09|3|v|Feria IV after II Sunday of Advent|-|-|-|1
-2026-12-10|3|v|Feria V after II Sunday of Advent|-|St. Melchiades|-|1
-2026-12-11|3|w|St. Damasus I|Feria_VI_after_II_Sunday_of_Advent|Feria VI after II Sunday of Advent|-|1
-2026-12-12|3|v|Sabbato after II Sunday of Advent|-|-|-|1
-2026-12-13|1|pv|III Sunday of Advent|-|-|St. Lucy|1
-2026-12-14|3|pv|Feria II after III Sunday of Advent|-|-|-|1
-2026-12-15|3|pv|Feria III after III Sunday of Advent|-|-|-|1
-2026-12-16|2|v|Ember Wednesday of Advent|-|St. Eusebius|-|1
-2026-12-17|2|pv|Feria V after III Sunday of Advent|-|-|-|1
-2026-12-18|2|v|Ember Friday of Advent|-|-|-|1
-2026-12-19|2|v|Ember Saturday of Advent|-|-|-|1
-2026-12-20|1|v|IV Sunday of Advent|-|-|-|1
-2026-12-21|2|r|St. Thomas|Feria_II_after_IV_Sunday_of_Advent|Feria II after IV Sunday of Advent|-|1
-2026-12-22|2|v|Feria III after IV Sunday of Advent|-|-|-|1
-2026-12-23|2|v|Feria IV after IV Sunday of Advent|-|-|-|1
-2026-12-24|1|v|Vigil of Christmas|-|-|-|1
-2026-12-25|1|w|The Nativity of Our Lord|-|-|-|3
-2026-12-26|2|r|St. Stephen|-|For Octave of the Nativity|-|1
-2026-12-27|2|w|Sunday in the Octave of Christmas|-|St. John the Evangelist|For Octave of the Nativity|1
-2026-12-28|2|r|Holy Innocents|-|For Octave of the Nativity|-|1
-2026-12-29|2|w|Feria in the Octave of Christmas|-|St. Thomas Becket|-|1
-2026-12-30|2|w|Feria in the Octave of Christmas|-|-|-|1
-2026-12-31|2|w|Feria in the Octave of Christmas|-|St. Silvester|-|1
-2027-01-01|1|w|Octave Day of Christmas|-|-|-|1
-2027-01-02|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1
-2027-01-03|2|w|Holy Name of Jesus|-|-|-|1
-2027-01-04|4|w|Feria|-|-|-|1
-2027-01-05|4|w|Feria|-|St. Telesphorus Pope and Martyr|-|1
-2027-01-06|1|w|Epiphany of the Lord|-|-|-|1
-2027-01-07|4|w|Feria|-|-|-|1
-2027-01-08|4|w|Feria|-|-|-|1
-2027-01-09|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1
-2027-01-10|2|w|The Holy Family: Jesus, Mary & Joseph|-|-|-|1
-2027-01-11|4|w|Feria|Feria_II_after_Epiphany|St. Hyginus Pope and Martyr|-|1
-2027-01-12|4|w|Feria|Feria_III_after_Epiphany|-|-|1
-2027-01-13|2|w|Commemoration of the Baptism of the Lord|Feria_IV_after_Epiphany|-|-|1
-2027-01-14|3|w|St. Hilary|Feria_V_after_Epiphany|S. Felicis|-|1
-2027-01-15|3|w|St. Paul, the First Hermit|Feria_VI_after_Epiphany|St. Maur, Abbot|-|1
-2027-01-16|3|r|St. Marcellus I|Saturday_after_Epiphany|-|-|1
-2027-01-17|2|g|II Sunday after Epiphany|-|-|St. Anthony|1
-2027-01-18|4|g|Feria|Feria_II_after_II_Sunday_after_Epiphany|St. Prisca|-|1
-2027-01-19|4|g|Feria|Feria_III_after_II_Sunday_after_Epiphany|Sts. Marius, Martha, Audifax & Abachum;St. Canute, Martyr|-|1
-2027-01-20|3|r|Sts. Fabian & Sebastian|Feria_IV_after_II_Sunday_after_Epiphany|-|-|1
-2027-01-21|3|r|St. Agnes|Feria_V_after_II_Sunday_after_Epiphany|-|-|1
-2027-01-22|3|r|Sts. Vincent & Anastasius|Feria_VI_after_II_Sunday_after_Epiphany|-|-|1
-2027-01-23|3|w|St. Raymond of Peñafort|Saturday_after_II_Sunday_after_Epiphany|St. Emerentiana|-|1
-2027-01-24|2|v|Septuagesima Sunday|-|-|St. Timothy|1
-2027-01-25|3|w|Conversion of St. Paul|Feria_II_after_Septuagesima|St. Peter|-|1
-2027-01-26|3|r|St. Polycarp|Feria_III_after_Septuagesima|-|-|1
-2027-01-27|3|w|St. John Chrysostom|Feria_IV_after_Septuagesima|-|-|1
-2027-01-28|3|w|St. Peter Nolasco|Feria_V_after_Septuagesima|St. Agnes|-|1
-2027-01-29|3|w|St. Francis de Sales|Feria_VI_after_Septuagesima|-|-|1
-2027-01-30|3|r|St. Martina|Saturday_after_Septuagesima|-|-|1
-2027-01-31|2|v|Sexagesima Sunday|-|-|St. John Bosco|1
-2027-02-01|3|r|St. Ignatius of Antioch|Feria_II_after_Sexagesima|-|-|1
-2027-02-02|2|w|Purification of the Blessed Virgin Mary|Feria_III_after_Sexagesimæ|-|-|1
-2027-02-03|4|v|Feria|Feria_IV_after_Sexagesimæ|St. Blaise|-|1
-2027-02-04|3|w|St. Andrew Corsini|Feria_V_after_Sexagesimæ|-|-|1
-2027-02-05|3|r|St. Agatha|Feria_VI_after_Sexagesimæ|-|-|1
-2027-02-06|3|w|St. Titus|Saturday_after_Sexagesimæ|St. Dorothy|-|1
-2027-02-07|2|v|Quinquagesima Sunday|-|-|St. Romuald|1
-2027-02-08|3|w|St. John of Matha|Feria_II_after_Quinquagesima|-|-|1
-2027-02-09|3|w|St. Cyril of Alexandria|Feria_III_after_Quinquagesima|St. Appollonia|-|1
-2027-02-10|1|v|Ash Wednesday|-|-|St. Scholastica|1
-2027-02-11|3|v|Feria V after Ash Wednesday|-|Our Lady of Lourdes|-|1
-2027-02-12|3|v|Feria VI after Ash Wednesday|-|Seven Holy Servite Founders|-|1
-2027-02-13|3|v|Saturday after Ash Wednesday|-|-|-|1
-2027-02-14|1|v|I Sunday of Lent|-|-|St. Valentine|1
-2027-02-15|3|v|Feria II after the I Sunday of Lent|-|Sts. Faustinus & Jovita|-|1
-2027-02-16|3|v|Feria III after the I Sunday of Lent|-|-|-|1
-2027-02-17|2|v|Ember Wednesday of Lent|-|-|-|1
-2027-02-18|3|v|Feria V after the I Sunday of Lent|-|St. Simeon|-|1
-2027-02-19|2|v|Ember Friday of Lent|-|-|-|1
-2027-02-20|2|v|Ember Saturday of Lent|-|-|-|1
-2027-02-21|1|v|II Sunday of Lent|-|-|-|1
-2027-02-22|2|w|Chair of St. Peter|Feria_II_after_the_II_Sunday_of_Lent|St. Paul;Feria II after the II Sunday of Lent|-|1
-2027-02-23|3|v|Feria III after the II Sunday of Lent|-|St. Peter Damien|-|1
-2027-02-24|2|r|St. Matthias|Feria_IV_after_the_II_Sunday_of_Lent|Feria IV after the II Sunday of Lent|-|1
-2027-02-25|3|v|Feria V after the II Sunday of Lent|-|-|-|1
-2027-02-26|3|v|Feria VI after the II Sunday of Lent|-|-|-|1
-2027-02-27|3|v|Saturday after the II Sunday of Lent|-|St. Gabriel of Our Lady of Sorrows|-|1
-2027-02-28|1|v|III Sunday of Lent|-|-|-|1
-2027-03-01|3|v|Feria II after the III Sunday of Lent|-|-|-|1
-2027-03-02|3|v|Feria III after the III Sunday of Lent|-|-|-|1
-2027-03-03|3|v|Feria IV after the III Sunday of Lent|-|-|-|1
-2027-03-04|3|v|Feria V after the III Sunday of Lent|-|St. Casimir;St. Lucius|-|1
-2027-03-05|3|v|Feria VI after the III Sunday of Lent|-|-|-|1
-2027-03-06|3|v|Saturday after the III Sunday of Lent|-|Sts. Felicitas & Perpetua|-|1
-2027-03-07|1|pv|IV Sunday of Lent|-|-|St. Thomas Aquinas|1
-2027-03-08|3|v|Feria II after the IV Sunday of Lent|-|St. John of God|-|1
-2027-03-09|3|v|Feria III after the IV Sunday of Lent|-|St. Frances Rome|-|1
-2027-03-10|3|v|Feria IV after the IV Sunday of Lent|-|Forty Holy Martyrs of Sebaste|-|1
-2027-03-11|3|v|Feria V after the IV Sunday of Lent|-|-|-|1
-2027-03-12|3|v|Feria VI after the IV Sunday of Lent|-|St. Gregory the Great|-|1
-2027-03-13|3|v|Saturday after the IV Sunday of Lent|-|-|-|1
-2027-03-14|1|v|Passion Sunday|-|-|-|1
-2027-03-15|3|v|Feria II of Passion Week|-|-|-|1
-2027-03-16|3|v|Feria III of Passion Week|-|-|-|1
-2027-03-17|3|v|Feria IV of Passion Week|-|St. Patrick|-|1
-2027-03-18|3|v|Feria V of Passion Week|-|St. Cyril of Jerusalem|-|1
-2027-03-19|3|v|Feria VI of Passion Week|-|For Our Lady of the Seven Sorrows|St. Joseph, Spouse of the Bl. Virgin Mary|1
-2027-03-20|3|v|Saturday of Passion Week|-|-|-|1
-2027-03-21|1|rv|Palm Sunday|-|-|St. Benedict|1
-2027-03-22|1|v|Feria II of Holy Week|-|-|-|1
-2027-03-23|1|v|Feria III of Holy Week|-|-|-|1
-2027-03-24|1|v|Feria IV of Holy Week|-|-|St. Gabriel the Archangel|1
-2027-03-25|1|w|Holy Thursday|-|-|Annunciation of the Blessed Virgin Mary|1
-2027-03-26|1|bv|Good Friday|-|-|-|1
-2027-03-27|1|vw|Holy Saturday|-|-|St. John Damascene|1
-2027-03-28|1|w|Easter Sunday|-|-|St. John of Capistrano|1
-2027-03-29|1|w|Monday in the Octave of Easter|-|-|-|1
-2027-03-30|1|w|Tuesday in the Octave of Easter|-|-|-|1
-2027-03-31|1|w|Wednesday in the Octave of Easter|-|-|-|1
-2027-04-01|1|w|Thursday in the Octave of Easter|-|-|-|1
-2027-04-02|1|w|Friday in the Octave of Easter|-|-|St. Francis of Paola|1
-2027-04-03|1|w|Saturday in the Octave of Easter|-|-|-|1
-2027-04-04|1|w|Low Sunday|-|-|St. Isidore of Seville|1
-2027-04-05|1|w|Annunciation of the Blessed Virgin Mary|Monday_after_I_Sunday_after_Easter|-|St. Vincent Ferrer|1
-2027-04-06|4|w|Feria|Tuesday_after_I_Sunday_after_Easter|-|-|1
-2027-04-07|4|w|Feria|Wednesday_after_I_Sunday_after_Easter|-|-|1
-2027-04-08|4|w|Feria|Thursday_after_I_Sunday_after_Easter|-|-|1
-2027-04-09|4|w|Feria|Friday_after_I_Sunday_after_Easter|-|-|1
-2027-04-10|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_I_Sunday_after_Easter|-|-|1
-2027-04-11|2|w|II Sunday after Easter|-|-|St. Leo the Great|1
-2027-04-12|4|w|Feria|Monday_after_II_Sunday_after_Easter|-|-|1
-2027-04-13|3|r|St. Hermenegild|Tuesday_after_II_Sunday_after_Easter|-|-|1
-2027-04-14|3|r|St. Justin|Wednesday_after_II_Sunday_after_Easter|Sts. Tiburtius, Valerian et Maximus, Martyrs|-|1
-2027-04-15|4|w|Feria|Thursday_after_II_Sunday_after_Easter|-|-|1
-2027-04-16|4|w|Feria|Friday_after_II_Sunday_after_Easter|-|-|1
-2027-04-17|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_II_Sunday_after_Easter|St. Anicetus|-|1
-2027-04-18|2|w|III Sunday after Easter|-|-|-|1
-2027-04-19|4|w|Feria|Monday_after_III_Sunday_after_Easter|-|-|1
-2027-04-20|4|w|Feria|Tuesday_after_III_Sunday_after_Easter|-|-|1
-2027-04-21|3|w|St. Anselm|Wednesday_after_III_Sunday_after_Easter|-|-|1
-2027-04-22|3|r|Sts. Soter & Caius|Thursday_after_III_Sunday_after_Easter|-|-|1
-2027-04-23|4|w|Feria|Friday_after_III_Sunday_after_Easter|St. George|-|1
-2027-04-24|3|r|St. Fidelis of Sigmaringen|Saturday_after_III_Sunday_after_Easter|-|-|1
-2027-04-25|2|w|IV Sunday after Easter|-|St. Mark|Pro rogationibus|1
-2027-04-26|3|r|Sts. Cletus & Marcellinus|Monday_after_IV_Sunday_after_Easter|-|-|1
-2027-04-27|3|w|St. Peter Canisius|Tuesday_after_IV_Sunday_after_Easter|-|-|1
-2027-04-28|3|w|St. Paul of the Cross|Wednesday_after_IV_Sunday_after_Easter|-|-|1
-2027-04-29|3|r|St. Peter of Verona|Thursday_after_IV_Sunday_after_Easter|-|-|1
-2027-04-30|3|w|St. Catherine of Siena|Friday_after_IV_Sunday_after_Easter|-|-|1
-2027-05-01|1|w|St. Joseph the Workman|Saturday_after_IV_Sunday_after_Easter|-|-|1
-2027-05-02|2|w|V Sunday after Easter|-|-|St. Athanasius|1
-2027-05-03|4|w|Feria|The_Minor_Litanies_–_Rogations|Sts. Alexander & Companions|-|1
-2027-05-04|3|w|St. Monica|The_Minor_Litanies_–_Rogations|-|-|1
-2027-05-05|2|w|Vigil of the Ascension|-|St. Pius V|-|1
-2027-05-06|1|w|Ascension of the Lord|-|-|-|1
-2027-05-07|3|r|St. Stanislaus|Feria_VI_after_the_Ascension|-|-|1
-2027-05-08|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_the_Ascension|-|-|1
-2027-05-09|2|w|Sunday after the Ascension|-|-|St. Gregory of Nazianzen|1
-2027-05-10|3|w|St. Antoninus|Feria_II_after_the_Ascension|St. Gordiano and Epimacho|-|1
-2027-05-11|2|r|Sts. Philip & James|Feria_III_after_the_Ascension|-|-|1
-2027-05-12|3|r|Sts. Nereus, Achilleus, Domitilla, & Pancras|Feria_IV_after_the_Ascension|-|-|1
-2027-05-13|3|w|St. Robert Bellarmine|Feria_V_after_the_Ascension|-|-|1
-2027-05-14|4|w|Feria|Feria_VI_after_the_Ascension|St. Boniface|-|1
-2027-05-15|1|r|Saturday after the Ascension|-|-|St. John Baptist de la Salle|1
-2027-05-16|1|r|Pentecost Sunday|-|-|St. Ubaldus|1
-2027-05-17|1|r|Monday after Pentecost|-|-|St. Paschal Baylon|1
-2027-05-18|1|r|Tuesday after Pentecost|-|-|St. Venantius|1
-2027-05-19|1|r|Ember Wednesday of Pentecost|-|-|St. Peter Celestine;St. Pudentiana Virginis|1
-2027-05-20|1|r|Thursday after Pentecost|-|-|St. Bernardine of Siena|1
-2027-05-21|1|r|Ember Friday of Pentecost|-|-|-|1
-2027-05-22|1|r|Ember Saturday of Pentecost|-|-|-|1
-2027-05-23|1|w|Trinity Sunday|-|-|-|1
-2027-05-24|4|g|Feria|Feria_II_after_I_Sunday_after_Pentecost|-|-|1
-2027-05-25|3|w|St. Gregory VII|Feria_III_after_I_Sunday_after_Pentecost|St. Urban, Pope and Martyr|-|1
-2027-05-26|3|w|St. Philip Neri|Feria_IV_after_I_Sunday_after_Pentecost|S. Eleutherius|-|1
-2027-05-27|1|w|Corpus Christi|-|-|St. Bede the Venerable;St. John I|1
-2027-05-28|3|w|St. Augustine of Canterbury|Feria_V_after_I_Sunday_after_Pentecost|-|-|1
-2027-05-29|3|w|St. Mary Magdalene de Pazzi|Saturday_after_I_Sunday_after_Pentecost|-|-|1
-2027-05-30|2|g|II Sunday after Pentecost|-|-|St. Felix I|1
-2027-05-31|2|w|Queenship of the Blessed Virgin Mary|Feria_II_after_II_Sunday_after_Pentecost|St. Petronilla|-|1
-2027-06-01|3|w|St. Angela Merici|Feria_III_after_II_Sunday_after_Pentecost|-|-|1
-2027-06-02|4|g|Feria|Feria_IV_after_II_Sunday_after_Pentecost|Sts. Marcellinus, Peter, & Erasmus|-|1
-2027-06-03|4|g|Feria|Feria_V_after_II_Sunday_after_Pentecost|-|-|1
-2027-06-04|1|w|Sacred Heart of Jesus|-|-|St. Francis Caracciolo|1
-2027-06-05|3|r|St. Boniface|Saturday_after_II_Sunday_after_Pentecost|-|-|1
-2027-06-06|2|g|III Sunday after Pentecost|-|-|St. Norbert|1
-2027-06-07|4|g|Feria|Feria_II_after_III_Sunday_after_Pentecost|-|-|1
-2027-06-08|4|g|Feria|Feria_III_after_III_Sunday_after_Pentecost|-|-|1
-2027-06-09|4|g|Feria|Feria_IV_after_III_Sunday_after_Pentecost|Sts. Primus & Felicianus|-|1
-2027-06-10|3|w|St. Margaret of Scotland|Feria_V_after_III_Sunday_after_Pentecost|-|-|1
-2027-06-11|3|r|St. Barnabas|Feria_VI_after_III_Sunday_after_Pentecost|-|-|1
-2027-06-12|3|r|St. John of San Fecundo|Saturday_after_III_Sunday_after_Pentecost|St. Basilidus|-|1
-2027-06-13|2|g|IV Sunday after Pentecost|-|-|St. Anthony of Padua|1
-2027-06-14|3|w|St. Basil the Great|Feria_II_after_IV_Sunday_after_Pentecost|-|-|1
-2027-06-15|4|g|Feria|Feria_III_after_IV_Sunday_after_Pentecost|St. Vitus|-|1
-2027-06-16|4|g|Feria|Feria_IV_after_IV_Sunday_after_Pentecost|-|-|1
-2027-06-17|3|w|St. Gregory Barbarigo|Feria_V_after_IV_Sunday_after_Pentecost|-|-|1
-2027-06-18|3|r|St. Ephrem of Syria|Feria_VI_after_IV_Sunday_after_Pentecost|Ss. Marcus and Marcellianus|-|1
-2027-06-19|3|r|St. Julia of Falconieri|Saturday_after_IV_Sunday_after_Pentecost|Sts. Gervasius and Protasius|-|1
-2027-06-20|2|g|V Sunday after Pentecost|-|-|St. Silverius|1
-2027-06-21|3|w|St. Aloysius Gongzaga|Feria_II_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-22|3|w|St. Paulinus of Nola|Feria_III_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-23|2|v|Vigil of the Nativity of St. John the Baptist|Feria_IV_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-24|1|w|Nativity of St. John the Baptist|Feria_V_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-25|3|w|St. William|Feria_VI_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-26|3|r|Sts. John & Paul|Saturday_after_V_Sunday_after_Pentecost|-|-|1
-2027-06-27|2|g|VI Sunday after Pentecost|-|-|-|1
-2027-06-28|2|v|Vigil of Sts. Peter & Paul|Feria_II_after_VI_Sunday_after_Pentecost|-|-|1
-2027-06-29|1|r|Sts. Peter & Paul|Feria_III_after_VI_Sunday_after_Pentecost|-|-|1
-2027-06-30|3|r|In Commemoratione Sancti Pauli Apostoli|Feria_IV_after_VI_Sunday_after_Pentecost|-|-|1
-2027-07-01|1|r|The Precious Blood of Our Lord Jesus Christ|Feria_V_after_VI_Sunday_after_Pentecost|-|-|1
-2027-07-02|2|w|Visitation of the Blessed Virgin Mary|Feria_VI_after_VI_Sunday_after_Pentecost|SS. Processus and Martinian|-|1
-2027-07-03|3|r|St. Irenaeus|Saturday_after_VI_Sunday_after_Pentecost|-|-|1
-2027-07-04|2|g|VII Sunday after Pentecost|-|-|-|1
-2027-07-05|3|w|St. Anthony Mary Zaccariah|Feria_II_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-06|4|g|Feria|Feria_III_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-07|3|w|Sts. Cyril & Methodius|Feria_IV_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-08|3|w|St. Elizabeth of Portugal|Feria_V_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-09|4|g|Feria|Feria_VI_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-10|3|r|Seven Holy Brothers and Sts. Rufina & Secunda|Saturday_after_VII_Sunday_after_Pentecost|-|-|1
-2027-07-11|2|g|VIII Sunday after Pentecost|-|-|St. Pius I|1
-2027-07-12|3|r|St. John Gualbert|Feria_II_after_VIII_Sunday_after_Pentecost|Ss. Naboris et Felicis|-|1
-2027-07-13|4|g|Feria|Feria_III_after_VIII_Sunday_after_Pentecost|-|-|1
-2027-07-14|3|w|St. Bonaventure|Feria_IV_after_VIII_Sunday_after_Pentecost|-|-|1
-2027-07-15|3|w|St. Henry the Emperor|Feria_V_after_VIII_Sunday_after_Pentecost|-|-|1
-2027-07-16|4|g|Feria|Feria_VI_after_VIII_Sunday_after_Pentecost|Our Lady of Mt. Carmel|-|1
-2027-07-17|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_VIII_Sunday_after_Pentecost|St. Alexis|-|1
-2027-07-18|2|g|IX Sunday after Pentecost|-|-|Camillus de Lellis;Ss. Symphorosa and sons|1
-2027-07-19|3|w|St. Vincent de Paul|Feria_II_after_IX_Sunday_after_Pentecost|-|-|1
-2027-07-20|3|r|St. Jerome Emiliani|Feria_III_after_IX_Sunday_after_Pentecost|St. Margaret|-|1
-2027-07-21|3|w|St. Laurence of Brindisi|Feria_IV_after_IX_Sunday_after_Pentecost|St. Praxedis Virginis|-|1
-2027-07-22|3|w|St. Mary Magdalene|Feria_V_after_IX_Sunday_after_Pentecost|-|-|1
-2027-07-23|3|w|St. Apollinaris|Feria_VI_after_IX_Sunday_after_Pentecost|S. Liborii|-|1
-2027-07-24|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IX_Sunday_after_Pentecost|St. Christina|-|1
-2027-07-25|2|g|X Sunday after Pentecost|-|St. James the Greater|St. Christopher|1
-2027-07-26|2|w|St. Anne, Mother of the Blessed Virgin|Feria_II_after_X_Sunday_after_Pentecost|-|-|1
-2027-07-27|4|g|Feria|Feria_III_after_X_Sunday_after_Pentecost|St. Pantaleon|-|1
-2027-07-28|3|r|Sts. Nazarius & Celsus, St. Victor I & St. Innocent I|Feria_IV_after_X_Sunday_after_Pentecost|-|-|1
-2027-07-29|3|r|St. Martha|Feria_V_after_X_Sunday_after_Pentecost|Ss. Felicis, Simplicii, Faustini et Beatricis|-|1
-2027-07-30|4|g|Feria|Feria_VI_after_X_Sunday_after_Pentecost|Sts. Abdon & Sennen|-|1
-2027-07-31|3|w|St. Ignatius Loyola|Saturday_after_X_Sunday_after_Pentecost|-|-|1
-2027-08-01|2|g|XI Sunday after Pentecost|-|-|Holy Machabees|1
-2027-08-02|3|r|St. Alphonsus Liguori|Feria_II_after_XI_Sunday_after_Pentecost|St. Stephen I, Pope and Martyr|-|1
-2027-08-03|4|g|Feria|Feria_III_after_XI_Sunday_after_Pentecost|-|-|1
-2027-08-04|3|w|St. Dominic|Feria_IV_after_XI_Sunday_after_Pentecost|-|-|1
-2027-08-05|3|w|Dedication of the Basilica of St. Mary Major|Feria_V_after_XI_Sunday_after_Pentecost|-|-|1
-2027-08-06|2|w|Transfiguration of Our Lord|Feria_VI_after_XI_Sunday_after_Pentecost|Pope Sixtus II, Felicissimus and Agapitus, Martyrs|-|1
-2027-08-07|3|w|St. Cajetan|Saturday_after_XI_Sunday_after_Pentecost|St. Donatus|-|1
-2027-08-08|2|g|XII Sunday after Pentecost|-|-|St. John Mary Vianney;Ss. Cyriacus, Largus and Smaragdus, Martyrs|1
-2027-08-09|3|r|Vigil of St. Lawrence|Feria_II_after_XII_Sunday_after_Pentecost|St. Romanus|-|1
-2027-08-10|2|r|St. Lawrence|Feria_III_after_XII_Sunday_after_Pentecost|-|-|1
-2027-08-11|4|g|Feria|Feria_IV_after_XII_Sunday_after_Pentecost|Sts. Tiburtius & Susanna|-|1
-2027-08-12|3|w|St. Clare|Feria_V_after_XII_Sunday_after_Pentecost|-|-|1
-2027-08-13|4|g|Feria|Feria_VI_after_XII_Sunday_after_Pentecost|Sts. Hippolytus & Cassian|-|1
-2027-08-14|2|w|Vigil of the Assumption|Saturday_after_XII_Sunday_after_Pentecost|St. Eusebius|-|1
-2027-08-15|1|w|Assumption of the Blessed Virgin Mary|XIII_Sunday_after_Pentecost|-|-|1
-2027-08-16|2|w|St. Joachim, Father of the Blessed Virgin|Feria_II_after_XIII_Sunday_after_Pentecost|-|-|1
-2027-08-17|3|w|St. Hyacinth|Feria_III_after_XIII_Sunday_after_Pentecost|-|-|1
-2027-08-18|4|g|Feria|Feria_IV_after_XIII_Sunday_after_Pentecost|St. Agapitus|-|1
-2027-08-19|3|w|St. John Eudes|Feria_V_after_XIII_Sunday_after_Pentecost|-|-|1
-2027-08-20|3|w|St. Bernard of Clairvaux|Feria_VI_after_XIII_Sunday_after_Pentecost|-|-|1
-2027-08-21|3|w|St. Jane Frances de Chantal|Saturday_after_XIII_Sunday_after_Pentecost|-|-|1
-2027-08-22|2|g|XIV Sunday after Pentecost|-|Immaculate Heart of Mary|Sts. Timothy, Hippolytus and Symphorianus, Martyrs|1
-2027-08-23|3|w|St. Philip Benizi|Feria_II_after_XIV_Sunday_after_Pentecost|-|-|1
-2027-08-24|2|r|St. Bartholomew|Feria_III_after_XIV_Sunday_after_Pentecost|-|-|1
-2027-08-25|3|w|St. Louis IX|Feria_IV_after_XIV_Sunday_after_Pentecost|-|-|1
-2027-08-26|4|g|Feria|Feria_V_after_XIV_Sunday_after_Pentecost|St. Zephyrinus|-|1
-2027-08-27|3|w|St. Joseph Calasance|Feria_VI_after_XIV_Sunday_after_Pentecost|-|-|1
-2027-08-28|3|r|St. Augustine|Saturday_after_XIV_Sunday_after_Pentecost|St. Hermes|-|1
-2027-08-29|2|g|XV Sunday after Pentecost|-|-|Beheading of St. John the Baptist;St. Sabina|1
-2027-08-30|3|r|St. Rose of Lima|Feria_II_after_XV_Sunday_after_Pentecost|Sts. Felix and Adauctus|-|1
-2027-08-31|3|w|St. Raymond Nonnatus|Feria_III_after_XV_Sunday_after_Pentecost|-|-|1
-2027-09-01|4|g|Feria|Feria_IV_after_XV_Sunday_after_Pentecost|St. Giles;Twelve Holy Brothers, Martyrs|-|1
-2027-09-02|3|w|St. Stephen of Hungary|Feria_V_after_XV_Sunday_after_Pentecost|-|-|1
-2027-09-03|3|w|St. Pius X|Feria_VI_after_XV_Sunday_after_Pentecost|-|-|1
-2027-09-04|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XV_Sunday_after_Pentecost|-|-|1
-2027-09-05|2|g|XVI Sunday after Pentecost|-|-|St. Lawrence Justinian|1
-2027-09-06|4|g|Feria|Feria_II_after_XVI_Sunday_after_Pentecost|-|-|1
-2027-09-07|4|g|Feria|Feria_III_after_XVI_Sunday_after_Pentecost|-|-|1
-2027-09-08|2|w|Nativity of the Blessed Virgin Mary|Feria_IV_after_XVI_Sunday_after_Pentecost|S. Hadriani|-|1
-2027-09-09|4|g|Feria|Feria_V_after_XVI_Sunday_after_Pentecost|St. Gorgonius|-|1
-2027-09-10|3|w|St. Nicholas of Tolentino|Feria_VI_after_XVI_Sunday_after_Pentecost|-|-|1
-2027-09-11|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XVI_Sunday_after_Pentecost|Sts. Protus & Hyacinth|-|1
-2027-09-12|2|g|XVII Sunday after Pentecost|-|-|Most Holy Name of Mary|1
-2027-09-13|4|g|Feria|Feria_II_after_XVII_Sunday_after_Pentecost|-|-|1
-2027-09-14|2|r|Exaltation of the Holy Cross|Feria_III_after_XVII_Sunday_after_Pentecost|-|-|1
-2027-09-15|2|w|Seven Sorrows of the Blessed Virgin Mary|Feria_IV_after_XVII_Sunday_after_Pentecost|S. Nicomedes|-|1
-2027-09-16|3|r|Sts. Cornelius & Cyprian|Feria_V_after_XVII_Sunday_after_Pentecost|Sts. Euphemia, Lucy and Geminianus|-|1
-2027-09-17|4|g|Feria|Feria_VI_after_XVII_Sunday_after_Pentecost|Stigmata of St. Francis|-|1
-2027-09-18|3|w|St. Joseph of Cupertino|Saturday_after_XVII_Sunday_after_Pentecost|-|-|1
-2027-09-19|2|g|XVIII Sunday after Pentecost|-|-|St. Januarius & Companions|1
-2027-09-20|4|g|Feria|Feria_II_after_XVIII_Sunday_after_Pentecost|Sts. Eustace & Companions|-|1
-2027-09-21|2|r|St. Matthew|Feria_III_after_XVIII_Sunday_after_Pentecost|-|-|1
-2027-09-22|2|v|Ember Wednesday of September|-|St. Thomas of Villanova|St. Maurice and Companions, Martyrs|1
-2027-09-23|3|r|St. Linus|Feria_V_after_XVIII_Sunday_after_Pentecost|St. Thecla|-|1
-2027-09-24|2|v|Ember Friday of September|-|Our Lady of Ransom|-|1
-2027-09-25|2|v|Ember Saturday of September|-|-|-|1
-2027-09-26|2|g|XIX Sunday after Pentecost|-|-|Sts. Cyprian & Justina|1
-2027-09-27|3|r|Sts. Cosmas & Damian|Feria_II_after_XIX_Sunday_after_Pentecost|-|-|1
-2027-09-28|3|r|St. Wenceslaus|Feria_III_after_XIX_Sunday_after_Pentecost|-|-|1
-2027-09-29|1|w|Dedication of St. Michael the Archangel|Feria_IV_after_XIX_Sunday_after_Pentecost|-|-|1
-2027-09-30|3|w|St. Jerome|Feria_V_after_XIX_Sunday_after_Pentecost|-|-|1
-2027-10-01|4|g|Feria|Feria_VI_after_XIX_Sunday_after_Pentecost|St. Remigius|-|1
-2027-10-02|3|w|Holy Guardian Angels|Saturday_after_XIX_Sunday_after_Pentecost|-|-|1
-2027-10-03|2|g|XX Sunday after Pentecost|-|-|St. Theresa of the Infant Jesus|1
-2027-10-04|3|w|St. Francis of Assisi|Feria_II_after_XX_Sunday_after_Pentecost|-|-|1
-2027-10-05|4|g|Feria|Feria_III_after_XX_Sunday_after_Pentecost|St. Placid & Companions|-|1
-2027-10-06|3|w|St. Bruno|Feria_IV_after_XX_Sunday_after_Pentecost|-|-|1
-2027-10-07|2|w|Our Lady of the Rosary|Feria_V_after_XX_Sunday_after_Pentecost|St. Mark I|-|1
-2027-10-08|3|w|St. Bridget of Sweden|Feria_VI_after_XX_Sunday_after_Pentecost|Ss. Sergio, Baccho, Marcello and Apulejo Martyrs|-|1
-2027-10-09|3|w|St. John Leonardi|Saturday_after_XX_Sunday_after_Pentecost|St. Dionysius and companions|-|1
-2027-10-10|2|g|XXI Sunday after Pentecost|-|-|St. Francis Borgia|1
-2027-10-11|2|w|Maternity of the Blessed Virgin Mary|Feria_II_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-12|4|g|Feria|Feria_III_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-13|3|w|St. Edward|Feria_IV_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-14|3|r|St. Callistus I|Feria_V_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-15|3|w|St. Teresa of Avila|Feria_VI_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-16|3|w|St. Hedwig|Saturday_after_XXI_Sunday_after_Pentecost|-|-|1
-2027-10-17|2|g|XXII Sunday after Pentecost|-|-|St. Margaret Mary Alacoque|1
-2027-10-18|2|r|St. Luke the Evangelist|Feria_II_after_XXII_Sunday_after_Pentecost|-|-|1
-2027-10-19|3|w|St. Peter of Alcantara|Feria_III_after_XXII_Sunday_after_Pentecost|-|-|1
-2027-10-20|3|w|St. John Cantius|Feria_IV_after_XXII_Sunday_after_Pentecost|-|-|1
-2027-10-21|4|g|Feria|Feria_V_after_XXII_Sunday_after_Pentecost|St. Hilarion;St. Ursula and Companions|-|1
-2027-10-22|4|g|Feria|Feria_VI_after_XXII_Sunday_after_Pentecost|-|-|1
-2027-10-23|3|w|St. Anthony Mary Claret|Saturday_after_XXII_Sunday_after_Pentecost|-|-|1
-2027-10-24|2|g|XXIII Sunday after Pentecost|-|-|St. Raphael the Archangel|1
-2027-10-25|4|g|Feria|Feria_II_after_XXIII_Sunday_after_Pentecost|Sts. Chrysanthus & Daria|-|1
-2027-10-26|4|g|Feria|Feria_III_after_XXIII_Sunday_after_Pentecost|St. Evaristus|-|1
-2027-10-27|4|g|Feria|Feria_IV_after_XXIII_Sunday_after_Pentecost|-|-|1
-2027-10-28|2|r|Sts. Simon & Jude|Feria_V_after_XXIII_Sunday_after_Pentecost|-|-|1
-2027-10-29|4|g|Feria|Feria_VI_after_XXIII_Sunday_after_Pentecost|-|-|1
-2027-10-30|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIII_Sunday_after_Pentecost|-|-|1
-2027-10-31|1|w|Christ the King|IV_Sunday_after_Epiphany|-|-|1
-2027-11-01|1|w|All Saints|Feria_II_after_IV_Sunday_after_Epiphany|-|-|1
-2027-11-02|1|b|Commemoration of All Souls|Feria_III_after_IV_Sunday_after_Epiphany|-|-|3
-2027-11-03|4|g|Feria|Feria_IV_after_IV_Sunday_after_Epiphany|-|-|1
-2027-11-04|3|w|St. Charles Borromeo|Feria_V_after_IV_Sunday_after_Epiphany|Sts. Vitalis and Agricola, Martyrs|-|1
-2027-11-05|4|g|Feria|Feria_VI_after_IV_Sunday_after_Epiphany|-|-|1
-2027-11-06|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IV_Sunday_after_Epiphany|-|-|1
-2027-11-07|2|g|V Sunday after Epiphany|-|-|-|1
-2027-11-08|4|g|Feria|Feria_II_after_V_Sunday_after_Epiphany|Four Holy Crowned Martyrs|-|1
-2027-11-09|2|w|Dedication of the Archbasilica of Our Holy Savior|Feria_III_after_V_Sunday_after_Epiphany|St. Theodore|-|1
-2027-11-10|3|w|St. Andrew Avellino|Feria_IV_after_V_Sunday_after_Epiphany|Sts. Tryphonis, Respicii, et Nymphae|-|1
-2027-11-11|3|w|St. Martin of Tours|Feria_V_after_V_Sunday_after_Epiphany|St. Menna|-|1
-2027-11-12|3|r|St. Martin I|Feria_VI_after_V_Sunday_after_Epiphany|-|-|1
-2027-11-13|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_V_Sunday_after_Epiphany|St. Didacus|-|1
-2027-11-14|2|g|VI Sunday after Epiphany|-|-|St. Josaphat|1
-2027-11-15|3|w|St. Albert the Great|Feria_II_after_VI_Sunday_after_Epiphany|-|-|1
-2027-11-16|3|w|St. Gertrude the Great|Feria_III_after_VI_Sunday_after_Epiphany|-|-|1
-2027-11-17|3|w|St. Gregory the Wonderworker|Feria_IV_after_VI_Sunday_after_Epiphany|-|-|1
-2027-11-18|3|w|Dedication of the Basilicas of Sts. Peter & Paul|Feria_V_after_VI_Sunday_after_Epiphany|-|-|1
-2027-11-19|3|w|St. Elizabeth of Hungary|Feria_VI_after_VI_Sunday_after_Epiphany|St. Pontian|-|1
-2027-11-20|3|w|St. Felix of Valois|Saturday_after_VI_Sunday_after_Epiphany|-|-|1
-2027-11-21|2|g|XXIV Sunday after Pentecost|-|-|Presentation of the Blessed Virgin Mary|1
-2027-11-22|3|r|St. Cecilia|Feria_II_after_XXIV_Sunday_after_Pentecost|-|-|1
-2027-11-23|3|r|St. Clement I|Feria_III_after_XXIV_Sunday_after_Pentecost|St. Felicity|-|1
-2027-11-24|3|w|St. John of the Cross|Feria_IV_after_XXIV_Sunday_after_Pentecost|St. Chrysogonus|-|1
-2027-11-25|3|r|St. Catherine of Alexandria|Feria_V_after_XXIV_Sunday_after_Pentecost|-|-|1
-2027-11-26|3|w|St. Sylvester|Feria_VI_after_XXIV_Sunday_after_Pentecost|St. Peter of Alexandria|-|1
-2027-11-27|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIV_Sunday_after_Pentecost|-|-|1
-2027-11-28|1|v|I Sunday of Advent|-|-|-|1
-2027-11-29|3|v|Feria II after I Sunday of Advent|-|St. Saturninus|-|1
-2027-11-30|2|r|St. Andrew|Feria_III_after_I_Sunday_of_Advent|-|-|1
-2027-12-01|3|v|Feria IV after I Sunday of Advent|-|-|-|1
-2027-12-02|3|r|St. Vivian|Feria_V_after_I_Sunday_of_Advent|Feria V after I Sunday of Advent|-|1
-2027-12-03|3|w|St. Francis Xavier|Feria_VI_after_I_Sunday_of_Advent|Feria VI after I Sunday of Advent|-|1
-2027-12-04|3|w|St. Peter Chrysologus|Sabbato_after_I_Sunday_of_Advent|Sabbato after I Sunday of Advent|-|1
-2027-12-05|1|v|II Sunday of Advent|-|-|St. Sabbas|1
-2027-12-06|3|w|St. Nicholas|Feria_II_after_II_Sunday_of_Advent|Feria II after II Sunday of Advent|-|1
-2027-12-07|3|w|St. Ambrose|Feria_III_after_II_Sunday_of_Advent|Feria III after II Sunday of Advent|-|1
-2027-12-08|1|w|Immaculate Conception of the Blessed Virgin Mary|Feria_IV_after_II_Sunday_of_Advent|-|-|1
-2027-12-09|3|v|Feria V after II Sunday of Advent|-|-|-|1
-2027-12-10|3|v|Feria VI after II Sunday of Advent|-|St. Melchiades|-|1
-2027-12-11|3|w|St. Damasus I|Sabbato_after_II_Sunday_of_Advent|Sabbato after II Sunday of Advent|-|1
-2027-12-12|1|pv|III Sunday of Advent|-|-|-|1
-2027-12-13|3|r|St. Lucy|Feria_II_after_III_Sunday_of_Advent|Feria II after III Sunday of Advent|-|1
-2027-12-14|3|pv|Feria III after III Sunday of Advent|-|-|-|1
-2027-12-15|2|v|Ember Wednesday of Advent|-|-|-|1
-2027-12-16|3|r|St. Eusebius|Feria_V_after_III_Sunday_of_Advent|Feria V after III Sunday of Advent|-|1
-2027-12-17|2|v|Ember Friday of Advent|-|-|-|1
-2027-12-18|2|v|Ember Saturday of Advent|-|-|-|1
-2027-12-19|1|v|IV Sunday of Advent|-|-|-|1
-2027-12-20|2|v|Feria II after IV Sunday of Advent|-|-|-|1
-2027-12-21|2|r|St. Thomas|Feria_III_after_IV_Sunday_of_Advent|Feria III after IV Sunday of Advent|-|1
-2027-12-22|2|v|Feria IV after IV Sunday of Advent|-|-|-|1
-2027-12-23|2|v|Feria V after IV Sunday of Advent|-|-|-|1
-2027-12-24|1|v|Vigil of Christmas|-|-|-|1
-2027-12-25|1|w|The Nativity of Our Lord|-|-|-|3
-2027-12-26|2|w|Sunday in the Octave of Christmas|-|St. Stephen|For Octave of the Nativity|1
-2027-12-27|2|w|St. John the Evangelist|-|For Octave of the Nativity|-|1
-2027-12-28|2|r|Holy Innocents|-|For Octave of the Nativity|-|1
-2027-12-29|2|w|Feria in the Octave of Christmas|-|St. Thomas Becket|-|1
-2027-12-30|2|w|Feria in the Octave of Christmas|-|-|-|1
-2027-12-31|2|w|Feria in the Octave of Christmas|-|St. Silvester|-|1
+2026-01-01|1|w|Octave Day of Christmas|-|-|-|1|-
+2026-01-02|4|w|Feria|-|-|-|1|-
+2026-01-03|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1|-
+2026-01-04|2|w|Holy Name of Jesus|-|-|-|1|-
+2026-01-05|4|w|Feria|-|St. Telesphorus Pope and Martyr|-|1|sancti:01-05:4:r
+2026-01-06|1|w|Epiphany of the Lord|-|-|-|1|-
+2026-01-07|4|w|Feria|-|-|-|1|-
+2026-01-08|4|w|Feria|-|-|-|1|-
+2026-01-09|4|w|Feria|-|-|-|1|-
+2026-01-10|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1|-
+2026-01-11|2|w|The Holy Family: Jesus, Mary & Joseph|-|-|St. Hyginus Pope and Martyr|1|-
+2026-01-12|4|w|Feria|Feria_II_after_Epiphany|-|-|1|-
+2026-01-13|2|w|Commemoration of the Baptism of the Lord|Feria_III_after_Epiphany|-|-|1|-
+2026-01-14|3|w|St. Hilary|Feria_IV_after_Epiphany|S. Felicis|-|1|sancti:01-14cc:4:r
+2026-01-15|3|w|St. Paul, the First Hermit|Feria_V_after_Epiphany|St. Maur, Abbot|-|1|sancti:01-15cc:4:w
+2026-01-16|3|r|St. Marcellus I|Feria_VI_after_Epiphany|-|-|1|-
+2026-01-17|3|w|St. Anthony|Saturday_after_Epiphany|-|-|1|-
+2026-01-18|2|g|II Sunday after Epiphany|-|-|St. Prisca|1|-
+2026-01-19|4|g|Feria|Feria_II_after_II_Sunday_after_Epiphany|Sts. Marius, Martha, Audifax & Abachum;St. Canute, Martyr|-|1|sancti:01-19:4:r;sancti:01-19o:4:r
+2026-01-20|3|r|Sts. Fabian & Sebastian|Feria_III_after_II_Sunday_after_Epiphany|-|-|1|-
+2026-01-21|3|r|St. Agnes|Feria_IV_after_II_Sunday_after_Epiphany|-|-|1|-
+2026-01-22|3|r|Sts. Vincent & Anastasius|Feria_V_after_II_Sunday_after_Epiphany|-|-|1|-
+2026-01-23|3|w|St. Raymond of Peñafort|Feria_VI_after_II_Sunday_after_Epiphany|St. Emerentiana|-|1|sancti:01-23o:4:r
+2026-01-24|3|r|St. Timothy|Saturday_after_II_Sunday_after_Epiphany|-|-|1|-
+2026-01-25|2|g|III Sunday after Epiphany|-|-|Conversion of St. Paul;St. Peter|1|-
+2026-01-26|3|r|St. Polycarp|Feria_II_after_III_Sunday_after_Epiphany|-|-|1|-
+2026-01-27|3|w|St. John Chrysostom|Feria_III_after_III_Sunday_after_Epiphany|-|-|1|-
+2026-01-28|3|w|St. Peter Nolasco|Feria_IV_after_III_Sunday_after_Epiphany|St. Agnes|-|1|sancti:01-28t:4:r
+2026-01-29|3|w|St. Francis de Sales|Feria_V_after_III_Sunday_after_Epiphany|-|-|1|-
+2026-01-30|3|r|St. Martina|Feria_VI_after_III_Sunday_after_Epiphany|-|-|1|-
+2026-01-31|3|w|St. John Bosco|Saturday_after_III_Sunday_after_Epiphany|-|-|1|-
+2026-02-01|2|v|Septuagesima Sunday|-|-|St. Ignatius of Antioch|1|-
+2026-02-02|2|w|Purification of the Blessed Virgin Mary|Feria_II_after_Septuagesima|-|-|1|-
+2026-02-03|4|v|Feria|Feria_III_after_Septuagesima|St. Blaise|-|1|sancti:02-03:4:r
+2026-02-04|3|w|St. Andrew Corsini|Feria_IV_after_Septuagesima|-|-|1|-
+2026-02-05|3|r|St. Agatha|Feria_V_after_Septuagesima|-|-|1|-
+2026-02-06|3|w|St. Titus|Feria_VI_after_Septuagesima|St. Dorothy|-|1|sancti:02-06o:4:r
+2026-02-07|3|w|St. Romuald|Saturday_after_Septuagesima|-|-|1|-
+2026-02-08|2|v|Sexagesima Sunday|-|-|St. John of Matha|1|-
+2026-02-09|3|w|St. Cyril of Alexandria|Feria_II_after_Sexagesima|St. Appollonia|-|1|sancti:02-09o:4:r
+2026-02-10|3|w|St. Scholastica|Feria_III_after_Sexagesimæ|-|-|1|-
+2026-02-11|3|w|Our Lady of Lourdes|Feria_IV_after_Sexagesimæ|-|-|1|-
+2026-02-12|3|w|Seven Holy Servite Founders|Feria_V_after_Sexagesimæ|-|-|1|-
+2026-02-13|4|v|Feria|Feria_VI_after_Sexagesimæ|-|-|1|-
+2026-02-14|4|w|III Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_Sexagesimæ|St. Valentine|-|1|sancti:02-14:4:r
+2026-02-15|2|v|Quinquagesima Sunday|-|-|Sts. Faustinus & Jovita|1|-
+2026-02-16|4|v|Feria|Feria_II_after_Quinquagesima|-|-|1|-
+2026-02-17|4|v|Feria|Feria_III_after_Quinquagesima|-|-|1|-
+2026-02-18|1|v|Ash Wednesday|-|-|St. Simeon|1|-
+2026-02-19|3|v|Feria V after Ash Wednesday|-|-|-|1|-
+2026-02-20|3|v|Feria VI after Ash Wednesday|-|-|-|1|-
+2026-02-21|3|v|Saturday after Ash Wednesday|-|-|-|1|-
+2026-02-22|1|v|I Sunday of Lent|-|-|Chair of St. Peter;St. Paul|1|-
+2026-02-23|3|v|Feria II after the I Sunday of Lent|-|St. Peter Damien|-|1|sancti:02-23r:3:w
+2026-02-24|2|r|St. Matthias|Feria_III_after_the_I_Sunday_of_Lent|Feria III after the I Sunday of Lent|-|1|tempora:Quad1-2:3:v
+2026-02-25|2|v|Ember Wednesday of Lent|-|-|-|1|-
+2026-02-26|3|v|Feria V after the I Sunday of Lent|-|-|-|1|-
+2026-02-27|2|v|Ember Friday of Lent|-|St. Gabriel of Our Lady of Sorrows|-|1|sancti:02-27:3:w
+2026-02-28|2|v|Ember Saturday of Lent|-|-|-|1|-
+2026-03-01|1|v|II Sunday of Lent|-|-|-|1|-
+2026-03-02|3|v|Feria II after the II Sunday of Lent|-|-|-|1|-
+2026-03-03|3|v|Feria III after the II Sunday of Lent|-|-|-|1|-
+2026-03-04|3|v|Feria IV after the II Sunday of Lent|-|St. Casimir;St. Lucius|-|1|sancti:03-04:3:w;sancti:03-04cc:4:r
+2026-03-05|3|v|Feria V after the II Sunday of Lent|-|-|-|1|-
+2026-03-06|3|v|Feria VI after the II Sunday of Lent|-|Sts. Felicitas & Perpetua|-|1|sancti:03-06:3:r
+2026-03-07|3|v|Saturday after the II Sunday of Lent|-|St. Thomas Aquinas|-|1|sancti:03-07:3:w
+2026-03-08|1|v|III Sunday of Lent|-|-|St. John of God|1|-
+2026-03-09|3|v|Feria II after the III Sunday of Lent|-|St. Frances Rome|-|1|sancti:03-09:3:w
+2026-03-10|3|v|Feria III after the III Sunday of Lent|-|Forty Holy Martyrs of Sebaste|-|1|sancti:03-10:3:r
+2026-03-11|3|v|Feria IV after the III Sunday of Lent|-|-|-|1|-
+2026-03-12|3|v|Feria V after the III Sunday of Lent|-|St. Gregory the Great|-|1|sancti:03-12:3:w
+2026-03-13|3|v|Feria VI after the III Sunday of Lent|-|-|-|1|-
+2026-03-14|3|v|Saturday after the III Sunday of Lent|-|-|-|1|-
+2026-03-15|1|pv|IV Sunday of Lent|-|-|-|1|-
+2026-03-16|3|v|Feria II after the IV Sunday of Lent|-|-|-|1|-
+2026-03-17|3|v|Feria III after the IV Sunday of Lent|-|St. Patrick|-|1|sancti:03-17:3:w
+2026-03-18|3|v|Feria IV after the IV Sunday of Lent|-|St. Cyril of Jerusalem|-|1|sancti:03-18:3:w
+2026-03-19|1|w|St. Joseph, Spouse of the Bl. Virgin Mary|Feria_V_after_the_IV_Sunday_of_Lent|Feria V after the IV Sunday of Lent|-|1|tempora:Quad4-4:3:v
+2026-03-20|3|v|Feria VI after the IV Sunday of Lent|-|-|-|1|-
+2026-03-21|3|v|Saturday after the IV Sunday of Lent|-|St. Benedict|-|1|sancti:03-21:3:w
+2026-03-22|1|v|Passion Sunday|-|-|-|1|-
+2026-03-23|3|v|Feria II of Passion Week|-|-|-|1|-
+2026-03-24|3|v|Feria III of Passion Week|-|St. Gabriel the Archangel|-|1|sancti:03-24:3:w
+2026-03-25|1|w|Annunciation of the Blessed Virgin Mary|Feria_IV_of_Passion_Week|Feria IV of Passion Week|-|1|tempora:Quad5-3:3:v
+2026-03-26|3|v|Feria V of Passion Week|-|-|-|1|-
+2026-03-27|3|v|Feria VI of Passion Week|-|For Our Lady of the Seven Sorrows|St. John Damascene|1|tempora:Quad5-5Feriac:4:w
+2026-03-28|3|v|Saturday of Passion Week|-|St. John of Capistrano|-|1|sancti:03-28:3:w
+2026-03-29|1|rv|Palm Sunday|-|-|-|1|-
+2026-03-30|1|v|Feria II of Holy Week|-|-|-|1|-
+2026-03-31|1|v|Feria III of Holy Week|-|-|-|1|-
+2026-04-01|1|v|Feria IV of Holy Week|-|-|-|1|-
+2026-04-02|1|w|Holy Thursday|-|-|St. Francis of Paola|1|-
+2026-04-03|1|bv|Good Friday|-|-|-|1|-
+2026-04-04|1|vw|Holy Saturday|-|-|St. Isidore of Seville|1|-
+2026-04-05|1|w|Easter Sunday|-|-|St. Vincent Ferrer|1|-
+2026-04-06|1|w|Monday in the Octave of Easter|-|-|-|1|-
+2026-04-07|1|w|Tuesday in the Octave of Easter|-|-|-|1|-
+2026-04-08|1|w|Wednesday in the Octave of Easter|-|-|-|1|-
+2026-04-09|1|w|Thursday in the Octave of Easter|-|-|-|1|-
+2026-04-10|1|w|Friday in the Octave of Easter|-|-|-|1|-
+2026-04-11|1|w|Saturday in the Octave of Easter|-|-|St. Leo the Great|1|-
+2026-04-12|1|w|Low Sunday|-|-|-|1|-
+2026-04-13|3|r|St. Hermenegild|Monday_after_I_Sunday_after_Easter|-|-|1|-
+2026-04-14|3|r|St. Justin|Tuesday_after_I_Sunday_after_Easter|Sts. Tiburtius, Valerian et Maximus, Martyrs|-|1|sancti:04-14t:4:r
+2026-04-15|4|w|Feria|Wednesday_after_I_Sunday_after_Easter|-|-|1|-
+2026-04-16|4|w|Feria|Thursday_after_I_Sunday_after_Easter|-|-|1|-
+2026-04-17|4|w|Feria|Friday_after_I_Sunday_after_Easter|St. Anicetus|-|1|sancti:04-17:4:r
+2026-04-18|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_I_Sunday_after_Easter|-|-|1|-
+2026-04-19|2|w|II Sunday after Easter|-|-|-|1|-
+2026-04-20|4|w|Feria|Monday_after_II_Sunday_after_Easter|-|-|1|-
+2026-04-21|3|w|St. Anselm|Tuesday_after_II_Sunday_after_Easter|-|-|1|-
+2026-04-22|3|r|Sts. Soter & Caius|Wednesday_after_II_Sunday_after_Easter|-|-|1|-
+2026-04-23|4|w|Feria|Thursday_after_II_Sunday_after_Easter|St. George|-|1|sancti:04-23:4:r
+2026-04-24|3|r|St. Fidelis of Sigmaringen|Friday_after_II_Sunday_after_Easter|-|-|1|-
+2026-04-25|2|r|St. Mark|Saturday_after_II_Sunday_after_Easter|Pro rogationibus|-|1|sancti:04-25c:4:r
+2026-04-26|2|w|III Sunday after Easter|-|-|Sts. Cletus & Marcellinus|1|-
+2026-04-27|3|w|St. Peter Canisius|Monday_after_III_Sunday_after_Easter|-|-|1|-
+2026-04-28|3|w|St. Paul of the Cross|Tuesday_after_III_Sunday_after_Easter|-|-|1|-
+2026-04-29|3|r|St. Peter of Verona|Wednesday_after_III_Sunday_after_Easter|-|-|1|-
+2026-04-30|3|w|St. Catherine of Siena|Thursday_after_III_Sunday_after_Easter|-|-|1|-
+2026-05-01|1|w|St. Joseph the Workman|Friday_after_III_Sunday_after_Easter|-|-|1|-
+2026-05-02|3|w|St. Athanasius|Saturday_after_III_Sunday_after_Easter|-|-|1|-
+2026-05-03|2|w|IV Sunday after Easter|-|-|Sts. Alexander & Companions|1|-
+2026-05-04|3|w|St. Monica|Monday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-05|3|w|St. Pius V|Tuesday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-06|4|w|Feria|Wednesday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-07|3|r|St. Stanislaus|Thursday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-08|4|w|Feria|Friday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-09|3|w|St. Gregory of Nazianzen|Saturday_after_IV_Sunday_after_Easter|-|-|1|-
+2026-05-10|2|w|V Sunday after Easter|-|-|St. Antoninus;St. Gordiano and Epimacho|1|-
+2026-05-11|2|r|Sts. Philip & James|The_Minor_Litanies_–_Rogations|-|-|1|-
+2026-05-12|3|r|Sts. Nereus, Achilleus, Domitilla, & Pancras|The_Minor_Litanies_–_Rogations|-|-|1|-
+2026-05-13|2|w|Vigil of the Ascension|-|St. Robert Bellarmine|-|1|sancti:05-13:3:w
+2026-05-14|1|w|Ascension of the Lord|-|-|St. Boniface|1|-
+2026-05-15|3|w|St. John Baptist de la Salle|Feria_VI_after_the_Ascension|-|-|1|-
+2026-05-16|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_the_Ascension|St. Ubaldus|-|1|sancti:05-16:4:w
+2026-05-17|2|w|Sunday after the Ascension|-|-|St. Paschal Baylon|1|-
+2026-05-18|3|r|St. Venantius|Feria_II_after_the_Ascension|-|-|1|-
+2026-05-19|3|w|St. Peter Celestine|Feria_III_after_the_Ascension|St. Pudentiana Virginis|-|1|sancti:05-19o:4:w
+2026-05-20|3|w|St. Bernardine of Siena|Feria_IV_after_the_Ascension|-|-|1|-
+2026-05-21|4|w|Feria|Feria_V_after_the_Ascension|-|-|1|-
+2026-05-22|4|w|Feria|Feria_VI_after_the_Ascension|-|-|1|-
+2026-05-23|1|r|Saturday after the Ascension|-|-|-|1|-
+2026-05-24|1|r|Pentecost Sunday|-|-|-|1|-
+2026-05-25|1|r|Monday after Pentecost|-|-|St. Gregory VII;St. Urban, Pope and Martyr|1|-
+2026-05-26|1|r|Tuesday after Pentecost|-|-|St. Philip Neri;S. Eleutherius|1|-
+2026-05-27|1|r|Ember Wednesday of Pentecost|-|-|St. Bede the Venerable;St. John I|1|-
+2026-05-28|1|r|Thursday after Pentecost|-|-|St. Augustine of Canterbury|1|-
+2026-05-29|1|r|Ember Friday of Pentecost|-|-|St. Mary Magdalene de Pazzi|1|-
+2026-05-30|1|r|Ember Saturday of Pentecost|-|-|St. Felix I|1|-
+2026-05-31|1|w|Trinity Sunday|-|-|Queenship of the Blessed Virgin Mary;St. Petronilla|1|-
+2026-06-01|3|w|St. Angela Merici|Feria_II_after_I_Sunday_after_Pentecost|-|-|1|-
+2026-06-02|4|g|Feria|Feria_III_after_I_Sunday_after_Pentecost|Sts. Marcellinus, Peter, & Erasmus|-|1|sancti:06-02:4:r
+2026-06-03|4|g|Feria|Feria_IV_after_I_Sunday_after_Pentecost|-|-|1|-
+2026-06-04|1|w|Corpus Christi|-|-|St. Francis Caracciolo|1|-
+2026-06-05|3|r|St. Boniface|Feria_V_after_I_Sunday_after_Pentecost|-|-|1|-
+2026-06-06|3|w|St. Norbert|Saturday_after_I_Sunday_after_Pentecost|-|-|1|-
+2026-06-07|2|g|II Sunday after Pentecost|-|-|-|1|-
+2026-06-08|4|g|Feria|Feria_II_after_II_Sunday_after_Pentecost|-|-|1|-
+2026-06-09|4|g|Feria|Feria_III_after_II_Sunday_after_Pentecost|Sts. Primus & Felicianus|-|1|sancti:06-09:4:r
+2026-06-10|3|w|St. Margaret of Scotland|Feria_IV_after_II_Sunday_after_Pentecost|-|-|1|-
+2026-06-11|3|r|St. Barnabas|Feria_V_after_II_Sunday_after_Pentecost|-|-|1|-
+2026-06-12|1|w|Sacred Heart of Jesus|-|-|St. John of San Fecundo;St. Basilidus|1|-
+2026-06-13|3|w|St. Anthony of Padua|Saturday_after_II_Sunday_after_Pentecost|-|-|1|-
+2026-06-14|2|g|III Sunday after Pentecost|-|-|St. Basil the Great|1|-
+2026-06-15|4|g|Feria|Feria_II_after_III_Sunday_after_Pentecost|St. Vitus|-|1|sancti:06-15:4:w
+2026-06-16|4|g|Feria|Feria_III_after_III_Sunday_after_Pentecost|-|-|1|-
+2026-06-17|3|w|St. Gregory Barbarigo|Feria_IV_after_III_Sunday_after_Pentecost|-|-|1|-
+2026-06-18|3|r|St. Ephrem of Syria|Feria_V_after_III_Sunday_after_Pentecost|Ss. Marcus and Marcellianus|-|1|sancti:06-18t:4:r
+2026-06-19|3|r|St. Julia of Falconieri|Feria_VI_after_III_Sunday_after_Pentecost|Sts. Gervasius and Protasius|-|1|sancti:06-19o:4:r
+2026-06-20|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_III_Sunday_after_Pentecost|St. Silverius|-|1|sancti:06-20:4:r
+2026-06-21|2|g|IV Sunday after Pentecost|-|-|St. Aloysius Gongzaga|1|-
+2026-06-22|3|w|St. Paulinus of Nola|Feria_II_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-23|2|v|Vigil of the Nativity of St. John the Baptist|Feria_III_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-24|1|w|Nativity of St. John the Baptist|Feria_IV_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-25|3|w|St. William|Feria_V_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-26|3|r|Sts. John & Paul|Feria_VI_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-27|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IV_Sunday_after_Pentecost|-|-|1|-
+2026-06-28|2|g|V Sunday after Pentecost|-|Vigil of Sts. Peter & Paul|-|1|sancti:06-28r:2:v
+2026-06-29|1|r|Sts. Peter & Paul|Feria_II_after_V_Sunday_after_Pentecost|-|-|1|-
+2026-06-30|3|r|In Commemoratione Sancti Pauli Apostoli|Feria_III_after_V_Sunday_after_Pentecost|-|-|1|-
+2026-07-01|1|r|The Precious Blood of Our Lord Jesus Christ|Feria_IV_after_V_Sunday_after_Pentecost|-|-|1|-
+2026-07-02|2|w|Visitation of the Blessed Virgin Mary|Feria_V_after_V_Sunday_after_Pentecost|SS. Processus and Martinian|-|1|sancti:07-02cc:4:r
+2026-07-03|3|r|St. Irenaeus|Feria_VI_after_V_Sunday_after_Pentecost|-|-|1|-
+2026-07-04|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_V_Sunday_after_Pentecost|-|-|1|-
+2026-07-05|2|g|VI Sunday after Pentecost|-|-|St. Anthony Mary Zaccariah|1|-
+2026-07-06|4|g|Feria|Feria_II_after_VI_Sunday_after_Pentecost|-|-|1|-
+2026-07-07|3|w|Sts. Cyril & Methodius|Feria_III_after_VI_Sunday_after_Pentecost|-|-|1|-
+2026-07-08|3|w|St. Elizabeth of Portugal|Feria_IV_after_VI_Sunday_after_Pentecost|-|-|1|-
+2026-07-09|4|g|Feria|Feria_V_after_VI_Sunday_after_Pentecost|-|-|1|-
+2026-07-10|3|r|Seven Holy Brothers and Sts. Rufina & Secunda|Feria_VI_after_VI_Sunday_after_Pentecost|-|-|1|-
+2026-07-11|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_VI_Sunday_after_Pentecost|St. Pius I|-|1|sancti:07-11:4:r
+2026-07-12|2|g|VII Sunday after Pentecost|-|-|St. John Gualbert;Ss. Naboris et Felicis|1|-
+2026-07-13|4|g|Feria|Feria_II_after_VII_Sunday_after_Pentecost|-|-|1|-
+2026-07-14|3|w|St. Bonaventure|Feria_III_after_VII_Sunday_after_Pentecost|-|-|1|-
+2026-07-15|3|w|St. Henry the Emperor|Feria_IV_after_VII_Sunday_after_Pentecost|-|-|1|-
+2026-07-16|4|g|Feria|Feria_V_after_VII_Sunday_after_Pentecost|Our Lady of Mt. Carmel|-|1|sancti:07-16:4:w
+2026-07-17|4|g|Feria|Feria_VI_after_VII_Sunday_after_Pentecost|St. Alexis|-|1|sancti:07-17:4:w
+2026-07-18|3|r|Camillus de Lellis|Saturday_after_VII_Sunday_after_Pentecost|Ss. Symphorosa and sons|-|1|sancti:07-18cc:4:r
+2026-07-19|2|g|VIII Sunday after Pentecost|-|-|St. Vincent de Paul|1|-
+2026-07-20|3|r|St. Jerome Emiliani|Feria_II_after_VIII_Sunday_after_Pentecost|St. Margaret|-|1|sancti:07-20o:4:w
+2026-07-21|3|w|St. Laurence of Brindisi|Feria_III_after_VIII_Sunday_after_Pentecost|St. Praxedis Virginis|-|1|sancti:07-21:4:w
+2026-07-22|3|w|St. Mary Magdalene|Feria_IV_after_VIII_Sunday_after_Pentecost|-|-|1|-
+2026-07-23|3|w|St. Apollinaris|Feria_V_after_VIII_Sunday_after_Pentecost|S. Liborii|-|1|sancti:07-23cc:4:r
+2026-07-24|4|g|Feria|Feria_VI_after_VIII_Sunday_after_Pentecost|St. Christina|-|1|sancti:07-24r:4:r
+2026-07-25|2|r|St. James the Greater|Saturday_after_VIII_Sunday_after_Pentecost|St. Christopher|-|1|sancti:07-25cc:4:r
+2026-07-26|2|g|IX Sunday after Pentecost|-|St. Anne, Mother of the Blessed Virgin|-|1|sancti:07-26:2:w
+2026-07-27|4|g|Feria|Feria_II_after_IX_Sunday_after_Pentecost|St. Pantaleon|-|1|sancti:07-27:4:r
+2026-07-28|3|r|Sts. Nazarius & Celsus, St. Victor I & St. Innocent I|Feria_III_after_IX_Sunday_after_Pentecost|-|-|1|-
+2026-07-29|3|r|St. Martha|Feria_IV_after_IX_Sunday_after_Pentecost|Ss. Felicis, Simplicii, Faustini et Beatricis|-|1|sancti:07-29cc:4:r
+2026-07-30|4|g|Feria|Feria_V_after_IX_Sunday_after_Pentecost|Sts. Abdon & Sennen|-|1|sancti:07-30:4:r
+2026-07-31|3|w|St. Ignatius Loyola|Feria_VI_after_IX_Sunday_after_Pentecost|-|-|1|-
+2026-08-01|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IX_Sunday_after_Pentecost|Holy Machabees|-|1|sancti:08-01r:4:r
+2026-08-02|2|g|X Sunday after Pentecost|-|-|St. Alphonsus Liguori;St. Stephen I, Pope and Martyr|1|-
+2026-08-03|4|g|Feria|Feria_II_after_X_Sunday_after_Pentecost|-|-|1|-
+2026-08-04|3|w|St. Dominic|Feria_III_after_X_Sunday_after_Pentecost|-|-|1|-
+2026-08-05|3|w|Dedication of the Basilica of St. Mary Major|Feria_IV_after_X_Sunday_after_Pentecost|-|-|1|-
+2026-08-06|2|w|Transfiguration of Our Lord|Feria_V_after_X_Sunday_after_Pentecost|Pope Sixtus II, Felicissimus and Agapitus, Martyrs|-|1|sancti:08-06cc:4:r
+2026-08-07|3|w|St. Cajetan|Feria_VI_after_X_Sunday_after_Pentecost|St. Donatus|-|1|sancti:08-07o:4:r
+2026-08-08|3|w|St. John Mary Vianney|Saturday_after_X_Sunday_after_Pentecost|Ss. Cyriacus, Largus and Smaragdus, Martyrs|-|1|sancti:08-08c:4:r
+2026-08-09|3|r|Vigil of St. Lawrence|XI_Sunday_after_Pentecost|St. Romanus|-|1|sancti:08-09cc:4:r
+2026-08-10|2|r|St. Lawrence|Feria_II_after_XI_Sunday_after_Pentecost|-|-|1|-
+2026-08-11|4|g|Feria|Feria_III_after_XI_Sunday_after_Pentecost|Sts. Tiburtius & Susanna|-|1|sancti:08-11:4:r
+2026-08-12|3|w|St. Clare|Feria_IV_after_XI_Sunday_after_Pentecost|-|-|1|-
+2026-08-13|4|g|Feria|Feria_V_after_XI_Sunday_after_Pentecost|Sts. Hippolytus & Cassian|-|1|sancti:08-13:4:r
+2026-08-14|2|w|Vigil of the Assumption|Feria_VI_after_XI_Sunday_after_Pentecost|St. Eusebius|-|1|sancti:08-14cc:4:r
+2026-08-15|1|w|Assumption of the Blessed Virgin Mary|Saturday_after_XI_Sunday_after_Pentecost|-|-|1|-
+2026-08-16|2|g|XII Sunday after Pentecost|-|St. Joachim, Father of the Blessed Virgin|-|1|sancti:08-16:2:w
+2026-08-17|3|w|St. Hyacinth|Feria_II_after_XII_Sunday_after_Pentecost|-|-|1|-
+2026-08-18|4|g|Feria|Feria_III_after_XII_Sunday_after_Pentecost|St. Agapitus|-|1|sancti:08-18r:4:w
+2026-08-19|3|w|St. John Eudes|Feria_IV_after_XII_Sunday_after_Pentecost|-|-|1|-
+2026-08-20|3|w|St. Bernard of Clairvaux|Feria_V_after_XII_Sunday_after_Pentecost|-|-|1|-
+2026-08-21|3|w|St. Jane Frances de Chantal|Feria_VI_after_XII_Sunday_after_Pentecost|-|-|1|-
+2026-08-22|2|w|Immaculate Heart of Mary|Saturday_after_XII_Sunday_after_Pentecost|Sts. Timothy, Hippolytus and Symphorianus, Martyrs|-|1|sancti:08-22cc:4:r
+2026-08-23|2|g|XIII Sunday after Pentecost|-|-|St. Philip Benizi|1|-
+2026-08-24|2|r|St. Bartholomew|Feria_II_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2026-08-25|3|w|St. Louis IX|Feria_III_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2026-08-26|4|g|Feria|Feria_IV_after_XIII_Sunday_after_Pentecost|St. Zephyrinus|-|1|sancti:08-26:4:r
+2026-08-27|3|w|St. Joseph Calasance|Feria_V_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2026-08-28|3|r|St. Augustine|Feria_VI_after_XIII_Sunday_after_Pentecost|St. Hermes|-|1|sancti:08-28cc:4:r
+2026-08-29|3|r|Beheading of St. John the Baptist|Saturday_after_XIII_Sunday_after_Pentecost|St. Sabina|-|1|sancti:08-29cc:4:r
+2026-08-30|2|g|XIV Sunday after Pentecost|-|-|St. Rose of Lima;Sts. Felix and Adauctus|1|-
+2026-08-31|3|w|St. Raymond Nonnatus|Feria_II_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2026-09-01|4|g|Feria|Feria_III_after_XIV_Sunday_after_Pentecost|St. Giles;Twelve Holy Brothers, Martyrs|-|1|sancti:09-01:4:w;sancti:09-01cc:4:r
+2026-09-02|3|w|St. Stephen of Hungary|Feria_IV_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2026-09-03|3|w|St. Pius X|Feria_V_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2026-09-04|4|g|Feria|Feria_VI_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2026-09-05|3|w|St. Lawrence Justinian|Saturday_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2026-09-06|2|g|XV Sunday after Pentecost|-|-|-|1|-
+2026-09-07|4|g|Feria|Feria_II_after_XV_Sunday_after_Pentecost|-|-|1|-
+2026-09-08|2|w|Nativity of the Blessed Virgin Mary|Feria_III_after_XV_Sunday_after_Pentecost|S. Hadriani|-|1|sancti:09-08cc:4:r
+2026-09-09|4|g|Feria|Feria_IV_after_XV_Sunday_after_Pentecost|St. Gorgonius|-|1|sancti:09-09:4:r
+2026-09-10|3|w|St. Nicholas of Tolentino|Feria_V_after_XV_Sunday_after_Pentecost|-|-|1|-
+2026-09-11|4|g|Feria|Feria_VI_after_XV_Sunday_after_Pentecost|Sts. Protus & Hyacinth|-|1|sancti:09-11:4:r
+2026-09-12|3|w|Most Holy Name of Mary|Saturday_after_XV_Sunday_after_Pentecost|-|-|1|-
+2026-09-13|2|g|XVI Sunday after Pentecost|-|-|-|1|-
+2026-09-14|2|r|Exaltation of the Holy Cross|Feria_II_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2026-09-15|2|w|Seven Sorrows of the Blessed Virgin Mary|Feria_III_after_XVI_Sunday_after_Pentecost|S. Nicomedes|-|1|sancti:09-15cc:4:r
+2026-09-16|3|r|Sts. Cornelius & Cyprian|Feria_IV_after_XVI_Sunday_after_Pentecost|Sts. Euphemia, Lucy and Geminianus|-|1|sancti:09-16cc:4:r
+2026-09-17|4|g|Feria|Feria_V_after_XVI_Sunday_after_Pentecost|Stigmata of St. Francis|-|1|sancti:09-17:4:w
+2026-09-18|3|w|St. Joseph of Cupertino|Feria_VI_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2026-09-19|3|r|St. Januarius & Companions|Saturday_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2026-09-20|2|g|XVII Sunday after Pentecost|-|-|Sts. Eustace & Companions|1|-
+2026-09-21|2|r|St. Matthew|Feria_II_after_XVII_Sunday_after_Pentecost|-|-|1|-
+2026-09-22|3|w|St. Thomas of Villanova|Feria_III_after_XVII_Sunday_after_Pentecost|St. Maurice and Companions, Martyrs|-|1|sancti:09-22o:4:r
+2026-09-23|2|v|Ember Wednesday of September|-|St. Linus|St. Thecla|1|sancti:09-23:3:r
+2026-09-24|4|g|Feria|Feria_V_after_XVII_Sunday_after_Pentecost|Our Lady of Ransom|-|1|sancti:09-24:4:w
+2026-09-25|2|v|Ember Friday of September|-|-|-|1|-
+2026-09-26|2|v|Ember Saturday of September|-|Sts. Cyprian & Justina|-|1|sancti:09-26:4:r
+2026-09-27|2|g|XVIII Sunday after Pentecost|-|-|Sts. Cosmas & Damian|1|-
+2026-09-28|3|r|St. Wenceslaus|Feria_II_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2026-09-29|1|w|Dedication of St. Michael the Archangel|Feria_III_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2026-09-30|3|w|St. Jerome|Feria_IV_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2026-10-01|4|g|Feria|Feria_V_after_XVIII_Sunday_after_Pentecost|St. Remigius|-|1|sancti:10-01:4:w
+2026-10-02|3|w|Holy Guardian Angels|Feria_VI_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2026-10-03|3|w|St. Theresa of the Infant Jesus|Saturday_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2026-10-04|2|g|XIX Sunday after Pentecost|-|-|St. Francis of Assisi|1|-
+2026-10-05|4|g|Feria|Feria_II_after_XIX_Sunday_after_Pentecost|St. Placid & Companions|-|1|sancti:10-05:4:r
+2026-10-06|3|w|St. Bruno|Feria_III_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2026-10-07|2|w|Our Lady of the Rosary|Feria_IV_after_XIX_Sunday_after_Pentecost|St. Mark I|-|1|sancti:10-07t:4:r
+2026-10-08|3|w|St. Bridget of Sweden|Feria_V_after_XIX_Sunday_after_Pentecost|Ss. Sergio, Baccho, Marcello and Apulejo Martyrs|-|1|sancti:10-08c:4:r
+2026-10-09|3|w|St. John Leonardi|Feria_VI_after_XIX_Sunday_after_Pentecost|St. Dionysius and companions|-|1|sancti:10-09t:4:r
+2026-10-10|3|w|St. Francis Borgia|Saturday_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2026-10-11|2|g|XX Sunday after Pentecost|-|Maternity of the Blessed Virgin Mary|-|1|sancti:10-11:2:w
+2026-10-12|4|g|Feria|Feria_II_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-13|3|w|St. Edward|Feria_III_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-14|3|r|St. Callistus I|Feria_IV_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-15|3|w|St. Teresa of Avila|Feria_V_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-16|3|w|St. Hedwig|Feria_VI_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-17|3|w|St. Margaret Mary Alacoque|Saturday_after_XX_Sunday_after_Pentecost|-|-|1|-
+2026-10-18|2|g|XXI Sunday after Pentecost|-|St. Luke the Evangelist|-|1|sancti:10-18:2:r
+2026-10-19|3|w|St. Peter of Alcantara|Feria_II_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2026-10-20|3|w|St. John Cantius|Feria_III_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2026-10-21|4|g|Feria|Feria_IV_after_XXI_Sunday_after_Pentecost|St. Hilarion;St. Ursula and Companions|-|1|sancti:10-21:4:w;sancti:10-21cc:4:r
+2026-10-22|4|g|Feria|Feria_V_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2026-10-23|3|w|St. Anthony Mary Claret|Feria_VI_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2026-10-24|3|w|St. Raphael the Archangel|Saturday_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2026-10-25|1|w|Christ the King|XXII_Sunday_after_Pentecost|-|Sts. Chrysanthus & Daria|1|-
+2026-10-26|4|g|Feria|Feria_II_after_XXII_Sunday_after_Pentecost|St. Evaristus|-|1|sancti:10-26:4:r
+2026-10-27|4|g|Feria|Feria_III_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2026-10-28|2|r|Sts. Simon & Jude|Feria_IV_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2026-10-29|4|g|Feria|Feria_V_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2026-10-30|4|g|Feria|Feria_VI_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2026-10-31|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2026-11-01|1|w|All Saints|XXIII_Sunday_after_Pentecost|-|-|1|-
+2026-11-02|1|b|Commemoration of All Souls|Feria_II_after_XXIII_Sunday_after_Pentecost|-|-|3|-
+2026-11-03|4|g|Feria|Feria_III_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2026-11-04|3|w|St. Charles Borromeo|Feria_IV_after_XXIII_Sunday_after_Pentecost|Sts. Vitalis and Agricola, Martyrs|-|1|sancti:11-04cc:4:r
+2026-11-05|4|g|Feria|Feria_V_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2026-11-06|4|g|Feria|Feria_VI_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2026-11-07|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2026-11-08|2|g|V Sunday after Epiphany|-|-|Four Holy Crowned Martyrs|1|-
+2026-11-09|2|w|Dedication of the Archbasilica of Our Holy Savior|Feria_II_after_V_Sunday_after_Epiphany|St. Theodore|-|1|sancti:11-09cc:4:r
+2026-11-10|3|w|St. Andrew Avellino|Feria_III_after_V_Sunday_after_Epiphany|Sts. Tryphonis, Respicii, et Nymphae|-|1|sancti:11-10o:4:r
+2026-11-11|3|w|St. Martin of Tours|Feria_IV_after_V_Sunday_after_Epiphany|St. Menna|-|1|sancti:11-11cc:4:r
+2026-11-12|3|r|St. Martin I|Feria_V_after_V_Sunday_after_Epiphany|-|-|1|-
+2026-11-13|4|g|Feria|Feria_VI_after_V_Sunday_after_Epiphany|St. Didacus|-|1|sancti:11-13:4:w
+2026-11-14|3|w|St. Josaphat|Saturday_after_V_Sunday_after_Epiphany|-|-|1|-
+2026-11-15|2|g|VI Sunday after Epiphany|-|-|St. Albert the Great|1|-
+2026-11-16|3|w|St. Gertrude the Great|Feria_II_after_VI_Sunday_after_Epiphany|-|-|1|-
+2026-11-17|3|w|St. Gregory the Wonderworker|Feria_III_after_VI_Sunday_after_Epiphany|-|-|1|-
+2026-11-18|3|w|Dedication of the Basilicas of Sts. Peter & Paul|Feria_IV_after_VI_Sunday_after_Epiphany|-|-|1|-
+2026-11-19|3|w|St. Elizabeth of Hungary|Feria_V_after_VI_Sunday_after_Epiphany|St. Pontian|-|1|sancti:11-19o:4:r
+2026-11-20|3|w|St. Felix of Valois|Feria_VI_after_VI_Sunday_after_Epiphany|-|-|1|-
+2026-11-21|3|w|Presentation of the Blessed Virgin Mary|Saturday_after_VI_Sunday_after_Epiphany|-|-|1|-
+2026-11-22|2|g|XXIV Sunday after Pentecost|-|-|St. Cecilia|1|-
+2026-11-23|3|r|St. Clement I|Feria_II_after_XXIV_Sunday_after_Pentecost|St. Felicity|-|1|sancti:11-23cc:4:r
+2026-11-24|3|w|St. John of the Cross|Feria_III_after_XXIV_Sunday_after_Pentecost|St. Chrysogonus|-|1|sancti:11-24o:4:r
+2026-11-25|3|r|St. Catherine of Alexandria|Feria_IV_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2026-11-26|3|w|St. Sylvester|Feria_V_after_XXIV_Sunday_after_Pentecost|St. Peter of Alexandria|-|1|sancti:11-26t:4:r
+2026-11-27|4|g|Feria|Feria_VI_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2026-11-28|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2026-11-29|1|v|I Sunday of Advent|-|-|St. Saturninus|1|-
+2026-11-30|2|r|St. Andrew|Feria_II_after_I_Sunday_of_Advent|-|-|1|-
+2026-12-01|3|v|Feria III after I Sunday of Advent|-|-|-|1|-
+2026-12-02|3|r|St. Vivian|Feria_IV_after_I_Sunday_of_Advent|Feria IV after I Sunday of Advent|-|1|tempora:Adv1-3:3:v
+2026-12-03|3|w|St. Francis Xavier|Feria_V_after_I_Sunday_of_Advent|Feria V after I Sunday of Advent|-|1|tempora:Adv1-4:3:v
+2026-12-04|3|w|St. Peter Chrysologus|Feria_VI_after_I_Sunday_of_Advent|Feria VI after I Sunday of Advent|-|1|tempora:Adv1-5:3:v
+2026-12-05|3|v|Sabbato after I Sunday of Advent|-|St. Sabbas|-|1|sancti:12-05:4:w
+2026-12-06|1|v|II Sunday of Advent|-|-|St. Nicholas|1|-
+2026-12-07|3|w|St. Ambrose|Feria_II_after_II_Sunday_of_Advent|Feria II after II Sunday of Advent|-|1|tempora:Adv2-1:3:v
+2026-12-08|1|w|Immaculate Conception of the Blessed Virgin Mary|Feria_III_after_II_Sunday_of_Advent|-|-|1|-
+2026-12-09|3|v|Feria IV after II Sunday of Advent|-|-|-|1|-
+2026-12-10|3|v|Feria V after II Sunday of Advent|-|St. Melchiades|-|1|sancti:12-10o:4:r
+2026-12-11|3|w|St. Damasus I|Feria_VI_after_II_Sunday_of_Advent|Feria VI after II Sunday of Advent|-|1|tempora:Adv2-5:3:v
+2026-12-12|3|v|Sabbato after II Sunday of Advent|-|-|-|1|-
+2026-12-13|1|pv|III Sunday of Advent|-|-|St. Lucy|1|-
+2026-12-14|3|pv|Feria II after III Sunday of Advent|-|-|-|1|-
+2026-12-15|3|pv|Feria III after III Sunday of Advent|-|-|-|1|-
+2026-12-16|2|v|Ember Wednesday of Advent|-|St. Eusebius|-|1|sancti:12-16:3:r
+2026-12-17|2|pv|Feria V after III Sunday of Advent|-|-|-|1|-
+2026-12-18|2|v|Ember Friday of Advent|-|-|-|1|-
+2026-12-19|2|v|Ember Saturday of Advent|-|-|-|1|-
+2026-12-20|1|v|IV Sunday of Advent|-|-|-|1|-
+2026-12-21|2|r|St. Thomas|Feria_II_after_IV_Sunday_of_Advent|Feria II after IV Sunday of Advent|-|1|tempora:Adv4-1:2:v
+2026-12-22|2|v|Feria III after IV Sunday of Advent|-|-|-|1|-
+2026-12-23|2|v|Feria IV after IV Sunday of Advent|-|-|-|1|-
+2026-12-24|1|v|Vigil of Christmas|-|-|-|1|-
+2026-12-25|1|w|The Nativity of Our Lord|-|-|-|3|-
+2026-12-26|2|r|St. Stephen|-|For Octave of the Nativity|-|1|sancti:12-26c:4:w
+2026-12-27|2|w|Sunday in the Octave of Christmas|-|St. John the Evangelist|For Octave of the Nativity|1|sancti:12-27:2:w
+2026-12-28|2|r|Holy Innocents|-|For Octave of the Nativity|-|1|sancti:12-28c:4:w
+2026-12-29|2|w|Feria in the Octave of Christmas|-|St. Thomas Becket|-|1|sancti:12-29:4:r
+2026-12-30|2|w|Feria in the Octave of Christmas|-|-|-|1|-
+2026-12-31|2|w|Feria in the Octave of Christmas|-|St. Silvester|-|1|sancti:12-31:4:w
+2027-01-01|1|w|Octave Day of Christmas|-|-|-|1|-
+2027-01-02|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1|-
+2027-01-03|2|w|Holy Name of Jesus|-|-|-|1|-
+2027-01-04|4|w|Feria|-|-|-|1|-
+2027-01-05|4|w|Feria|-|St. Telesphorus Pope and Martyr|-|1|sancti:01-05:4:r
+2027-01-06|1|w|Epiphany of the Lord|-|-|-|1|-
+2027-01-07|4|w|Feria|-|-|-|1|-
+2027-01-08|4|w|Feria|-|-|-|1|-
+2027-01-09|4|w|II Mass of the B. V. M. – Vultum Tuum|-|-|-|1|-
+2027-01-10|2|w|The Holy Family: Jesus, Mary & Joseph|-|-|-|1|-
+2027-01-11|4|w|Feria|Feria_II_after_Epiphany|St. Hyginus Pope and Martyr|-|1|sancti:01-11cc:4:r
+2027-01-12|4|w|Feria|Feria_III_after_Epiphany|-|-|1|-
+2027-01-13|2|w|Commemoration of the Baptism of the Lord|Feria_IV_after_Epiphany|-|-|1|-
+2027-01-14|3|w|St. Hilary|Feria_V_after_Epiphany|S. Felicis|-|1|sancti:01-14cc:4:r
+2027-01-15|3|w|St. Paul, the First Hermit|Feria_VI_after_Epiphany|St. Maur, Abbot|-|1|sancti:01-15cc:4:w
+2027-01-16|3|r|St. Marcellus I|Saturday_after_Epiphany|-|-|1|-
+2027-01-17|2|g|II Sunday after Epiphany|-|-|St. Anthony|1|-
+2027-01-18|4|g|Feria|Feria_II_after_II_Sunday_after_Epiphany|St. Prisca|-|1|sancti:01-18r:4:w
+2027-01-19|4|g|Feria|Feria_III_after_II_Sunday_after_Epiphany|Sts. Marius, Martha, Audifax & Abachum;St. Canute, Martyr|-|1|sancti:01-19:4:r;sancti:01-19o:4:r
+2027-01-20|3|r|Sts. Fabian & Sebastian|Feria_IV_after_II_Sunday_after_Epiphany|-|-|1|-
+2027-01-21|3|r|St. Agnes|Feria_V_after_II_Sunday_after_Epiphany|-|-|1|-
+2027-01-22|3|r|Sts. Vincent & Anastasius|Feria_VI_after_II_Sunday_after_Epiphany|-|-|1|-
+2027-01-23|3|w|St. Raymond of Peñafort|Saturday_after_II_Sunday_after_Epiphany|St. Emerentiana|-|1|sancti:01-23o:4:r
+2027-01-24|2|v|Septuagesima Sunday|-|-|St. Timothy|1|-
+2027-01-25|3|w|Conversion of St. Paul|Feria_II_after_Septuagesima|St. Peter|-|1|sancti:01-25c:4:w
+2027-01-26|3|r|St. Polycarp|Feria_III_after_Septuagesima|-|-|1|-
+2027-01-27|3|w|St. John Chrysostom|Feria_IV_after_Septuagesima|-|-|1|-
+2027-01-28|3|w|St. Peter Nolasco|Feria_V_after_Septuagesima|St. Agnes|-|1|sancti:01-28t:4:r
+2027-01-29|3|w|St. Francis de Sales|Feria_VI_after_Septuagesima|-|-|1|-
+2027-01-30|3|r|St. Martina|Saturday_after_Septuagesima|-|-|1|-
+2027-01-31|2|v|Sexagesima Sunday|-|-|St. John Bosco|1|-
+2027-02-01|3|r|St. Ignatius of Antioch|Feria_II_after_Sexagesima|-|-|1|-
+2027-02-02|2|w|Purification of the Blessed Virgin Mary|Feria_III_after_Sexagesimæ|-|-|1|-
+2027-02-03|4|v|Feria|Feria_IV_after_Sexagesimæ|St. Blaise|-|1|sancti:02-03:4:r
+2027-02-04|3|w|St. Andrew Corsini|Feria_V_after_Sexagesimæ|-|-|1|-
+2027-02-05|3|r|St. Agatha|Feria_VI_after_Sexagesimæ|-|-|1|-
+2027-02-06|3|w|St. Titus|Saturday_after_Sexagesimæ|St. Dorothy|-|1|sancti:02-06o:4:r
+2027-02-07|2|v|Quinquagesima Sunday|-|-|St. Romuald|1|-
+2027-02-08|3|w|St. John of Matha|Feria_II_after_Quinquagesima|-|-|1|-
+2027-02-09|3|w|St. Cyril of Alexandria|Feria_III_after_Quinquagesima|St. Appollonia|-|1|sancti:02-09o:4:r
+2027-02-10|1|v|Ash Wednesday|-|-|St. Scholastica|1|-
+2027-02-11|3|v|Feria V after Ash Wednesday|-|Our Lady of Lourdes|-|1|sancti:02-11:3:w
+2027-02-12|3|v|Feria VI after Ash Wednesday|-|Seven Holy Servite Founders|-|1|sancti:02-12:3:w
+2027-02-13|3|v|Saturday after Ash Wednesday|-|-|-|1|-
+2027-02-14|1|v|I Sunday of Lent|-|-|St. Valentine|1|-
+2027-02-15|3|v|Feria II after the I Sunday of Lent|-|Sts. Faustinus & Jovita|-|1|sancti:02-15:4:r
+2027-02-16|3|v|Feria III after the I Sunday of Lent|-|-|-|1|-
+2027-02-17|2|v|Ember Wednesday of Lent|-|-|-|1|-
+2027-02-18|3|v|Feria V after the I Sunday of Lent|-|St. Simeon|-|1|sancti:02-18:4:r
+2027-02-19|2|v|Ember Friday of Lent|-|-|-|1|-
+2027-02-20|2|v|Ember Saturday of Lent|-|-|-|1|-
+2027-02-21|1|v|II Sunday of Lent|-|-|-|1|-
+2027-02-22|2|w|Chair of St. Peter|Feria_II_after_the_II_Sunday_of_Lent|St. Paul;Feria II after the II Sunday of Lent|-|1|sancti:02-22c:4:r;tempora:Quad2-1:3:v
+2027-02-23|3|v|Feria III after the II Sunday of Lent|-|St. Peter Damien|-|1|sancti:02-23r:3:w
+2027-02-24|2|r|St. Matthias|Feria_IV_after_the_II_Sunday_of_Lent|Feria IV after the II Sunday of Lent|-|1|tempora:Quad2-3:3:v
+2027-02-25|3|v|Feria V after the II Sunday of Lent|-|-|-|1|-
+2027-02-26|3|v|Feria VI after the II Sunday of Lent|-|-|-|1|-
+2027-02-27|3|v|Saturday after the II Sunday of Lent|-|St. Gabriel of Our Lady of Sorrows|-|1|sancti:02-27:3:w
+2027-02-28|1|v|III Sunday of Lent|-|-|-|1|-
+2027-03-01|3|v|Feria II after the III Sunday of Lent|-|-|-|1|-
+2027-03-02|3|v|Feria III after the III Sunday of Lent|-|-|-|1|-
+2027-03-03|3|v|Feria IV after the III Sunday of Lent|-|-|-|1|-
+2027-03-04|3|v|Feria V after the III Sunday of Lent|-|St. Casimir;St. Lucius|-|1|sancti:03-04:3:w;sancti:03-04cc:4:r
+2027-03-05|3|v|Feria VI after the III Sunday of Lent|-|-|-|1|-
+2027-03-06|3|v|Saturday after the III Sunday of Lent|-|Sts. Felicitas & Perpetua|-|1|sancti:03-06:3:r
+2027-03-07|1|pv|IV Sunday of Lent|-|-|St. Thomas Aquinas|1|-
+2027-03-08|3|v|Feria II after the IV Sunday of Lent|-|St. John of God|-|1|sancti:03-08:3:w
+2027-03-09|3|v|Feria III after the IV Sunday of Lent|-|St. Frances Rome|-|1|sancti:03-09:3:w
+2027-03-10|3|v|Feria IV after the IV Sunday of Lent|-|Forty Holy Martyrs of Sebaste|-|1|sancti:03-10:3:r
+2027-03-11|3|v|Feria V after the IV Sunday of Lent|-|-|-|1|-
+2027-03-12|3|v|Feria VI after the IV Sunday of Lent|-|St. Gregory the Great|-|1|sancti:03-12:3:w
+2027-03-13|3|v|Saturday after the IV Sunday of Lent|-|-|-|1|-
+2027-03-14|1|v|Passion Sunday|-|-|-|1|-
+2027-03-15|3|v|Feria II of Passion Week|-|-|-|1|-
+2027-03-16|3|v|Feria III of Passion Week|-|-|-|1|-
+2027-03-17|3|v|Feria IV of Passion Week|-|St. Patrick|-|1|sancti:03-17:3:w
+2027-03-18|3|v|Feria V of Passion Week|-|St. Cyril of Jerusalem|-|1|sancti:03-18:3:w
+2027-03-19|3|v|Feria VI of Passion Week|-|For Our Lady of the Seven Sorrows|St. Joseph, Spouse of the Bl. Virgin Mary|1|tempora:Quad5-5Feriac:4:w
+2027-03-20|3|v|Saturday of Passion Week|-|-|-|1|-
+2027-03-21|1|rv|Palm Sunday|-|-|St. Benedict|1|-
+2027-03-22|1|v|Feria II of Holy Week|-|-|-|1|-
+2027-03-23|1|v|Feria III of Holy Week|-|-|-|1|-
+2027-03-24|1|v|Feria IV of Holy Week|-|-|St. Gabriel the Archangel|1|-
+2027-03-25|1|w|Holy Thursday|-|-|Annunciation of the Blessed Virgin Mary|1|-
+2027-03-26|1|bv|Good Friday|-|-|-|1|-
+2027-03-27|1|vw|Holy Saturday|-|-|St. John Damascene|1|-
+2027-03-28|1|w|Easter Sunday|-|-|St. John of Capistrano|1|-
+2027-03-29|1|w|Monday in the Octave of Easter|-|-|-|1|-
+2027-03-30|1|w|Tuesday in the Octave of Easter|-|-|-|1|-
+2027-03-31|1|w|Wednesday in the Octave of Easter|-|-|-|1|-
+2027-04-01|1|w|Thursday in the Octave of Easter|-|-|-|1|-
+2027-04-02|1|w|Friday in the Octave of Easter|-|-|St. Francis of Paola|1|-
+2027-04-03|1|w|Saturday in the Octave of Easter|-|-|-|1|-
+2027-04-04|1|w|Low Sunday|-|-|St. Isidore of Seville|1|-
+2027-04-05|1|w|Annunciation of the Blessed Virgin Mary|Monday_after_I_Sunday_after_Easter|-|St. Vincent Ferrer|1|-
+2027-04-06|4|w|Feria|Tuesday_after_I_Sunday_after_Easter|-|-|1|-
+2027-04-07|4|w|Feria|Wednesday_after_I_Sunday_after_Easter|-|-|1|-
+2027-04-08|4|w|Feria|Thursday_after_I_Sunday_after_Easter|-|-|1|-
+2027-04-09|4|w|Feria|Friday_after_I_Sunday_after_Easter|-|-|1|-
+2027-04-10|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_I_Sunday_after_Easter|-|-|1|-
+2027-04-11|2|w|II Sunday after Easter|-|-|St. Leo the Great|1|-
+2027-04-12|4|w|Feria|Monday_after_II_Sunday_after_Easter|-|-|1|-
+2027-04-13|3|r|St. Hermenegild|Tuesday_after_II_Sunday_after_Easter|-|-|1|-
+2027-04-14|3|r|St. Justin|Wednesday_after_II_Sunday_after_Easter|Sts. Tiburtius, Valerian et Maximus, Martyrs|-|1|sancti:04-14t:4:r
+2027-04-15|4|w|Feria|Thursday_after_II_Sunday_after_Easter|-|-|1|-
+2027-04-16|4|w|Feria|Friday_after_II_Sunday_after_Easter|-|-|1|-
+2027-04-17|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_II_Sunday_after_Easter|St. Anicetus|-|1|sancti:04-17:4:r
+2027-04-18|2|w|III Sunday after Easter|-|-|-|1|-
+2027-04-19|4|w|Feria|Monday_after_III_Sunday_after_Easter|-|-|1|-
+2027-04-20|4|w|Feria|Tuesday_after_III_Sunday_after_Easter|-|-|1|-
+2027-04-21|3|w|St. Anselm|Wednesday_after_III_Sunday_after_Easter|-|-|1|-
+2027-04-22|3|r|Sts. Soter & Caius|Thursday_after_III_Sunday_after_Easter|-|-|1|-
+2027-04-23|4|w|Feria|Friday_after_III_Sunday_after_Easter|St. George|-|1|sancti:04-23:4:r
+2027-04-24|3|r|St. Fidelis of Sigmaringen|Saturday_after_III_Sunday_after_Easter|-|-|1|-
+2027-04-25|2|w|IV Sunday after Easter|-|St. Mark|Pro rogationibus|1|sancti:04-25:2:r
+2027-04-26|3|r|Sts. Cletus & Marcellinus|Monday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-04-27|3|w|St. Peter Canisius|Tuesday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-04-28|3|w|St. Paul of the Cross|Wednesday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-04-29|3|r|St. Peter of Verona|Thursday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-04-30|3|w|St. Catherine of Siena|Friday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-05-01|1|w|St. Joseph the Workman|Saturday_after_IV_Sunday_after_Easter|-|-|1|-
+2027-05-02|2|w|V Sunday after Easter|-|-|St. Athanasius|1|-
+2027-05-03|4|w|Feria|The_Minor_Litanies_–_Rogations|Sts. Alexander & Companions|-|1|sancti:05-03r:4:r
+2027-05-04|3|w|St. Monica|The_Minor_Litanies_–_Rogations|-|-|1|-
+2027-05-05|2|w|Vigil of the Ascension|-|St. Pius V|-|1|sancti:05-05:3:w
+2027-05-06|1|w|Ascension of the Lord|-|-|-|1|-
+2027-05-07|3|r|St. Stanislaus|Feria_VI_after_the_Ascension|-|-|1|-
+2027-05-08|4|w|IV Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_the_Ascension|-|-|1|-
+2027-05-09|2|w|Sunday after the Ascension|-|-|St. Gregory of Nazianzen|1|-
+2027-05-10|3|w|St. Antoninus|Feria_II_after_the_Ascension|St. Gordiano and Epimacho|-|1|sancti:05-10o:4:r
+2027-05-11|2|r|Sts. Philip & James|Feria_III_after_the_Ascension|-|-|1|-
+2027-05-12|3|r|Sts. Nereus, Achilleus, Domitilla, & Pancras|Feria_IV_after_the_Ascension|-|-|1|-
+2027-05-13|3|w|St. Robert Bellarmine|Feria_V_after_the_Ascension|-|-|1|-
+2027-05-14|4|w|Feria|Feria_VI_after_the_Ascension|St. Boniface|-|1|sancti:05-14:4:r
+2027-05-15|1|r|Saturday after the Ascension|-|-|St. John Baptist de la Salle|1|-
+2027-05-16|1|r|Pentecost Sunday|-|-|St. Ubaldus|1|-
+2027-05-17|1|r|Monday after Pentecost|-|-|St. Paschal Baylon|1|-
+2027-05-18|1|r|Tuesday after Pentecost|-|-|St. Venantius|1|-
+2027-05-19|1|r|Ember Wednesday of Pentecost|-|-|St. Peter Celestine;St. Pudentiana Virginis|1|-
+2027-05-20|1|r|Thursday after Pentecost|-|-|St. Bernardine of Siena|1|-
+2027-05-21|1|r|Ember Friday of Pentecost|-|-|-|1|-
+2027-05-22|1|r|Ember Saturday of Pentecost|-|-|-|1|-
+2027-05-23|1|w|Trinity Sunday|-|-|-|1|-
+2027-05-24|4|g|Feria|Feria_II_after_I_Sunday_after_Pentecost|-|-|1|-
+2027-05-25|3|w|St. Gregory VII|Feria_III_after_I_Sunday_after_Pentecost|St. Urban, Pope and Martyr|-|1|sancti:05-25o:4:r
+2027-05-26|3|w|St. Philip Neri|Feria_IV_after_I_Sunday_after_Pentecost|S. Eleutherius|-|1|sancti:05-26o:4:r
+2027-05-27|1|w|Corpus Christi|-|-|St. Bede the Venerable;St. John I|1|-
+2027-05-28|3|w|St. Augustine of Canterbury|Feria_V_after_I_Sunday_after_Pentecost|-|-|1|-
+2027-05-29|3|w|St. Mary Magdalene de Pazzi|Saturday_after_I_Sunday_after_Pentecost|-|-|1|-
+2027-05-30|2|g|II Sunday after Pentecost|-|-|St. Felix I|1|-
+2027-05-31|2|w|Queenship of the Blessed Virgin Mary|Feria_II_after_II_Sunday_after_Pentecost|St. Petronilla|-|1|sancti:05-31c:4:w
+2027-06-01|3|w|St. Angela Merici|Feria_III_after_II_Sunday_after_Pentecost|-|-|1|-
+2027-06-02|4|g|Feria|Feria_IV_after_II_Sunday_after_Pentecost|Sts. Marcellinus, Peter, & Erasmus|-|1|sancti:06-02:4:r
+2027-06-03|4|g|Feria|Feria_V_after_II_Sunday_after_Pentecost|-|-|1|-
+2027-06-04|1|w|Sacred Heart of Jesus|-|-|St. Francis Caracciolo|1|-
+2027-06-05|3|r|St. Boniface|Saturday_after_II_Sunday_after_Pentecost|-|-|1|-
+2027-06-06|2|g|III Sunday after Pentecost|-|-|St. Norbert|1|-
+2027-06-07|4|g|Feria|Feria_II_after_III_Sunday_after_Pentecost|-|-|1|-
+2027-06-08|4|g|Feria|Feria_III_after_III_Sunday_after_Pentecost|-|-|1|-
+2027-06-09|4|g|Feria|Feria_IV_after_III_Sunday_after_Pentecost|Sts. Primus & Felicianus|-|1|sancti:06-09:4:r
+2027-06-10|3|w|St. Margaret of Scotland|Feria_V_after_III_Sunday_after_Pentecost|-|-|1|-
+2027-06-11|3|r|St. Barnabas|Feria_VI_after_III_Sunday_after_Pentecost|-|-|1|-
+2027-06-12|3|r|St. John of San Fecundo|Saturday_after_III_Sunday_after_Pentecost|St. Basilidus|-|1|sancti:06-12o:4:r
+2027-06-13|2|g|IV Sunday after Pentecost|-|-|St. Anthony of Padua|1|-
+2027-06-14|3|w|St. Basil the Great|Feria_II_after_IV_Sunday_after_Pentecost|-|-|1|-
+2027-06-15|4|g|Feria|Feria_III_after_IV_Sunday_after_Pentecost|St. Vitus|-|1|sancti:06-15:4:w
+2027-06-16|4|g|Feria|Feria_IV_after_IV_Sunday_after_Pentecost|-|-|1|-
+2027-06-17|3|w|St. Gregory Barbarigo|Feria_V_after_IV_Sunday_after_Pentecost|-|-|1|-
+2027-06-18|3|r|St. Ephrem of Syria|Feria_VI_after_IV_Sunday_after_Pentecost|Ss. Marcus and Marcellianus|-|1|sancti:06-18t:4:r
+2027-06-19|3|r|St. Julia of Falconieri|Saturday_after_IV_Sunday_after_Pentecost|Sts. Gervasius and Protasius|-|1|sancti:06-19o:4:r
+2027-06-20|2|g|V Sunday after Pentecost|-|-|St. Silverius|1|-
+2027-06-21|3|w|St. Aloysius Gongzaga|Feria_II_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-22|3|w|St. Paulinus of Nola|Feria_III_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-23|2|v|Vigil of the Nativity of St. John the Baptist|Feria_IV_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-24|1|w|Nativity of St. John the Baptist|Feria_V_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-25|3|w|St. William|Feria_VI_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-26|3|r|Sts. John & Paul|Saturday_after_V_Sunday_after_Pentecost|-|-|1|-
+2027-06-27|2|g|VI Sunday after Pentecost|-|-|-|1|-
+2027-06-28|2|v|Vigil of Sts. Peter & Paul|Feria_II_after_VI_Sunday_after_Pentecost|-|-|1|-
+2027-06-29|1|r|Sts. Peter & Paul|Feria_III_after_VI_Sunday_after_Pentecost|-|-|1|-
+2027-06-30|3|r|In Commemoratione Sancti Pauli Apostoli|Feria_IV_after_VI_Sunday_after_Pentecost|-|-|1|-
+2027-07-01|1|r|The Precious Blood of Our Lord Jesus Christ|Feria_V_after_VI_Sunday_after_Pentecost|-|-|1|-
+2027-07-02|2|w|Visitation of the Blessed Virgin Mary|Feria_VI_after_VI_Sunday_after_Pentecost|SS. Processus and Martinian|-|1|sancti:07-02cc:4:r
+2027-07-03|3|r|St. Irenaeus|Saturday_after_VI_Sunday_after_Pentecost|-|-|1|-
+2027-07-04|2|g|VII Sunday after Pentecost|-|-|-|1|-
+2027-07-05|3|w|St. Anthony Mary Zaccariah|Feria_II_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-06|4|g|Feria|Feria_III_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-07|3|w|Sts. Cyril & Methodius|Feria_IV_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-08|3|w|St. Elizabeth of Portugal|Feria_V_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-09|4|g|Feria|Feria_VI_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-10|3|r|Seven Holy Brothers and Sts. Rufina & Secunda|Saturday_after_VII_Sunday_after_Pentecost|-|-|1|-
+2027-07-11|2|g|VIII Sunday after Pentecost|-|-|St. Pius I|1|-
+2027-07-12|3|r|St. John Gualbert|Feria_II_after_VIII_Sunday_after_Pentecost|Ss. Naboris et Felicis|-|1|sancti:07-12o:4:r
+2027-07-13|4|g|Feria|Feria_III_after_VIII_Sunday_after_Pentecost|-|-|1|-
+2027-07-14|3|w|St. Bonaventure|Feria_IV_after_VIII_Sunday_after_Pentecost|-|-|1|-
+2027-07-15|3|w|St. Henry the Emperor|Feria_V_after_VIII_Sunday_after_Pentecost|-|-|1|-
+2027-07-16|4|g|Feria|Feria_VI_after_VIII_Sunday_after_Pentecost|Our Lady of Mt. Carmel|-|1|sancti:07-16:4:w
+2027-07-17|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_VIII_Sunday_after_Pentecost|St. Alexis|-|1|sancti:07-17:4:w
+2027-07-18|2|g|IX Sunday after Pentecost|-|-|Camillus de Lellis;Ss. Symphorosa and sons|1|-
+2027-07-19|3|w|St. Vincent de Paul|Feria_II_after_IX_Sunday_after_Pentecost|-|-|1|-
+2027-07-20|3|r|St. Jerome Emiliani|Feria_III_after_IX_Sunday_after_Pentecost|St. Margaret|-|1|sancti:07-20o:4:w
+2027-07-21|3|w|St. Laurence of Brindisi|Feria_IV_after_IX_Sunday_after_Pentecost|St. Praxedis Virginis|-|1|sancti:07-21:4:w
+2027-07-22|3|w|St. Mary Magdalene|Feria_V_after_IX_Sunday_after_Pentecost|-|-|1|-
+2027-07-23|3|w|St. Apollinaris|Feria_VI_after_IX_Sunday_after_Pentecost|S. Liborii|-|1|sancti:07-23cc:4:r
+2027-07-24|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IX_Sunday_after_Pentecost|St. Christina|-|1|sancti:07-24r:4:r
+2027-07-25|2|g|X Sunday after Pentecost|-|St. James the Greater|St. Christopher|1|sancti:07-25:2:r
+2027-07-26|2|w|St. Anne, Mother of the Blessed Virgin|Feria_II_after_X_Sunday_after_Pentecost|-|-|1|-
+2027-07-27|4|g|Feria|Feria_III_after_X_Sunday_after_Pentecost|St. Pantaleon|-|1|sancti:07-27:4:r
+2027-07-28|3|r|Sts. Nazarius & Celsus, St. Victor I & St. Innocent I|Feria_IV_after_X_Sunday_after_Pentecost|-|-|1|-
+2027-07-29|3|r|St. Martha|Feria_V_after_X_Sunday_after_Pentecost|Ss. Felicis, Simplicii, Faustini et Beatricis|-|1|sancti:07-29cc:4:r
+2027-07-30|4|g|Feria|Feria_VI_after_X_Sunday_after_Pentecost|Sts. Abdon & Sennen|-|1|sancti:07-30:4:r
+2027-07-31|3|w|St. Ignatius Loyola|Saturday_after_X_Sunday_after_Pentecost|-|-|1|-
+2027-08-01|2|g|XI Sunday after Pentecost|-|-|Holy Machabees|1|-
+2027-08-02|3|r|St. Alphonsus Liguori|Feria_II_after_XI_Sunday_after_Pentecost|St. Stephen I, Pope and Martyr|-|1|sancti:08-02o:4:r
+2027-08-03|4|g|Feria|Feria_III_after_XI_Sunday_after_Pentecost|-|-|1|-
+2027-08-04|3|w|St. Dominic|Feria_IV_after_XI_Sunday_after_Pentecost|-|-|1|-
+2027-08-05|3|w|Dedication of the Basilica of St. Mary Major|Feria_V_after_XI_Sunday_after_Pentecost|-|-|1|-
+2027-08-06|2|w|Transfiguration of Our Lord|Feria_VI_after_XI_Sunday_after_Pentecost|Pope Sixtus II, Felicissimus and Agapitus, Martyrs|-|1|sancti:08-06cc:4:r
+2027-08-07|3|w|St. Cajetan|Saturday_after_XI_Sunday_after_Pentecost|St. Donatus|-|1|sancti:08-07o:4:r
+2027-08-08|2|g|XII Sunday after Pentecost|-|-|St. John Mary Vianney;Ss. Cyriacus, Largus and Smaragdus, Martyrs|1|-
+2027-08-09|3|r|Vigil of St. Lawrence|Feria_II_after_XII_Sunday_after_Pentecost|St. Romanus|-|1|sancti:08-09cc:4:r
+2027-08-10|2|r|St. Lawrence|Feria_III_after_XII_Sunday_after_Pentecost|-|-|1|-
+2027-08-11|4|g|Feria|Feria_IV_after_XII_Sunday_after_Pentecost|Sts. Tiburtius & Susanna|-|1|sancti:08-11:4:r
+2027-08-12|3|w|St. Clare|Feria_V_after_XII_Sunday_after_Pentecost|-|-|1|-
+2027-08-13|4|g|Feria|Feria_VI_after_XII_Sunday_after_Pentecost|Sts. Hippolytus & Cassian|-|1|sancti:08-13:4:r
+2027-08-14|2|w|Vigil of the Assumption|Saturday_after_XII_Sunday_after_Pentecost|St. Eusebius|-|1|sancti:08-14cc:4:r
+2027-08-15|1|w|Assumption of the Blessed Virgin Mary|XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-16|2|w|St. Joachim, Father of the Blessed Virgin|Feria_II_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-17|3|w|St. Hyacinth|Feria_III_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-18|4|g|Feria|Feria_IV_after_XIII_Sunday_after_Pentecost|St. Agapitus|-|1|sancti:08-18r:4:w
+2027-08-19|3|w|St. John Eudes|Feria_V_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-20|3|w|St. Bernard of Clairvaux|Feria_VI_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-21|3|w|St. Jane Frances de Chantal|Saturday_after_XIII_Sunday_after_Pentecost|-|-|1|-
+2027-08-22|2|g|XIV Sunday after Pentecost|-|Immaculate Heart of Mary|Sts. Timothy, Hippolytus and Symphorianus, Martyrs|1|sancti:08-22:2:w
+2027-08-23|3|w|St. Philip Benizi|Feria_II_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2027-08-24|2|r|St. Bartholomew|Feria_III_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2027-08-25|3|w|St. Louis IX|Feria_IV_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2027-08-26|4|g|Feria|Feria_V_after_XIV_Sunday_after_Pentecost|St. Zephyrinus|-|1|sancti:08-26:4:r
+2027-08-27|3|w|St. Joseph Calasance|Feria_VI_after_XIV_Sunday_after_Pentecost|-|-|1|-
+2027-08-28|3|r|St. Augustine|Saturday_after_XIV_Sunday_after_Pentecost|St. Hermes|-|1|sancti:08-28cc:4:r
+2027-08-29|2|g|XV Sunday after Pentecost|-|-|Beheading of St. John the Baptist;St. Sabina|1|-
+2027-08-30|3|r|St. Rose of Lima|Feria_II_after_XV_Sunday_after_Pentecost|Sts. Felix and Adauctus|-|1|sancti:08-30o:4:r
+2027-08-31|3|w|St. Raymond Nonnatus|Feria_III_after_XV_Sunday_after_Pentecost|-|-|1|-
+2027-09-01|4|g|Feria|Feria_IV_after_XV_Sunday_after_Pentecost|St. Giles;Twelve Holy Brothers, Martyrs|-|1|sancti:09-01:4:w;sancti:09-01cc:4:r
+2027-09-02|3|w|St. Stephen of Hungary|Feria_V_after_XV_Sunday_after_Pentecost|-|-|1|-
+2027-09-03|3|w|St. Pius X|Feria_VI_after_XV_Sunday_after_Pentecost|-|-|1|-
+2027-09-04|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XV_Sunday_after_Pentecost|-|-|1|-
+2027-09-05|2|g|XVI Sunday after Pentecost|-|-|St. Lawrence Justinian|1|-
+2027-09-06|4|g|Feria|Feria_II_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2027-09-07|4|g|Feria|Feria_III_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2027-09-08|2|w|Nativity of the Blessed Virgin Mary|Feria_IV_after_XVI_Sunday_after_Pentecost|S. Hadriani|-|1|sancti:09-08cc:4:r
+2027-09-09|4|g|Feria|Feria_V_after_XVI_Sunday_after_Pentecost|St. Gorgonius|-|1|sancti:09-09:4:r
+2027-09-10|3|w|St. Nicholas of Tolentino|Feria_VI_after_XVI_Sunday_after_Pentecost|-|-|1|-
+2027-09-11|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XVI_Sunday_after_Pentecost|Sts. Protus & Hyacinth|-|1|sancti:09-11:4:r
+2027-09-12|2|g|XVII Sunday after Pentecost|-|-|Most Holy Name of Mary|1|-
+2027-09-13|4|g|Feria|Feria_II_after_XVII_Sunday_after_Pentecost|-|-|1|-
+2027-09-14|2|r|Exaltation of the Holy Cross|Feria_III_after_XVII_Sunday_after_Pentecost|-|-|1|-
+2027-09-15|2|w|Seven Sorrows of the Blessed Virgin Mary|Feria_IV_after_XVII_Sunday_after_Pentecost|S. Nicomedes|-|1|sancti:09-15cc:4:r
+2027-09-16|3|r|Sts. Cornelius & Cyprian|Feria_V_after_XVII_Sunday_after_Pentecost|Sts. Euphemia, Lucy and Geminianus|-|1|sancti:09-16cc:4:r
+2027-09-17|4|g|Feria|Feria_VI_after_XVII_Sunday_after_Pentecost|Stigmata of St. Francis|-|1|sancti:09-17:4:w
+2027-09-18|3|w|St. Joseph of Cupertino|Saturday_after_XVII_Sunday_after_Pentecost|-|-|1|-
+2027-09-19|2|g|XVIII Sunday after Pentecost|-|-|St. Januarius & Companions|1|-
+2027-09-20|4|g|Feria|Feria_II_after_XVIII_Sunday_after_Pentecost|Sts. Eustace & Companions|-|1|sancti:09-20:4:r
+2027-09-21|2|r|St. Matthew|Feria_III_after_XVIII_Sunday_after_Pentecost|-|-|1|-
+2027-09-22|2|v|Ember Wednesday of September|-|St. Thomas of Villanova|St. Maurice and Companions, Martyrs|1|sancti:09-22:3:w
+2027-09-23|3|r|St. Linus|Feria_V_after_XVIII_Sunday_after_Pentecost|St. Thecla|-|1|sancti:09-23cc:4:r
+2027-09-24|2|v|Ember Friday of September|-|Our Lady of Ransom|-|1|sancti:09-24:4:w
+2027-09-25|2|v|Ember Saturday of September|-|-|-|1|-
+2027-09-26|2|g|XIX Sunday after Pentecost|-|-|Sts. Cyprian & Justina|1|-
+2027-09-27|3|r|Sts. Cosmas & Damian|Feria_II_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2027-09-28|3|r|St. Wenceslaus|Feria_III_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2027-09-29|1|w|Dedication of St. Michael the Archangel|Feria_IV_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2027-09-30|3|w|St. Jerome|Feria_V_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2027-10-01|4|g|Feria|Feria_VI_after_XIX_Sunday_after_Pentecost|St. Remigius|-|1|sancti:10-01:4:w
+2027-10-02|3|w|Holy Guardian Angels|Saturday_after_XIX_Sunday_after_Pentecost|-|-|1|-
+2027-10-03|2|g|XX Sunday after Pentecost|-|-|St. Theresa of the Infant Jesus|1|-
+2027-10-04|3|w|St. Francis of Assisi|Feria_II_after_XX_Sunday_after_Pentecost|-|-|1|-
+2027-10-05|4|g|Feria|Feria_III_after_XX_Sunday_after_Pentecost|St. Placid & Companions|-|1|sancti:10-05:4:r
+2027-10-06|3|w|St. Bruno|Feria_IV_after_XX_Sunday_after_Pentecost|-|-|1|-
+2027-10-07|2|w|Our Lady of the Rosary|Feria_V_after_XX_Sunday_after_Pentecost|St. Mark I|-|1|sancti:10-07t:4:r
+2027-10-08|3|w|St. Bridget of Sweden|Feria_VI_after_XX_Sunday_after_Pentecost|Ss. Sergio, Baccho, Marcello and Apulejo Martyrs|-|1|sancti:10-08c:4:r
+2027-10-09|3|w|St. John Leonardi|Saturday_after_XX_Sunday_after_Pentecost|St. Dionysius and companions|-|1|sancti:10-09t:4:r
+2027-10-10|2|g|XXI Sunday after Pentecost|-|-|St. Francis Borgia|1|-
+2027-10-11|2|w|Maternity of the Blessed Virgin Mary|Feria_II_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-12|4|g|Feria|Feria_III_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-13|3|w|St. Edward|Feria_IV_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-14|3|r|St. Callistus I|Feria_V_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-15|3|w|St. Teresa of Avila|Feria_VI_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-16|3|w|St. Hedwig|Saturday_after_XXI_Sunday_after_Pentecost|-|-|1|-
+2027-10-17|2|g|XXII Sunday after Pentecost|-|-|St. Margaret Mary Alacoque|1|-
+2027-10-18|2|r|St. Luke the Evangelist|Feria_II_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2027-10-19|3|w|St. Peter of Alcantara|Feria_III_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2027-10-20|3|w|St. John Cantius|Feria_IV_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2027-10-21|4|g|Feria|Feria_V_after_XXII_Sunday_after_Pentecost|St. Hilarion;St. Ursula and Companions|-|1|sancti:10-21:4:w;sancti:10-21cc:4:r
+2027-10-22|4|g|Feria|Feria_VI_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2027-10-23|3|w|St. Anthony Mary Claret|Saturday_after_XXII_Sunday_after_Pentecost|-|-|1|-
+2027-10-24|2|g|XXIII Sunday after Pentecost|-|-|St. Raphael the Archangel|1|-
+2027-10-25|4|g|Feria|Feria_II_after_XXIII_Sunday_after_Pentecost|Sts. Chrysanthus & Daria|-|1|sancti:10-25:4:r
+2027-10-26|4|g|Feria|Feria_III_after_XXIII_Sunday_after_Pentecost|St. Evaristus|-|1|sancti:10-26:4:r
+2027-10-27|4|g|Feria|Feria_IV_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2027-10-28|2|r|Sts. Simon & Jude|Feria_V_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2027-10-29|4|g|Feria|Feria_VI_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2027-10-30|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIII_Sunday_after_Pentecost|-|-|1|-
+2027-10-31|1|w|Christ the King|IV_Sunday_after_Epiphany|-|-|1|-
+2027-11-01|1|w|All Saints|Feria_II_after_IV_Sunday_after_Epiphany|-|-|1|-
+2027-11-02|1|b|Commemoration of All Souls|Feria_III_after_IV_Sunday_after_Epiphany|-|-|3|-
+2027-11-03|4|g|Feria|Feria_IV_after_IV_Sunday_after_Epiphany|-|-|1|-
+2027-11-04|3|w|St. Charles Borromeo|Feria_V_after_IV_Sunday_after_Epiphany|Sts. Vitalis and Agricola, Martyrs|-|1|sancti:11-04cc:4:r
+2027-11-05|4|g|Feria|Feria_VI_after_IV_Sunday_after_Epiphany|-|-|1|-
+2027-11-06|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_IV_Sunday_after_Epiphany|-|-|1|-
+2027-11-07|2|g|V Sunday after Epiphany|-|-|-|1|-
+2027-11-08|4|g|Feria|Feria_II_after_V_Sunday_after_Epiphany|Four Holy Crowned Martyrs|-|1|sancti:11-08r:4:r
+2027-11-09|2|w|Dedication of the Archbasilica of Our Holy Savior|Feria_III_after_V_Sunday_after_Epiphany|St. Theodore|-|1|sancti:11-09cc:4:r
+2027-11-10|3|w|St. Andrew Avellino|Feria_IV_after_V_Sunday_after_Epiphany|Sts. Tryphonis, Respicii, et Nymphae|-|1|sancti:11-10o:4:r
+2027-11-11|3|w|St. Martin of Tours|Feria_V_after_V_Sunday_after_Epiphany|St. Menna|-|1|sancti:11-11cc:4:r
+2027-11-12|3|r|St. Martin I|Feria_VI_after_V_Sunday_after_Epiphany|-|-|1|-
+2027-11-13|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_V_Sunday_after_Epiphany|St. Didacus|-|1|sancti:11-13:4:w
+2027-11-14|2|g|VI Sunday after Epiphany|-|-|St. Josaphat|1|-
+2027-11-15|3|w|St. Albert the Great|Feria_II_after_VI_Sunday_after_Epiphany|-|-|1|-
+2027-11-16|3|w|St. Gertrude the Great|Feria_III_after_VI_Sunday_after_Epiphany|-|-|1|-
+2027-11-17|3|w|St. Gregory the Wonderworker|Feria_IV_after_VI_Sunday_after_Epiphany|-|-|1|-
+2027-11-18|3|w|Dedication of the Basilicas of Sts. Peter & Paul|Feria_V_after_VI_Sunday_after_Epiphany|-|-|1|-
+2027-11-19|3|w|St. Elizabeth of Hungary|Feria_VI_after_VI_Sunday_after_Epiphany|St. Pontian|-|1|sancti:11-19o:4:r
+2027-11-20|3|w|St. Felix of Valois|Saturday_after_VI_Sunday_after_Epiphany|-|-|1|-
+2027-11-21|2|g|XXIV Sunday after Pentecost|-|-|Presentation of the Blessed Virgin Mary|1|-
+2027-11-22|3|r|St. Cecilia|Feria_II_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2027-11-23|3|r|St. Clement I|Feria_III_after_XXIV_Sunday_after_Pentecost|St. Felicity|-|1|sancti:11-23cc:4:r
+2027-11-24|3|w|St. John of the Cross|Feria_IV_after_XXIV_Sunday_after_Pentecost|St. Chrysogonus|-|1|sancti:11-24o:4:r
+2027-11-25|3|r|St. Catherine of Alexandria|Feria_V_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2027-11-26|3|w|St. Sylvester|Feria_VI_after_XXIV_Sunday_after_Pentecost|St. Peter of Alexandria|-|1|sancti:11-26t:4:r
+2027-11-27|4|w|V Mass of the B. V. M. – Salve, Sancta Parens|Saturday_after_XXIV_Sunday_after_Pentecost|-|-|1|-
+2027-11-28|1|v|I Sunday of Advent|-|-|-|1|-
+2027-11-29|3|v|Feria II after I Sunday of Advent|-|St. Saturninus|-|1|sancti:11-29r:4:r
+2027-11-30|2|r|St. Andrew|Feria_III_after_I_Sunday_of_Advent|-|-|1|-
+2027-12-01|3|v|Feria IV after I Sunday of Advent|-|-|-|1|-
+2027-12-02|3|r|St. Vivian|Feria_V_after_I_Sunday_of_Advent|Feria V after I Sunday of Advent|-|1|tempora:Adv1-4:3:v
+2027-12-03|3|w|St. Francis Xavier|Feria_VI_after_I_Sunday_of_Advent|Feria VI after I Sunday of Advent|-|1|tempora:Adv1-5:3:v
+2027-12-04|3|w|St. Peter Chrysologus|Sabbato_after_I_Sunday_of_Advent|Sabbato after I Sunday of Advent|-|1|tempora:Adv1-6:3:v
+2027-12-05|1|v|II Sunday of Advent|-|-|St. Sabbas|1|-
+2027-12-06|3|w|St. Nicholas|Feria_II_after_II_Sunday_of_Advent|Feria II after II Sunday of Advent|-|1|tempora:Adv2-1:3:v
+2027-12-07|3|w|St. Ambrose|Feria_III_after_II_Sunday_of_Advent|Feria III after II Sunday of Advent|-|1|tempora:Adv2-2:3:v
+2027-12-08|1|w|Immaculate Conception of the Blessed Virgin Mary|Feria_IV_after_II_Sunday_of_Advent|-|-|1|-
+2027-12-09|3|v|Feria V after II Sunday of Advent|-|-|-|1|-
+2027-12-10|3|v|Feria VI after II Sunday of Advent|-|St. Melchiades|-|1|sancti:12-10o:4:r
+2027-12-11|3|w|St. Damasus I|Sabbato_after_II_Sunday_of_Advent|Sabbato after II Sunday of Advent|-|1|tempora:Adv2-6:3:v
+2027-12-12|1|pv|III Sunday of Advent|-|-|-|1|-
+2027-12-13|3|r|St. Lucy|Feria_II_after_III_Sunday_of_Advent|Feria II after III Sunday of Advent|-|1|tempora:Adv3-1:3:v
+2027-12-14|3|pv|Feria III after III Sunday of Advent|-|-|-|1|-
+2027-12-15|2|v|Ember Wednesday of Advent|-|-|-|1|-
+2027-12-16|3|r|St. Eusebius|Feria_V_after_III_Sunday_of_Advent|Feria V after III Sunday of Advent|-|1|tempora:Adv3-4:3:v
+2027-12-17|2|v|Ember Friday of Advent|-|-|-|1|-
+2027-12-18|2|v|Ember Saturday of Advent|-|-|-|1|-
+2027-12-19|1|v|IV Sunday of Advent|-|-|-|1|-
+2027-12-20|2|v|Feria II after IV Sunday of Advent|-|-|-|1|-
+2027-12-21|2|r|St. Thomas|Feria_III_after_IV_Sunday_of_Advent|Feria III after IV Sunday of Advent|-|1|tempora:Adv4-2:2:v
+2027-12-22|2|v|Feria IV after IV Sunday of Advent|-|-|-|1|-
+2027-12-23|2|v|Feria V after IV Sunday of Advent|-|-|-|1|-
+2027-12-24|1|v|Vigil of Christmas|-|-|-|1|-
+2027-12-25|1|w|The Nativity of Our Lord|-|-|-|3|-
+2027-12-26|2|w|Sunday in the Octave of Christmas|-|St. Stephen|For Octave of the Nativity|1|sancti:12-26:2:r
+2027-12-27|2|w|St. John the Evangelist|-|For Octave of the Nativity|-|1|sancti:12-27c:4:w
+2027-12-28|2|r|Holy Innocents|-|For Octave of the Nativity|-|1|sancti:12-28c:4:w
+2027-12-29|2|w|Feria in the Octave of Christmas|-|St. Thomas Becket|-|1|sancti:12-29:4:r
+2027-12-30|2|w|Feria in the Octave of Christmas|-|-|-|1|-
+2027-12-31|2|w|Feria in the Octave of Christmas|-|St. Silvester|-|1|sancti:12-31:4:w
diff --git a/test/test_calendar.ml b/test/test_calendar.ml
index 505994e..93cd0bb 100644
--- a/test/test_calendar.ml
+++ b/test/test_calendar.ml
@@ -82,7 +82,10 @@ module Fixture = struct
test below a genuine Precedence-native omission (distinct from a
deferred one) to exercise. *)
let rules : (season, rank) P.rules =
- { P.band; disposition; admit = (fun ~observed:_ cs -> List.filteri (fun i _ -> i < 1) cs) }
+ { P.band; disposition;
+ admit =
+ (fun ~observed:_ ~temporal:_ cs ->
+ List.filteri (fun i _ -> i < 1) cs |> List.map (fun (c, p, (_ : int)) -> (c, p))) }
(* RG 96, generic form: search forward from the day after [origin] for the
first day whose occupant is not "blocking" -- in this synthetic
diff --git a/test/test_differential.ml b/test/test_differential.ml
index a9bdb91..e12cd9a 100644
--- a/test/test_differential.ml
+++ b/test/test_differential.ml
@@ -450,6 +450,16 @@ let layer_c_reason (l : row) (c : row) diffs =
&& subset diffs [ Slug_f; Rank; Colour_f ]
then Some "C10"
else if String.equal c.slug "ef-passiontide-2-thursday" && diffs = [ Colour_f ] then Some "C11"
+ (* RG16(a) task, fix round 1 (CRITICAL finding): a C12 entry briefly lived
+ here, allow-listing 2 February on a Sunday against lectio, when
+ `data/ef/adjustments.sexp` retagged the Purification `Bvm`. REVERTED --
+ the user has ruled: follow the oracle (register §6.0 has the full
+ account). The Purification is `Lord` again, colitur observes it
+ outright on those six 2-February Sundays, matching lectio's own
+ `class = lord` exactly -- no divergence to allow-list. Left
+ unimplemented here deliberately, not merely absent by oversight: this
+ comment is the record that C12 existed and was removed, should a
+ future reader wonder why the numbering skips it. *)
else None
(* ---------------------------------------------------------------------- *)
diff --git a/test/test_golden.ml b/test/test_golden.ml
index 945abe5..fb3cff4 100644
--- a/test/test_golden.ml
+++ b/test/test_golden.ml
@@ -482,6 +482,104 @@ let test_ii_class_sunday_admits_only_ii_class_commemoration () =
colour=green comms=[] in=- out=[]"
(describe d2026)
+(* ------------------------------------------------------------------ *)
+(* RG 16(a) (register §6.0, Caput III "De Dominicis", primary text quoted in
+ this task's own report): "festum Domini I aut II classis, in dominica II
+ classis occurrens, ... de dominica, proinde, nulla fit commemoratio" -- a
+ Feast of the Lord, I or II class, impeding a II-class Sunday, takes the
+ Sunday's own place with no commemoration of the Sunday at all, unlike
+ every OTHER impeded II-class Sunday (RG 109(a)/RG 111(b), the
+ [test_ii_class_sunday_admits_only_ii_class_commemoration] pin above).
+ Two real dates, both directions, exactly the pair the task brief asks
+ for. *)
+(* ------------------------------------------------------------------ *)
+
+(* 2028-08-06: the Transfiguration (6 Aug, II class, calendarium "IN
+ TRANSFIGURATIONE D. N. I. C.") falls on an ordinary Time-after-Pentecost
+ Sunday. `date -d 2028-08-06 +%A` = Sunday, independently confirmed. Also
+ the exact date register §6.0's own reproduction names as a live instance
+ of the bug this pin closes -- before this fix `colitur day` admitted
+ "+ef-time-after-pentecost-sunday-9" here.
+
+ CORRECTED, fix round 1 (IMPORTANT finding, item 2): this pin used to
+ expect Pope Sixtus II et al. (6 August's own unrelated Class3 saint,
+ Commemoration_only) admitted as an ordinary commemoration in the freed
+ slot -- promoted from `colitur day`'s own actual output without
+ consulting either the primary text or the oracle first (the exact
+ vacuous-pin flavour the review caught, and this file's own header warns
+ against). Re-derived properly this time:
+ - PRIMARY TEXT: RG 16(a) itself says the winning Feast of the Lord holds
+ the Sunday's place cum omnibus iuribus et privilegiis -- WITH ALL the
+ Sunday's own rights and privileges. RG 111(b) is one of those: in
+ dominicis II classis, una tantum admittitur commemoratio, SCILICET DE
+ FESTO II CLASSIS -- a Sunday's own slot is reserved for a Class2
+ candidate specifically. The day is still a dominica II classis for
+ this purpose even though the Transfiguration, not the Sunday, is
+ [observed] -- so Sixtus (Class3) has no standing for the slot at all,
+ the same as on any other II-class Sunday (contrast
+ [test_ii_class_sunday_admits_only_ii_class_commemoration] above,
+ romanus, Class3, excluded the identical way on an ORDINARY II-class
+ Sunday).
+ - ORACLE, independently fetched (missalemeum's own /api/v5/calendar
+ JSON, not the small-model webpage summary, which proved unreliable for
+ this exact question): 2023-08-06 (a Sunday) -- title Transfiguration of
+ Our Lord, commemorations empty, displaced Pope Sixtus II, Felicissimus
+ and Agapitus, Martyrs -- Sixtus displaced, not commemorated. Control,
+ 2026-08-06 (a Thursday, no Sunday collision) -- Sixtus present in
+ commemorations. Being a Sunday is exactly what excludes him.
+
+ Deliberately NOT a bare "comms=[]" pin (this project's own catalogued
+ vacuity flavour: a count/emptiness assertion that would pass even if
+ nothing had ever been offered): [omitted_has] first proves the Sunday
+ really WAS a candidate that reached [disposition] and was actively
+ excluded, not merely never constructed. *)
+let test_rg16a_lord_feast_no_sunday_commemoration_2028 () =
+ let d = fetch 2028 8 6 in
+ Alcotest.(check bool)
+ "2028-08-06: the impeded Sunday is in [omitted], proving RG16(a) actively fired (not merely never offered)"
+ true
+ (omitted_has d "ef-time-after-pentecost-sunday-9");
+ Alcotest.(check string)
+ "2028-08-06: the Transfiguration observed; NO commemoration at all -- RG16(a)'s own \"cum omnibus iuribus \
+ et privilegiis\" keeps the day a dominica II classis for RG111(b), so Sixtus (Class3) has no standing \
+ either, oracle-confirmed"
+ "2028-08-06 sunday season=time-after-pentecost week=9 slug=transfiguration-of-our-lord rank=class-2 \
+ colour=white comms=[] in=- out=[]"
+ (describe d)
+
+(* 2025-02-02, the other real instance of the SAME pattern -- not a
+ contrasting second direction, per this task's fix round 1 (CRITICAL
+ finding, item 1, reverted; see register §6.0 for the full account).
+
+ The Purification (2 Feb, calendarium "IN PURIFICATIONE B. MARIAE VIRG.")
+ stays [subject = Lord] -- the user has ruled: follow the oracle.
+ missalemeum treats it exactly as RG 16(a)'s own "festum Domini" case
+ (independently fetched, `/api/v5/calendar` JSON): 2020-02-02 (a Sunday)
+ -- `{"title":"Purification of the Blessed Virgin Mary","tags":["IV
+ Sunday after Epiphany"],...,"commemorations":[],"displaced":[]}` -- the
+ Sunday named only as a TAG (the underlying temporal placement), not
+ commemorated at all; matches 2014-02-02 exactly. Contrast, the SAME
+ oracle on an ordinary Marian feast (2019-09-08, the Nativity of the
+ BVM): `{"title":"XIII Sunday after Pentecost",...,"commemorations":
+ [{"title":"Nativity of the Blessed Virgin Mary",...}],...}` -- the
+ Sunday observed, the feast merely commemorated, the OPPOSITE pattern --
+ proving missalemeum does not treat every Marian feast this way, only the
+ Purification specifically. `date -d 2025-02-02 +%A` = Sunday,
+ independently confirmed.
+
+ Unlike 2028-08-06, no second sanctoral candidate exists on 2 February
+ (data/ef/sanctoral.sexp has exactly one 2 February entry) -- a genuinely
+ clean "comms=[]" case, complementing the pair above rather than
+ duplicating it. *)
+let test_purification_on_a_sunday_2025 () =
+ check
+ ~msg:
+ "2025-02-02: the Purification observed (subject Lord, unretagged -- the oracle's own treatment); NO \
+ commemoration of the Sunday, oracle-confirmed"
+ 2025 2 2
+ "2025-02-02 sunday season=time-after-epiphany week=4 slug=purification-of-the-blessed-virgin-mary \
+ rank=class-2 colour=white comms=[] in=- out=[]"
+
let suite =
( "golden pins (known-tricky years)",
[ Alcotest.test_case "Easter extreme: 1598 earliest (22 Mar, Gauss-verified)" `Quick
@@ -507,5 +605,12 @@ let suite =
test_ember_ferias_commemorated_when_impeded;
Alcotest.test_case "IV-class ferias never commemorated (2026)" `Quick test_iv_class_ferias_never_commemorated;
Alcotest.test_case "RG111(b): a II-class Sunday admits only a de-festo-II-classis commemoration (2009, 2026)"
- `Quick test_ii_class_sunday_admits_only_ii_class_commemoration
+ `Quick test_ii_class_sunday_admits_only_ii_class_commemoration;
+ Alcotest.test_case
+ "RG16(a): a Feast of the Lord leaves the impeded Sunday with NO commemoration at all, not even an \
+ unrelated saint's own (2028-08-06, rubric + oracle)"
+ `Quick test_rg16a_lord_feast_no_sunday_commemoration_2028;
+ Alcotest.test_case
+ "RG16(a), the Purification (oracle-ruled): observed outright, the Sunday not commemorated (2025-02-02)"
+ `Quick test_purification_on_a_sunday_2025
] )
diff --git a/test/test_oracle.ml b/test/test_oracle.ml
index ac8d95d..2624664 100644
--- a/test/test_oracle.ml
+++ b/test/test_oracle.ml
@@ -14,11 +14,10 @@
that file's own limit 1). missalemeum is INDEPENDENT of colitur's
bootstrap chain, and its JSON carries a real admitted-commemorations
array (its own RG 111-shaped selection, not lectio's rejects) -- so this
- file compares THREE axes the lectio differential cannot touch at all:
- rank, colour (as SET membership, see below), and commemoration presence/
- count. Slug IDENTITY is deliberately NOT compared (the brief: needs a
- title->slug mapping, which is the data audit's business -- see the task
- report -- not this automated comparator's).
+ file compares axes the lectio differential cannot touch at all: rank,
+ colour (as SET membership, see below), commemoration presence, count,
+ and (CORRECTED 2026-08-12, Task B, branch ef-rg16a -- see below) IDENTITY
+ -- WHICH commemoration is admitted, not only how many.
*** THE FIXTURE'S OWN SHAPE (fixtures/missalemeum-ef-2026-2027.txt,
fixtures/missalemeum-ef-2026-2027.provenance, tools/
@@ -29,7 +28,59 @@
between the id-embedded rank and info.rank itself (task brief's own
premise was wrong here; the brief's extraction note has been corrected).
This file, like the extraction script, reads ONLY info.rank and
- info.colors, never parses anything out of info.id.
+ info.colors for the DAY's own rank/colour, never parses anything out of
+ info.id for that purpose.
+
+ *** COMMEMORATION IDENTITY (added 2026-08-12, Task B, branch ef-rg16a)
+ -- CORRECTING the previous header's own "deliberately NOT compared"
+ claim ***
+
+ The gap this correction closes: layer 4 used to compare commemoration
+ PRESENCE and List.length ONLY -- cardinality, never identity. A reviewer
+ proved this was vacuous by reversing admit's own dignity/precedence sort
+ (Rite_ef.Precedence_ef, so the engine admits the WORST candidate, an
+ outright RG 111 violation) and finding every assertion in this file
+ still green across all 730 days (see the perturbation record in the task
+ report, reproduced and reverted, not left in the tree). This file now
+ also compares WHICH commemoration is admitted, using two independent
+ signals from missalemeum's own JSON: the commemoration's title text
+ (English, exact string) and, for a sancti-origin commemoration, its own
+ [id]'s embedded rank digit (used only as a corroborating check, never as
+ the primary signal -- see [Comm_identity] below).
+
+ THE MAPPING, AND EXACTLY WHAT IT CANNOT RESOLVE: missalemeum identifies
+ a commemoration by an English TITLE string; colitur identifies one by a
+ SLUG. There is no hand-built slug<->title lookup table here -- colitur's
+ own {!Celebration.t}.names already carries an English name for every
+ SANCTORAL-origin celebration (bootstrapped from lectio's own English
+ titles, which verifiably match missalemeum's titles character-for-
+ character on every checked row), so the comparison reads that name
+ directly off colitur's own resolved output, the same field
+ test_differential.ml already treats as authoritative for OF/EF display
+ text. This resolves identity for every SANCTORAL-origin commemoration.
+ It CANNOT resolve a TEMPORAL-origin commemoration (an impeded feria, a
+ privileged Sunday, an Ember/Rogation day, etc.): {!Rite_ef.Temporal_ef}'s
+ own [build] never sets a celebration's [names] field (rite_ef/
+ temporal_ef.ml has no [en "..."] string anywhere in it), so every such
+ candidate's own title is empty on colitur's side -- there is nothing to
+ compare against missalemeum's title text, and no principled way to
+ invent one without duplicating missalemeum's own English-prose
+ convention ("Feria III after the I Sunday of Lent") as a second,
+ unverified source of truth. THIS CASE IS NEVER SILENTLY SKIPPED: see
+ [Comm_identity_unresolved] below -- it is counted, reported, and must be
+ named in the allow-list like any other difference, exactly the discipline
+ the brief demands ("a day whose commemoration cannot be matched must be
+ visibly counted and reported, not quietly passed").
+
+ Identity is only even ATTEMPTED once presence and count already agree
+ (both non-empty, same length) -- a cardinality mismatch is already
+ [Comm_presence]/[Comm_count]'s own business (see [diff_fields] below),
+ and comparing SETS of different size would just restate that mismatch
+ under a third name, not add information. Compared as a SORTED MULTISET
+ of titles, not a sequence: missalemeum's own [commemorations] array order
+ is not independently verified against RG 113's own "commemoratio de
+ Tempore fit primo loco" ordering rule here, so this axis proves WHICH
+ commemorations are admitted, not what order they are listed in.
info.colors is an ARRAY -- 14 of 730 days carry two colours (rose+violet
on Gaudete/Laetare per RG 131's indult, red+violet on Palm Sunday, black+
@@ -56,14 +107,26 @@
entries; RG 110's inseparable-Peter/Paul commemoration is unimplemented
code, a real feature this task did not build) -- honestly verdicted
[missalemeum] (colitur is short a feature or a row, not right), never
- silently absorbed as if colitur were correct. TWO entries (M11 and
- M13) are [verdict open] -- CORRECTED, final fix wave, item 7: this
- comment previously said "one entry (M13)", missing M11, whose own
- verdict was changed from [colitur] to [open] in fix round 1 (see M11's
- own entry below for why) but this summary was never updated to match.
- Both are adjudicated as unresolved, not resolved either way -- the
- brief's own explicit permission ("say so as an open item") used for
- real, not defaulted past. See the task report for every entry's full
+ silently absorbed as if colitur were correct. TWO entries (M11 and M13)
+ are [verdict open] -- CORRECTED, final fix wave, item 7: this comment
+ previously said "one entry (M13)", missing M11, whose own verdict was
+ changed from [colitur] to [open] in fix round 1 (see M11's own entry
+ below for why) but this summary was never updated to match. Task B
+ (branch ef-rg16a) briefly added a THIRD, M17 (the same-band tie-break
+ between Maurice and Thomas of Villanova, 22 September) -- CORRECTED,
+ fix round 1 of that same task: M17 was itself wrong. The "tie" was
+ manufactured by {!Precedence_ef.band} lending a [Commemoration_only]
+ candidate the same table entry as a genuine [Feast] of its own rank
+ (RG 91's table has no row for a bare commemoration at all -- fixed in
+ [band] itself, not here); once fixed, 22 September resolves cleanly on
+ both sides and M17 was deleted, not merely re-adjudicated. ONE entry
+ (M15) carries its own fourth verdict, [unresolvable] -- not a rubric
+ dispute or a data gap either engine is wrong about, but a LIMIT of this
+ comparator itself (see M15's own entry). All remaining OPEN entries are
+ adjudicated as unresolved/unresolvable, not resolved either way -- the
+ brief's own explicit permission ("say so as an open item") used for real,
+ not
+ defaulted past. See the task report for every entry's full
reasoning and primary-source citation. *)
module Cal = Colitur_kernel.Calendar
@@ -74,6 +137,8 @@ module Slug = Colitur_kernel.Slug
module Date = Colitur_kernel.Date
module Cel = Colitur_kernel.Celebration
module Colour = Colitur_kernel.Colour
+module Names = Colitur_kernel.Names
+module Lang = Colitur_kernel.Lang
module V = Rite_ef.Vocab_ef
(* Same relative paths test_differential.ml uses: dune test runs from
@@ -88,7 +153,16 @@ let allow_list_path = "../data/ef/expected-divergences-missalemeum.sexp"
same reason test_differential.ml's own [fixture_sha256] is: a hand-edit
or partial re-extraction would otherwise silently turn the oracle into
an unlabelled snapshot of whatever someone last ran. *)
-let fixture_sha256 = "718eff1a03fa09c3927ef18d19fe7921c2d4d7611890c22566058b81fd7cc5ea"
+(* CORRECTED 2026-08-12, Task B (branch ef-rg16a): field 9
+ (commemoration_ids) appended to the fixture (tools/
+ extract_missalemeum_oracle.py's own header) so this file can compare
+ commemoration IDENTITY, not merely presence/count -- see this file's own
+ header comment, rewritten below. Regenerated from the SAME underlying
+ snapshot (fixtures/missalemeum-ef-2026-2027.provenance: still lectio
+ commit d7da4b0, re-verified, first 8 fields byte-identical) -- only field
+ 9 is new content, so this digest changes but the fixture's own data does
+ not. *)
+let fixture_sha256 = "4162e79d7a0bc03b81a34ce6cd3b074e2d32570217759bc3b4058ada75ea8781"
(* Identical technique to test_differential.ml's own [sha256_of_file]
(that file's own comment explains why: shelling out to [sha256sum]
@@ -143,6 +217,7 @@ type oracle_row = {
o_colours : char list;
o_title : string;
o_commemorations : string list;
+ o_commemoration_ids : string list; (** parallel to [o_commemorations], see field 9's own doc above *)
o_displaced : string list;
}
@@ -150,16 +225,27 @@ let explode s = List.init (String.length s) (String.get s)
let split_list_field f = if f = "-" then [] else String.split_on_char ';' f
+(* A commemoration id's own trailing "rank" field, e.g. "sancti:01-05:4:r" ->
+ [Some 4] -- the SECOND, corroborating identity signal this file's own
+ header describes (test_identity_rank_corroboration, near the bottom of
+ this file). [None] for any id that does not have exactly 4 ':'-separated
+ parts (defensive; every id checked so far does). *)
+let id_rank id =
+ match String.split_on_char ':' id with [ _; _; rank; _ ] -> int_of_string_opt rank | _ -> None
+
+let is_sancti_id id = String.length id >= 7 && String.sub id 0 7 = "sancti:"
+
let oracle_row_of_line line =
match String.split_on_char '|' line with
- | [ date; rank; colours; title; _tempora; commemorations; displaced; _n_masses ] ->
+ | [ date; rank; colours; title; _tempora; commemorations; displaced; _n_masses; commemoration_ids ] ->
{ o_date = date;
o_rank = int_of_string rank;
o_colours = explode colours;
o_title = title;
o_commemorations = split_list_field commemorations;
+ o_commemoration_ids = split_list_field commemoration_ids;
o_displaced = split_list_field displaced }
- | _ -> Alcotest.failf "malformed fixture line (expected 8 '|'-separated fields): %S" line
+ | _ -> Alcotest.failf "malformed fixture line (expected 9 '|'-separated fields): %S" line
let read_lines path =
let ic = open_in path in
@@ -183,7 +269,20 @@ let oracle_rows () = List.map oracle_row_of_line (read_lines fixture_path)
(* year, which straddles two civil years). *)
(* ---------------------------------------------------------------------- *)
-type colitur_row = { c_date : string; c_rank : int; c_colour : char; c_commemorations : string list }
+(* [c_commemorations]: one entry per admitted commemoration, carrying its
+ own slug, RG 8 rank, STATUS, AND its English name if colitur's own
+ {!Celebration.t}.names has one -- [None] for a TEMPORAL-origin
+ candidate, which [Rite_ef.Temporal_ef] never names (this file's own
+ header, "THE MAPPING, AND EXACTLY WHAT IT CANNOT RESOLVE"). The [None]
+ case is what [Comm_identity_unresolved] below reads; [status] is read by
+ [test_identity_rank_corroboration]'s own scope guard, see its comment. *)
+type colitur_row = {
+ c_date : string;
+ c_rank : int;
+ c_colour : char;
+ c_commemorations : (string * int * Cel.status * string option) list;
+ (** slug, rank, status, English name *)
+}
let rank_to_int = function V.Class1 -> 1 | V.Class2 -> 2 | V.Class3 -> 3 | V.Class4 -> 4
@@ -195,6 +294,8 @@ let colour_to_char = function
| Colour.Rose -> 'p'
| Colour.Black -> 'b'
+let en = Lang.of_string_exn "en"
+
let colitur_rows_2026_2027 () =
let layer = real_layer () in
let by_rata : (int, (V.season, V.rank) LD.t) Hashtbl.t = Hashtbl.create 800 in
@@ -210,14 +311,17 @@ let colitur_rows_2026_2027 () =
(match Hashtbl.find_opt by_rata (Date.to_rata !d) with
| Some day ->
let cel = day.LD.observed in
- let commemoration_slugs =
- List.map (fun (c, _) -> Slug.to_string c.Cel.slug) day.LD.commemorations
+ let commemorations =
+ List.map
+ (fun (c, _) ->
+ (Slug.to_string c.Cel.slug, rank_to_int c.Cel.rank, c.Cel.status, Names.find c.Cel.names en))
+ day.LD.commemorations
in
rows :=
{ c_date = Date.to_iso8601 day.LD.date;
c_rank = rank_to_int cel.Cel.rank;
c_colour = colour_to_char cel.Cel.colour;
- c_commemorations = commemoration_slugs
+ c_commemorations = commemorations
}
:: !rows
| None -> Alcotest.failf "internal error: no resolved day for %s" (Date.to_iso8601 !d));
@@ -226,18 +330,39 @@ let colitur_rows_2026_2027 () =
List.rev !rows
(* ---------------------------------------------------------------------- *)
-(* Field-diff computation: the four axes the oracle actually supports *)
-(* (identity-by-slug is deliberately out of scope, see this file's own *)
-(* header). *)
+(* Field-diff computation: the axes the oracle supports, RANK/COLOUR/ *)
+(* PRESENCE/COUNT as before, plus (Task B) IDENTITY -- see this file's own *)
+(* header for the mapping and its exact limits. *)
(* ---------------------------------------------------------------------- *)
-type field = Rank | Colour_f | Comm_presence | Comm_count
+type field = Rank | Colour_f | Comm_presence | Comm_count | Comm_identity_mismatch | Comm_identity_unresolved
let field_name = function
| Rank -> "rank"
| Colour_f -> "colour"
| Comm_presence -> "commemoration-presence"
| Comm_count -> "commemoration-count"
+ | Comm_identity_mismatch -> "commemoration-identity-mismatch"
+ | Comm_identity_unresolved -> "commemoration-identity-unresolved"
+
+(* Identity (Task B): only even attempted once presence AND count already
+ agree (both non-empty, same length) -- see this file's own header,
+ "Identity is only even ATTEMPTED...". Two outcomes beyond a clean match:
+ [Comm_identity_unresolved] when ANY of colitur's own admitted
+ commemorations carries no English name to compare (a TEMPORAL-origin
+ candidate -- counted and reported, never silently skipped, per the
+ brief); [Comm_identity_mismatch] when every name IS resolvable but the
+ SORTED MULTISET of titles still disagrees with missalemeum's own. *)
+let identity_diff (c : colitur_row) (o : oracle_row) =
+ let c_has = c.c_commemorations <> [] and o_has = o.o_commemorations <> [] in
+ if not (c_has && o_has) || List.length c.c_commemorations <> List.length o.o_commemorations then None
+ else
+ let unresolved = List.exists (fun (_, _, _, name) -> name = None) c.c_commemorations in
+ if unresolved then Some Comm_identity_unresolved
+ else
+ let c_titles = List.sort compare (List.filter_map (fun (_, _, _, n) -> n) c.c_commemorations) in
+ let o_titles = List.sort compare o.o_commemorations in
+ if c_titles = o_titles then None else Some Comm_identity_mismatch
let diff_fields (c : colitur_row) (o : oracle_row) =
let c_has = c.c_commemorations <> [] and o_has = o.o_commemorations <> [] in
@@ -252,7 +377,8 @@ let diff_fields (c : colitur_row) (o : oracle_row) =
same disagreement under a second name. *)
(if c_has && o_has && List.length c.c_commemorations <> List.length o.o_commemorations then
Some Comm_count
- else None)
+ else None);
+ identity_diff c o
]
(* ---------------------------------------------------------------------- *)
@@ -345,19 +471,31 @@ let m4_dates = [ "2026-01-28"; "2027-01-28" ]
report). *)
let m5_dates = [ "2026-04-25" ]
-(* M6 -- the reverse of M4/M7/M9: the primary calendarium's own row for 14
- August reads, in full, "Vigilia, II classis." -- nothing else. No
- commemoration is listed for that date anywhere in the source this
- project treats as authoritative (CLAUDE.md binding decision 1). data/ef/
- sanctoral.sexp agrees (a single entry, [vigil-of-the-assumption], 14
- Aug). missalemeum's own "St. Eusebius" commemoration for that date has
- no support in the 1962 universal calendar found here (a DIFFERENT St
- Eusebius, bishop and martyr, is genuinely commemorated 16 December,
- matching lectio's own [eusebius] entry at that date -- not this one).
- Verdict colitur: this is the one direction among M4/M6/M7/M9 where the
- oracle itself appears to be carrying data outside the 1962 universal
- calendar (a pre-1955 survival or a different edition), not colitur
- missing something real. *)
+(* M6 -- CORRECTED 2026-08-12, transcription-audit task (branch ef-rg16a):
+ the previous version of this comment read the ELECTRONIC TRANSCRIPTION
+ (1962-06-23,_SS_Ioannes_XXIII,_Missale_Romanum,_LT.pdf), which silently
+ drops calendarium commemorations, and mistook its silence for the
+ calendarium's own -- "reads, in full, 'Vigilia, II classis.' -- nothing
+ else" was true of the TRANSCRIPTION only. A photographic scan
+ (missale-romanum-1962.pdf), 14 August row: "Vigilia, II classis,
+ Commemoratio S. Eusebii Conf.", with its own proper immediately
+ following ("Eodem die ... Et fit commemoratio S. Eusebii Conf.") --
+ independently confirmed in the second scan, Missale Romanum 1962_text
+ .pdf. The same shape as M4/M7/M9/M14, NOT their reverse: a genuine
+ commemoration is present in the calendarium and in missalemeum's own
+ data, but absent from data/ef/sanctoral.sexp and lectio's own
+ tridentine-calendar.ini (no 08-14 entry beyond [vigil-of-the-assumption]).
+ This Eusebius Confessor (14 Aug) is a genuinely DIFFERENT saint from
+ Eusebius Bishop and Martyr (16 Dec, already correctly in data/ef/
+ sanctoral.sexp, matching lectio's own [eusebius] entry at THAT date) --
+ both exist, at their own separate dates. Verdict missalemeum (flipped
+ from colitur): colitur is missing this commemoration, a genuine data gap
+ not fixable without touching ~/git/projects/lectio -- see
+ docs/research/rules-register.md, Decisions item 4 and the
+ transcription-audit record in section 6, for the full account and the
+ wider calendarium sweep this correction came from. The diff SHAPE this
+ predicate matches (Comm_presence, both dates) is unchanged by the
+ verdict flip -- only which side is right, and why, changed. *)
let m6_dates = [ "2026-08-14"; "2027-08-14" ]
(* M7 -- a genuine DATA GAP, primary-source-confirmed, the same shape as
@@ -479,6 +617,89 @@ let m12_dates = [ "2027-02-22" ]
item. *)
let m13_dates = [ "2027-03-19" ]
+(* M15 -- Task B (branch ef-rg16a), NOT a rubric dispute and NOT a data gap
+ either engine is wrong about: a genuine LIMIT of this comparator, honestly
+ counted rather than silently passed (the brief's own explicit
+ instruction: "a day whose commemoration cannot be matched must be
+ visibly counted and reported, not quietly passed"). On each of these 19
+ rows, colitur's own admitted commemoration is TEMPORAL-origin (an
+ impeded Advent/Lent feria) -- Rite_ef.Temporal_ef's own [build]
+ (temporal_ef.ml) never sets a celebration's [names] field, so there is no
+ English string on colitur's side to compare against missalemeum's title
+ text at all (this file's own header, "THE MAPPING, AND EXACTLY WHAT IT
+ CANNOT RESOLVE"). Every one of these 19 oracle titles reads as a plain
+ prose description of the SAME temporal ferial slot colitur independently
+ computes for that date (e.g. 2 Dec 2026: oracle "Feria IV after I Sunday
+ of Advent" against colitur's own [ef-advent-1-wednesday]; 4 Dec 2027:
+ oracle "Sabbato after I Sunday of Advent" against [ef-advent-1-saturday])
+ -- suggestive corroboration, recorded here for a human reader, but NOT
+ proof: this comparator has no mechanism to verify English prose against
+ an opaque slug, so it does not claim these as verified matches, only as
+ unresolved. Fixing this at the ROOT (giving every temporal-cycle
+ candidate an English name) is a data/lectionary-bootstrap task, not
+ something this comparator can do for itself -- register §6, "RG 113
+ tie-break" section's own neighbour, records it as an open item. *)
+let m15_dates =
+ [ "2026-02-24"; "2026-03-19"; "2026-03-25"; "2026-12-02"; "2026-12-03"; "2026-12-04";
+ "2026-12-07"; "2026-12-11"; "2026-12-21"; "2027-02-24"; "2027-12-02"; "2027-12-03";
+ "2027-12-04"; "2027-12-06"; "2027-12-07"; "2027-12-11"; "2027-12-13"; "2027-12-16";
+ "2027-12-21" ]
+
+(* M16 -- Task B: a genuine IDENTITY mismatch, both sides otherwise agreeing
+ on rank/colour/count/presence. 27 March 2026 (Friday of Passion Week):
+ colitur admits "St. John Damascene" (a real Class3 universal feast that
+ genuinely falls that day); missalemeum shows "For Our Lady of the Seven
+ Sorrows" instead. The SAME standing gap M13 above already names ("the
+ 1962 calendarium's own March table carries... 'Feria VI post dominicam I
+ Passionis: Commemoratio septem Dolorum B. Mariae Virg.'... a fixed
+ commemoration... EVERY year") -- confirmed real, and confirmed
+ UNIMPLEMENTED in this codebase (no candidate for it is ever constructed
+ in temporal_ef.ml), so colitur has nothing to admit in the Seven
+ Sorrows' place and falls back to whichever ordinary Class3 saint
+ actually wins that Friday instead. Verdict missalemeum: colitur is
+ missing a real, primary-cited office, not differently opinioned.
+ Register §6 open item (same one M13/M16's own primary-source note
+ already tracks). Only 2026 shows here -- 2027's Friday of Passion Week
+ IS 19 March, M13's own date, where the identity axis cannot even be
+ reached (M13's own rank/colour mismatch already excludes that day from
+ count-matched identity comparison).
+
+ NOTE for whoever builds the office (fix round 1, coordinator finding 7):
+ 27 March 2026 is a III-class day, where RG 111(d) admits TWO
+ commemorations, not one -- yet missalemeum admits only the Seven Sorrows
+ and DISPLACES John Damascene entirely (its own "displaced" list carries
+ his title that day), not merely drops him to second place. Implementing
+ the Seven Sorrows candidate naively (as one more ordinary III-class
+ commemoration competing for the day's two slots) will not reproduce
+ this: John Damascene would still win one of the two admitted slots by
+ dignity/band, giving colitur TWO commemorations where missalemeum shows
+ one. Whatever privilege or precedence the Seven Sorrows commemoration
+ carries must itself explain the exclusion, not just the admission --
+ register §6's own open item for this office should carry this caveat
+ forward. *)
+let m16_dates = [ "2026-03-27" ]
+
+(* M17 was DELETED, fix round 1 (Task B): the "genuine tie" it adjudicated
+ as [open] was itself wrong. 22 September (any year the September Ember
+ Wednesday falls on the 22nd -- 2027 in this window): colitur used to
+ admit "St. Maurice and Companions, Martyrs" (Commemoration_only, Class3)
+ where missalemeum shows "St. Thomas of Villanova" (Feast, Class3) --
+ NOT because RG 113 runs out of instruction between two same-rank
+ candidates (the framing this entry used to carry), but because
+ {!Precedence_ef.band} used to lend a [Commemoration_only] candidate the
+ SAME table entry (24) as a genuine [Feast] of its own rank, manufacturing
+ a tie the primary text never creates: RG 91's own table enumerates only
+ "dies liturgici" (entry 24: "Festa III classis..." -- FEASTS), and the
+ calendarium's own 22 September row confirms it in its own notation --
+ "S. Thomae de Villanova Ep. et Conf., III classis. / Commemoratio Ss.
+ Mauritii et Soc. Mm." -- Thomas carries a class number, Maurice carries
+ none. Fixed at the source ([band] itself now returns [Precedence_ef
+ .unclassified] for any [Commemoration_only] candidate, docs/research/
+ rules-register.md §6.1's own corrected account) rather than here: 22
+ September now resolves identically on both sides with no allow-list
+ entry needed at all -- removed, not re-adjudicated to a different
+ verdict, since there is no longer a divergence to name. *)
+
let layer_m_reason (c : colitur_row) (o : oracle_row) diffs =
if diffs = [] then None
else if List.mem c.c_date m1_dates && subset diffs [ Rank; Colour_f; Comm_presence ] then Some "M1"
@@ -494,7 +715,15 @@ let layer_m_reason (c : colitur_row) (o : oracle_row) diffs =
else if List.mem c.c_date m10_dates && diffs = [ Comm_presence ] then Some "M10"
else if List.mem c.c_date m11_dates && diffs = [ Comm_presence ] then Some "M11"
else if List.mem c.c_date m12_dates && diffs = [ Comm_count ] then Some "M12"
- else if List.mem c.c_date m13_dates && subset diffs [ Rank; Colour_f ] then Some "M13"
+ (* M13's own subset widened (Task B): the same underlying gap (the Seven
+ Sorrows commemoration is never constructed at all) now ALSO surfaces
+ as [Comm_identity_unresolved] on this date, since colitur's own
+ admitted commemoration there is temporal-origin (no English name) --
+ one root cause, one id, both axes it touches. *)
+ else if List.mem c.c_date m13_dates && subset diffs [ Rank; Colour_f; Comm_identity_unresolved ] then
+ Some "M13"
+ else if List.mem c.c_date m15_dates && diffs = [ Comm_identity_unresolved ] then Some "M15"
+ else if List.mem c.c_date m16_dates && diffs = [ Comm_identity_mismatch ] then Some "M16"
else None
(* ---------------------------------------------------------------------- *)
@@ -538,17 +767,24 @@ let classify oracle colitur =
| None -> (c, o, Unexplained diffs))
oracle colitur
+let status_to_string = function Cel.Feast -> "Feast" | Cel.Commemoration_only -> "Commemoration_only"
+
+let describe_comm (slug, rank, status, name) =
+ Printf.sprintf "%s(rank=%d,status=%s,name=%s)" slug rank (status_to_string status)
+ (match name with Some n -> Printf.sprintf "%S" n | None -> "NONE")
+
let describe_unexplained (c : colitur_row) (o : oracle_row) diffs =
Printf.sprintf "%s: %s differ -- colitur=(rank=%d colour=%c comms=[%s]) oracle=(rank=%d colours=[%s] \
- title=%S comms=[%s] displaced=[%s])"
+ title=%S comms=[%s] comm_ids=[%s] displaced=[%s])"
c.c_date
(String.concat "," (List.map field_name diffs))
c.c_rank c.c_colour
- (String.concat ";" c.c_commemorations)
+ (String.concat ";" (List.map describe_comm c.c_commemorations))
o.o_rank
(String.concat "" (List.map (String.make 1) o.o_colours))
o.o_title
(String.concat ";" o.o_commemorations)
+ (String.concat ";" o.o_commemoration_ids)
(String.concat ";" o.o_displaced)
let test_fixture_checksum () =
@@ -566,9 +802,11 @@ let test_dates_align () =
in
Alcotest.(check (list (pair string string))) "no misaligned dates" [] mismatched
-(* The core assertion: every one of the 42 raw differences across all four
+(* The core assertion: every one of the 63 raw differences across all six
axes (rank, colour-membership, commemoration-presence, commemoration-
- count) is named in the cited allow-list. Nothing else passes silently. *)
+ count, and, since Task B/ef-rg16a, commemoration-identity-mismatch and
+ commemoration-identity-unresolved) is named in the cited allow-list.
+ Nothing else passes silently. *)
let test_no_unexplained_differences () =
let oracle, colitur = compare_streams () in
let classified = classify oracle colitur in
@@ -604,6 +842,136 @@ let test_layer_m_counts_match_citations () =
undeclared"
expected actual
+(* Corroboration (Task B): for every day where the identity axis is CLEAN
+ (no [Comm_identity_mismatch]/[Comm_identity_unresolved] -- titles matched
+ as a set), independently cross-check missalemeum's own id-embedded rank
+ digit against colitur's OWN candidate rank for that SAME title -- a
+ SECOND, independent signal beyond string equality (this file's own
+ header: "used only as a corroborating check, never as the primary
+ signal"). Restricted to "sancti:"-origin ids (a TEMPORAL-origin oracle
+ commemoration has no colitur-side name to pair it with in the first
+ place, see [Comm_identity_unresolved]'s own days, which never reach here
+ since their identity axis is not clean).
+
+ SPLIT BY STATUS -- a genuine finding from running this check, not the
+ originally-planned single assertion: EVERY ONE of colitur's 114
+ [Commemoration_only] sanctoral entries carries a bootstrap-assigned
+ [rank Class3] (verified: `grep -c "status Commemoration_only"` and
+ `grep -B3 ... | grep -oP "rank Class\d" | sort | uniq -c` both give
+ 114/114 Class3, data/ef/sanctoral.sexp) -- but missalemeum's OWN id-rank
+ for a [Commemoration_only] match is NOT itself uniform: of the 175
+ examined, 17 genuinely AGREE (oracle_rank = colitur_rank = 3, real
+ corroboration) and 158 show oracle_rank 4 against colitur's bootstrapped
+ 3 -- CORRECTED after the first version of this comment overclaimed "id
+ consistently encodes 4 for every entry" from the 158-strong failure list
+ alone, before the 17 agreeing rows (then hidden inside a too-strict
+ assertion) were found. Two acceptable shapes, then, not one: either the
+ ranks genuinely agree, or the specific oracle=4/colitur=3 gap holds. This
+ is not evidence of a title-matching error, and not new: it independently
+ corroborates the register's own already-open item (§6, "Commemoration-
+ only entries' inferred STATUS, not only rank" -- Task 16's own data
+ audit already flagged these ranks as bootstrap inferences, never
+ individually Missal-verified). Auditing which of the 114 are genuinely
+ Class3 and which were silently defaulted to it is that item's own scope,
+ not this task's -- so rather than either asserting a false universal
+ equality (which fails on the 158 KNOWN, tracked, out-of-scope rows) or
+ silently dropping the check, this pins the discovered SHAPE itself:
+ every [Commemoration_only] match is EITHER a real agreement OR the known
+ gap, with no THIRD pattern -- a real, falsifiable claim (any other
+ combination would break it) that stays honest about what remains
+ unverified.
+
+ WHAT THIS DOES NOT PIN (coordinator finding 8, fix round 1, honestly
+ named rather than left implicit): the [oracle_rank = colitur_rank]
+ branch accepts ANY genuine agreement, including one this check cannot
+ independently verify is the CORRECT rank -- a regression that silently
+ flipped some entry's [rank] from [Class3] to [Class4] would land in the
+ agreement branch and pass cleanly if missalemeum's own id happened to
+ read 4 for that entry too (data drift on one side coinciding with data
+ drift on the other is not ruled out by this check, only coincidence
+ independent of any real cause is). This test pins "no third pattern
+ appears", not "every individual rank is correct" -- a narrower, still
+ genuinely useful claim (see the [> 50] population guard below, which
+ confirms the pinned shape is actually exercised at scale, not vacuously
+ true over an empty or trivial set), and this comment says so rather than
+ letting the assertion's own name imply more than it checks.
+
+ [Feast]-status candidates get the ORIGINAL, unrestricted check (any
+ disagreement at all is unexpected). CORRECTED (fix round 1, coordinator
+ finding 1): this comment previously claimed this branch was unreachable
+ in the 2026-2027 window (checked: 0) because its one candidate, Thomas
+ of Villanova on 22 September, was M17's own mismatch -- WRONG, once
+ traced further: M17 itself was wrong (see {!Precedence_ef.band}'s own
+ fidelity fix, register §6.1), and fixing it made 22 September resolve
+ cleanly on both sides, reachable here after all. Measured, not assumed:
+ 22 Feast-status commemorations are now examined by this branch (not
+ only Thomas of Villanova -- every OTHER genuinely clean Feast-status
+ match in the window reaches it too, which the earlier version of this
+ comment did not check for before asserting "0"). All 22 agree. *)
+let test_identity_rank_corroboration () =
+ let oracle, colitur = compare_streams () in
+ let feast_checked = ref 0 in
+ let feast_mismatches = ref [] in
+ let commemoration_only_checked = ref 0 in
+ let commemoration_only_surprises = ref [] in
+ List.iter2
+ (fun (o : oracle_row) (c : colitur_row) ->
+ if
+ identity_diff c o = None && c.c_commemorations <> [] && o.o_commemorations <> []
+ && List.length c.c_commemorations = List.length o.o_commemorations
+ then
+ List.iter2
+ (fun title id ->
+ if is_sancti_id id then
+ match id_rank id with
+ | None -> ()
+ | Some oracle_rank -> (
+ match List.find_opt (fun (_, _, _, n) -> n = Some title) c.c_commemorations with
+ | Some (slug, colitur_rank, Cel.Feast, _) ->
+ incr feast_checked;
+ if colitur_rank <> oracle_rank then
+ feast_mismatches :=
+ Printf.sprintf "%s: %s oracle-id-rank=%d colitur-rank=%d" c.c_date slug
+ oracle_rank colitur_rank
+ :: !feast_mismatches
+ | Some (slug, colitur_rank, Cel.Commemoration_only, _) ->
+ incr commemoration_only_checked;
+ (* Two ACCEPTABLE shapes, not one -- corrected after first running this
+ check: most Commemoration_only entries genuinely agree
+ (oracle_rank = colitur_rank, real corroboration, 17 of the
+ population checked), and the rest show the KNOWN
+ oracle=4/colitur=3 convention gap (this comment's own header).
+ Anything OUTSIDE those two shapes (e.g. oracle=2 or a THIRD
+ colitur rank paired with a non-4 oracle rank) is a genuine
+ surprise. *)
+ if not (oracle_rank = colitur_rank || (oracle_rank = 4 && colitur_rank = 3)) then
+ commemoration_only_surprises :=
+ Printf.sprintf "%s: %s oracle-id-rank=%d colitur-rank=%d (neither agrees nor \
+ fits the known oracle=4/colitur=3 pattern)"
+ c.c_date slug oracle_rank colitur_rank
+ :: !commemoration_only_surprises
+ | None -> ()))
+ o.o_commemorations o.o_commemoration_ids)
+ oracle colitur;
+ Alcotest.(check (list string))
+ "Feast-status matches: oracle id-rank agrees with colitur's own rank" [] (List.rev !feast_mismatches);
+ Alcotest.(check (list string))
+ "Commemoration_only-status matches: every one fits the KNOWN oracle=4/colitur=3 convention gap -- any \
+ other combination would be a genuine, new surprise"
+ [] (List.rev !commemoration_only_surprises);
+ (* Vacuity guard: BOTH branches must actually run now. CORRECTED (fix
+ round 1, coordinator finding 1): the [Feast] branch used to be
+ unreachable in this window (checked: 0) because its one candidate,
+ Thomas of Villanova on 22 September, was M17's own mismatch (excluded
+ by the [identity_diff = None] guard above). Fixing {!Precedence_ef
+ .band}'s Commemoration_only fidelity (register §6.1) made that day
+ resolve cleanly, so it is reachable here too -- this guard now expects
+ at least 1, not merely documents the branch as dormant (measured: 22
+ Feast-status commemorations now examined, up from 0). *)
+ Alcotest.(check bool) "the Feast-status population actually examined is non-trivial" true (!feast_checked > 0);
+ Alcotest.(check bool) "the Commemoration_only population actually examined is non-trivial" true
+ (!commemoration_only_checked > 50)
+
let suite =
( "oracle (missalemeum, EF, 2026-2027)",
[ Alcotest.test_case "fixture SHA-256 matches its provenance note" `Quick test_fixture_checksum;
@@ -611,5 +979,8 @@ let suite =
Alcotest.test_case "every difference is named in the cited allow-list -- none unexplained" `Quick
test_no_unexplained_differences;
Alcotest.test_case "allow-list counts match data/ef/expected-divergences-missalemeum.sexp exactly"
- `Quick test_layer_m_counts_match_citations
+ `Quick test_layer_m_counts_match_citations;
+ Alcotest.test_case
+ "identity corroboration: matched titles' oracle id-rank agrees with colitur's own rank" `Quick
+ test_identity_rank_corroboration
] )
diff --git a/test/test_precedence.ml b/test/test_precedence.ml
index 369c490..ce75ab6 100644
--- a/test/test_precedence.ml
+++ b/test/test_precedence.ml
@@ -26,7 +26,9 @@ let rules =
| Cel.Feast -> (match loser.P.cel.Cel.rank with
| Hi -> P.Transfer
| Lo -> P.Commemorate P.Ordinary));
- admit = (fun ~observed:_ cs -> List.filteri (fun i _ -> i < 2) cs) }
+ admit =
+ (fun ~observed:_ ~temporal:_ cs ->
+ List.filteri (fun i _ -> i < 2) cs |> List.map (fun (c, p, (_ : int)) -> (c, p))) }
let slug_of c = S.to_string c.P.cel.Cel.slug
diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml
index a0e1db1..2935e40 100644
--- a/test/test_precedence_ef.ml
+++ b/test/test_precedence_ef.ml
@@ -267,7 +267,26 @@ let cases =
(* RG 91's own vigil list (§4, "Vigils / octaves / Rogations / Sunday classes") stops at III class --
there is no IV-class vigil for entry 28's ferial catch-all to absorb. *)
( "unclassified: IV-class candidate marked as a vigil", mk 2026 6 20,
- cand ~rank:V.Class4 "ef-second-mystery-vigil", PE.unclassified )
+ cand ~rank:V.Class4 "ef-second-mystery-vigil", PE.unclassified );
+ (* Task B fix round 1 (coordinator finding 1): RG 91's table enumerates
+ only "dies liturgici" -- a [Cel.Commemoration_only] candidate is
+ never a row in the table at all, regardless of what rank it would
+ otherwise band to. [Class1]/universal-layer is deliberate: absent
+ the status guard this would band to entry 11, the FIRST, highest-
+ priority real entry any sanctoral candidate can reach, so this
+ proves the guard is checked BEFORE and overrides every rank-keyed
+ branch, not only the low-priority ones an accidental placement
+ might happen to catch. Real-world witness: "maurice-and-companions-
+ martyrs" (data/ef/sanctoral.sexp, 22 September, Class3,
+ Commemoration_only) used to band to entry 24 alongside the genuine
+ Class3 feast "thomas-of-villanova" -- test_oracle.ml's own former
+ M17 allow-list entry, deleted once this fix made the divergence it
+ named disappear. *)
+ ( "unclassified: a Commemoration_only candidate has no row in RG91's \
+ table at all, even at Class1", mk 2026 5 20,
+ cand ~origin:P.Sanctoral ~status:Cel.Commemoration_only ~layer:PE.universal_layer
+ "ef-some-commemoration-only",
+ PE.unclassified )
]
(* Review finding 1's end-to-end proof: on a real Sunday landing on 2
@@ -290,7 +309,7 @@ let test_all_souls_yields_to_sunday () =
let rules =
{ P.band = (fun c cd -> PE.band c cd);
disposition = (fun ~winner:_ ~loser:_ -> P.Omit);
- admit = (fun ~observed:_ cs -> cs) }
+ admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p, (_ : int)) -> (c, p)) cs) }
in
let resolution = P.resolve rules day_ctx ~temporal:sunday ~sanctoral:[ all_souls ] in
Alcotest.(check string) "the Sunday is observed, not All Souls"
@@ -540,7 +559,110 @@ let disposition_cases =
Omit under the refuted privilege_of=Ordinary gate",
an_ordinary_sunday,
cand ~rank:V.Class3 "ef-synthetic-ordinary-class3-feria",
- "Commemorate(Ordinary)" )
+ "Commemorate(Ordinary)" );
+ (* RG 16(a) (register §6.0, Caput III "De Dominicis"): "festum Domini I
+ aut II classis, in dominica II classis occurrens, ... de dominica,
+ proinde, nulla fit commemoratio" -- a Feast of the Lord, I or II
+ class, impeding a II-class Sunday, leaves the Sunday with NO
+ commemoration at all, unlike every other impeded II-class Sunday
+ (contrast the very first row of this table, and [privilege_cases]'s
+ own (a): both plain [Class1]/other-sanctoral winners still admit the
+ Sunday, [Commemorate(Privileged)]). Two positive rows, I and II
+ class, both real slugs/ranks/subjects this project's own audit
+ confirmed against the calendarium (this task's own report): the
+ Transfiguration (6 Aug, II class, "IN TRANSFIGURATIONE D. N. I. C.")
+ and the Precious Blood (1 Jul, I class, "PRETIOSISSIMI SANGUINIS
+ D. N. I. C."). *)
+ ( "RG16(a): a Feast of the Lord, II class, impedes a II-class Sunday -> \
+ Omit, no commemoration at all",
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord",
+ an_ordinary_sunday,
+ "Omit" );
+ ( "RG16(a): a Feast of the Lord, I class, impedes a II-class Sunday -> \
+ Omit, no commemoration at all",
+ cand ~origin:P.Sanctoral ~rank:V.Class1 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "precious-blood-of-our-lord-jesus-christ",
+ an_ordinary_sunday,
+ "Omit" );
+ (* Conjunct 1/4, WINNER subject: RG 16(a) names a feast "Domini", not any
+ I-class feast. {!band} entries 11-13 admit any I-class feast ahead of
+ a II-class Sunday with no subject test (unlike entry 14, see that
+ entry's own comment) -- so a real I-class SAINT feast can win the day
+ exactly as a Lord feast would, and must NOT trigger RG 16(a). Real
+ slug/rank/subject from data/ef/sanctoral.sexp (24 June, I class,
+ "NATIVITAS S. IOANNIS BAPTISTAE", subject Saint): 24 June falls on a
+ Time-after-Pentecost Sunday in real years (e.g. 2029), so this is a
+ live, not merely synthetic, shape -- {!band} entries 11-13 rank it
+ ahead of the ordinary Sunday's own entry 15 regardless of subject.
+ Dropping the [subject = Lord] conjunct would wrongly Omit the Sunday
+ here too. *)
+ ( "RG16(a) does NOT fire for a I-class feast of a SAINT (not the Lord) \
+ impeding a II-class Sunday -- stays Commemorate(Privileged)",
+ cand ~origin:P.Sanctoral ~rank:V.Class1 ~subject:Sub.Saint ~layer:PE.universal_layer
+ "nativity-of-st-john-the-baptist",
+ an_ordinary_sunday,
+ "Commemorate(Privileged)" );
+ (* Conjunct 2/4, LOSER rank: RG 16(a) names "Dominica II classis", not
+ any Sunday. A I-class Sunday (Advent/Lent/Passiontide, Low Sunday,
+ {!band} entry 6) can never actually reach here as a loser against a
+ Class1-or-2 Lord winner in real banding -- CORRECTED (fix round 1):
+ not because "entry 6's own band value (6) beats every entry such a
+ winner could occupy, 3/11-14" (WRONG: 6 is not lower than 3, and the
+ claim proves the opposite of what it was cited for anyway -- see
+ precedence_ef.ml's own corrected comment on this same conjunct for
+ the full argument). Against entries 11-14 the numeric claim genuinely
+ holds (6 < 11-14); against entry 3 (Epiphany/Ascension/Trinity/
+ Corpus Christi/Sacred Heart/Christ the King) it is a STRUCTURAL fact
+ instead -- every band-3 celebration is temporal-origin, and
+ [Precedence.resolve] takes exactly one temporal candidate per day, so
+ a band-3 Lord feast IS that date's own single temporal candidate,
+ never a second one contesting a separately-produced Sunday. Either
+ way, this is exactly why the primary text restricts itself to II
+ class -- but [disposition] takes no [context] and cannot itself
+ re-derive that fact, so the rank check is what actually enforces it
+ here. Sourced from [Temporal_ef.temporal]'s own real output (Advent I
+ Sunday 2026, Class1, "ef-advent-sunday-1"), the same row
+ [disposition_cases]'s own RG95/RG109(a) entry above already uses.
+ Dropping the [rank = Class2] conjunct on the loser would wrongly Omit
+ this Sunday's commemoration too. *)
+ ( "RG16(a) does NOT fire for a I-class Sunday, even losing to a Feast of \
+ the Lord -- stays Commemorate(Privileged)",
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord",
+ of_temporal (T.advent_start 2026),
+ "Commemorate(Privileged)" );
+ (* Conjunct 3/4, LOSER is a Sunday at all: RG 16(a) protects "de
+ dominica" specifically, not every ordinary office a Feast of the Lord
+ happens to impede. An ordinary sanctoral SAINT losing to the same
+ Lord-subject Class2 winner as the row above must still reach the
+ ordinary RG 95/111(c) commemorate-or-omit flow, not RG 16(a)'s
+ special no-commemoration rule. Dropping [is_sunday_slug] (or its
+ [is_temporal] companion) here would wrongly Omit this ordinary
+ saint's commemoration too. *)
+ ( "RG16(a) does NOT fire for an ordinary (non-Sunday) SAINT losing to a \
+ Feast of the Lord -- stays Commemorate(Ordinary)",
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord",
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~layer:PE.universal_layer "ef-some-other-saint",
+ "Commemorate(Ordinary)" );
+ (* Conjunct 4/4, WINNER rank: RG 16(a) says "I aut II classis", not any
+ class. Every real [subject = Lord] entry this project's own sanctoral
+ audit found is Class1 or Class2 (this task's own report), so this
+ conjunct is not independently reachable on real data -- SYNTHETIC,
+ the same defensive-but-not-load-bearing status this file already
+ gives the RG26 branch's own [not is_vigil] guard above. Without the
+ rank conjunct, [subject = Lord] alone would wrongly Omit this
+ Sunday's commemoration under a hypothetical Class3 "feast of the
+ Lord" too, which RG 16(a)'s own "I aut II classis" text does not
+ cover. *)
+ ( "SYNTHETIC: RG16(a) does NOT fire for a Class3 feast of the Lord \
+ (outside \"I aut II classis\") impeding a II-class Sunday -- stays \
+ Commemorate(Privileged)",
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "ef-synthetic-class3-lord-feast",
+ an_ordinary_sunday,
+ "Commemorate(Privileged)" )
]
(* Task 9: [privilege_of]'s RG 109 categories (§4, "Commemorations"),
@@ -719,32 +841,75 @@ let observed_class3 = cand ~rank:V.Class3 "ef-some-class3-day"
let slugs_of admitted =
List.map (fun (c, _) -> S.to_string c.P.cel.Cel.slug) admitted
+(* [admit_cases] below (Task B, ef-rg16a) needs a precedence-order [int] on
+ every comms triple -- {!Precedence.rules.admit}'s new parameter, RG 113
+ (docs/research/rules-register.md §4, "RG 113"). This table's own header
+ comment states its purpose: isolate [admit]'s own selection/count logic
+ from {!PE.band}'s occurrence-table classification, so every candidate
+ here is built from a synthetic slug ("ef-ordinary-hi" etc.) that matches
+ none of [band]'s 28 real branches -- calling the REAL [PE.band] on them
+ would collapse every one to {!PE.unclassified} (the same tied value),
+ destroying the table's ability to distinguish rows at all. [order_of_rank]
+ is a TEST-ONLY stand-in, reproducing exactly the relative order the
+ previous [dignity] function gave (RG 8's rank cardinal, lower first) --
+ so every existing expectation below still holds unchanged; only the
+ tuple shape gained this third field. *)
+let order_of_rank = function V.Class1 -> 10 | V.Class2 -> 20 | V.Class3 -> 30 | V.Class4 -> 40
+let po c p = (c, p, order_of_rank c.P.cel.Cel.rank)
+
+(* Real-data shapes for the fix round's own RG16(a)/[admit] interaction
+ (below): a Feast of the Lord (subject Lord, Class2, sanctoral) as
+ [observed], oracle-confirmed real slugs/ranks rather than hand-typed
+ ones, the same coupling-safety reason [of_temporal] rows elsewhere in
+ this file use real data. *)
+let lord_winner =
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord"
+
+(* Pope Sixtus II et al. (6 August, real slug/rank/status from
+ data/ef/sanctoral.sexp): Class3, Commemoration_only, tagged [Ordinary]
+ here directly (as every other [admit_cases] row does, isolating
+ [admit]'s own selection logic from [privilege_of], per this table's own
+ header comment). *)
+let sixtus =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~status:Cel.Commemoration_only
+ ~layer:PE.universal_layer "pope-sixtus-ii-felicissimus-and-agapitus-martyrs"
+
+(* (description, observed, temporal, comms, expected). [temporal] --
+ {!Precedence.rules.admit}'s own new parameter, fix round 1 (RG16(a)
+ task): the day's temporal-cycle candidate, independent of who is
+ [observed]. Every row below except the last two repeats [observed] as
+ [temporal] -- no RG16(a) displacement occurs in those rows (the pattern
+ [PE.admit]'s pre-fix code implicitly, and wrongly, assumed held
+ UNIVERSALLY), so the two values coinciding is the faithful shape, not a
+ simplification that dodges the new parameter. The last two rows are
+ where they genuinely differ -- see their own comment. *)
let admit_cases =
[ (* RG 111 (§4): "I class: none save one privileged." *)
( "I-class day, only an ordinary commemoration due -> none admitted",
- observed_class1,
- [ (ordinary_hi, P.Ordinary) ],
+ observed_class1, observed_class1,
+ [ po ordinary_hi P.Ordinary ],
[] );
( "I-class day, ordinary + privileged both due -> only the privileged \
one, regardless of the ordinary one's higher dignity",
- observed_class1,
- [ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
+ observed_class1, observed_class1,
+ [ po ordinary_hi P.Ordinary; po privileged_lo P.Privileged ],
[ "ef-privileged-lo" ] );
( "I-class day, two privileged due -> only the higher-dignity one (still \
just \"one\")",
- observed_class1,
- [ (privileged_lo, P.Privileged); (privileged_hi, P.Privileged) ],
+ observed_class1, observed_class1,
+ [ po privileged_lo P.Privileged; po privileged_hi P.Privileged ],
[ "ef-privileged-hi" ] );
(* RG 111: "II-class Sundays: one (dropped if a privileged one is due)." *)
( "II-class Sunday, only an ordinary commemoration due -> it is admitted",
- observed_class2_sunday,
- [ (ordinary_hi, P.Ordinary) ],
+ observed_class2_sunday, observed_class2_sunday,
+ [ po ordinary_hi P.Ordinary ],
[ "ef-ordinary-hi" ] );
( "II-class Sunday, ordinary (higher dignity) + privileged (lower \
dignity) both due -> the PRIVILEGED one is admitted, the ordinary \
one dropped despite outranking it",
- observed_class2_sunday,
- [ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
+ observed_class2_sunday, observed_class2_sunday,
+ [ po ordinary_hi P.Ordinary; po privileged_lo P.Privileged ],
[ "ef-privileged-lo" ] );
(* RG 111(b)'s own rank floor ("scilicet DE FESTO II CLASSIS"), fix
round 1 F7: a Class3 ORDINARY candidate -- no privileged rival due,
@@ -755,8 +920,8 @@ let admit_cases =
below, which has no such restriction. *)
( "II-class Sunday, sole candidate is an ORDINARY Class3 (not \
\"de festo II classis\") -> admitted nothing, not the best available",
- observed_class2_sunday,
- [ (ordinary_class3, P.Ordinary) ],
+ observed_class2_sunday, observed_class2_sunday,
+ [ po ordinary_class3 P.Ordinary ],
[] );
(* RG 111: "other II class: one" -- no privilege override, the exact
asymmetry the brief and precedence_ef.ml's own [admit] comment flag:
@@ -764,23 +929,55 @@ let admit_cases =
observed day, OPPOSITE winner. *)
( "other II-class day, only an ordinary commemoration due -> it is \
admitted",
- observed_class2_other,
- [ (ordinary_hi, P.Ordinary) ],
+ observed_class2_other, observed_class2_other,
+ [ po ordinary_hi P.Ordinary ],
[ "ef-ordinary-hi" ] );
( "other II-class day, same ordinary+privileged pair as the Sunday row \
above -> the ORDINARY one wins on pure dignity this time, the \
privileged one dropped",
- observed_class2_other,
- [ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
+ observed_class2_other, observed_class2_other,
+ [ po ordinary_hi P.Ordinary; po privileged_lo P.Privileged ],
[ "ef-ordinary-hi" ] );
(* RG 111: "III-IV class: at most two" -- three candidates due, top two
by dignity admitted, the third (lowest dignity) dropped. *)
( "III-class day, three commemorations due -> the top two by dignity, \
not merely \"two of them\"",
- observed_class3,
- [ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged);
- (ordinary_lowest, P.Ordinary) ],
- [ "ef-ordinary-hi"; "ef-privileged-lo" ] )
+ observed_class3, observed_class3,
+ [ po ordinary_hi P.Ordinary; po privileged_lo P.Privileged;
+ po ordinary_lowest P.Ordinary ],
+ [ "ef-ordinary-hi"; "ef-privileged-lo" ] );
+ (* Fix round 1, item 2 (RG16(a) task review): the CRITICAL witness for
+ [~temporal]. RG 16(a)'s own text -- the winning Feast of the Lord
+ holds the Sunday's place "cum omnibus iuribus et privilegiis" -- means
+ the day is STILL a "dominica II classis" for RG 111(b)'s own rank
+ floor, even though [observed] is now the FEAST (Transfiguration, real
+ slug/rank/subject), not the Sunday. [temporal] (a real Sunday
+ candidate, {!an_ordinary_sunday}) is what reveals that; nothing in
+ [observed] does, since its own slug carries no Sunday marker at all.
+ Oracle-confirmed (missalemeum, 2023-08-06, a Sunday):
+ "commemorations": [], Sixtus "displaced". Before this fix
+ [observed_is_sunday] read [observed]'s own slug and got [false] here,
+ wrongly taking the "other II class: one" branch below and admitting
+ Sixtus (Class3) despite RG 111(b)'s rank floor. *)
+ ( "RG16(a) interaction: a Feast of the Lord observed on a day whose \
+ TEMPORAL candidate is a II-class Sunday -> the RG111(b) rank floor \
+ still applies, admits nothing (Sixtus, Class3, has no standing)",
+ lord_winner, an_ordinary_sunday,
+ [ po sixtus P.Ordinary ],
+ [] );
+ (* The control, same pair as the row above with [observed] = [temporal]
+ (no displacement -- an ordinary WEEKDAY, not a Sunday): "other II
+ class: one", no rank floor, Sixtus IS admitted. Oracle-confirmed
+ (missalemeum, 2026-08-06, a Thursday): Sixtus in "commemorations".
+ Proves the DISCRIMINATING factor is [temporal]'s own Sunday-ness, not
+ merely "was the winner a Feast of the Lord" -- that alone is true of
+ BOTH rows here, and only one of them excludes Sixtus. *)
+ ( "control: the same Feast of the Lord on an ORDINARY weekday (temporal \
+ = observed, not a Sunday) -> \"other II class: one\", Sixtus IS \
+ admitted",
+ lord_winner, lord_winner,
+ [ po sixtus P.Ordinary ],
+ [ "pope-sixtus-ii-felicissimus-and-agapitus-martyrs" ] )
]
(* Order independence (brief: "the admitted set must not depend on input
@@ -791,13 +988,48 @@ let admit_cases =
two-candidate row where either order already happens to be sorted. *)
let test_admit_order_independent () =
let comms =
- [ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged); (ordinary_lowest, P.Ordinary) ]
+ [ po ordinary_hi P.Ordinary; po privileged_lo P.Privileged; po ordinary_lowest P.Ordinary ]
+ in
+ let forward = slugs_of (PE.admit ~observed:observed_class3 ~temporal:observed_class3 comms) in
+ let reversed =
+ slugs_of (PE.admit ~observed:observed_class3 ~temporal:observed_class3 (List.rev comms))
in
- let forward = slugs_of (PE.admit ~observed:observed_class3 comms) in
- let reversed = slugs_of (PE.admit ~observed:observed_class3 (List.rev comms)) in
Alcotest.(check (list string)) "reversed input admits the same candidates"
forward reversed
+(* RG 113 teeth (Task B, ef-rg16a): two SAME-rank candidates whose slug order
+ DISAGREES with their band/precedence order -- "aa-worse-precedence" sorts
+ first alphabetically but is given the WORSE (higher) precedence int,
+ "zz-better-precedence" sorts last alphabetically but the BETTER (lower)
+ one. Both are [Class3] (same RG 8 "dignity", so a version of [admit] that
+ silently reverted to sorting by [rank] then slug -- the exact pre-fix
+ shape this task replaced -- would pick "aa-worse-precedence" here, the
+ OPPOSITE of what this asserts. A real RG 91 [band] value never actually
+ produces this exact pairing against these two synthetic slugs (see
+ [admit_cases]'s own header on why this table uses synthetic, non-band-
+ classifiable slugs) -- the precedence ints are supplied directly, the
+ same [po]/explicit-order convention this file already uses, standing in
+ for whatever real [band] would compute. This is what proves [admit]
+ actually consults the passed-in precedence value rather than merely
+ accepting one as a matter of new type-checking. *)
+let order_tiebreak_alpha_first_worse = cand ~rank:V.Class2 "aa-worse-precedence"
+let order_tiebreak_alpha_last_better = cand ~rank:V.Class2 "zz-better-precedence"
+
+(* [observed_class2_other]: "other II class: one" admits exactly ONE, by
+ precedence order alone (no privilege override, no rank floor) -- unlike
+ the III-class row [test_admit_order_independent] reuses, which admits
+ TWO out of two offered here and so cannot distinguish "picked by
+ precedence" from "picked both anyway". *)
+let test_admit_uses_precedence_not_slug_when_they_disagree () =
+ let comms =
+ [ (order_tiebreak_alpha_first_worse, P.Ordinary, 90);
+ (order_tiebreak_alpha_last_better, P.Ordinary, 10) ]
+ in
+ Alcotest.(check (list string))
+ "the BETTER-precedence candidate is admitted even though it sorts LAST alphabetically"
+ [ "zz-better-precedence" ]
+ (slugs_of (PE.admit ~observed:observed_class2_other ~temporal:observed_class2_other comms))
+
(* The brief: "a case proving that what the limit drops is reported in
omitted rather than vanishing" -- three end-to-end proofs, wired with the
REAL [PE.band], [PE.disposition] and [PE.admit] together (not a stub, so
@@ -929,6 +1161,63 @@ let test_ii_class_sunday_privileged_witness_admitted_end_to_end () =
[ ("ef-some-saint", "omitted: admission limit reached") ]
(List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted)
+(* RG 16(a) (register §6.0) reached end-to-end through the REAL pipeline
+ ([PE.band], [PE.disposition] AND [PE.admit] together, not any one of
+ them in isolation as this file's own hand-tagged rows test them
+ separately): a real civil date this task's own blast-radius measurement
+ names as a live instance of the bug this branch fixes -- 6 August 2028
+ is a Sunday (independently checked with `date -d 2028-08-06 +%A`, the
+ same cross-check discipline [test_golden.ml]'s own header requires),
+ Time after Pentecost week 9, and the Transfiguration (6 Aug, II class,
+ "IN TRANSFIGURATIONE D. N. I. C.") falls on it. Before this fix
+ `colitur day` emitted this Sunday as an admitted
+ [+ef-time-after-pentecost-sunday-9] commemoration on that date (register
+ §6.0's own reproduction).
+
+ Fix round 1 (item 2): a THIRD candidate, Pope Sixtus II et al. (real
+ slug/rank/status, 6 August, unrelated to the Sunday), is now also
+ offered, so this test exercises BOTH fixes at once, the same real shape
+ [test_golden.ml]'s own 2028-08-06 pin does: [observed] is the
+ Transfiguration ({!band} entry 14 already did this correctly before this
+ task); the Sunday is [disposition]-level [Omit] (RG 16(a)); Sixtus is
+ [disposition]-level [Commemorate], but [admit] then excludes him too --
+ RG 111(b)'s rank floor, reached only because [admit] reads the day's
+ Sunday-ness off [~temporal] (the [sunday] candidate passed to
+ [P.resolve]), not off [observed] (the Transfiguration, whose own slug
+ carries no Sunday marker). [commemorations] is EMPTY, and BOTH losers
+ land in [omitted] with their own distinct reasons -- the Sunday via
+ [disposition]'s own Omit ("omitted: yielded to a higher day"), Sixtus via
+ [admit]'s cut ("omitted: admission limit reached") -- proving the two
+ fixes operate through genuinely different mechanisms, not the same one
+ coincidentally producing the same string. *)
+let test_rg16a_lord_feast_suppresses_sunday_end_to_end () =
+ let date = mk 2028 8 6 in
+ let day_ctx = ctx date in
+ let sunday = of_temporal date in
+ let transfiguration =
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord"
+ in
+ let sixtus =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~status:Cel.Commemoration_only ~layer:PE.universal_layer
+ "pope-sixtus-ii-felicissimus-and-agapitus-martyrs"
+ in
+ let resolution =
+ P.resolve real_rules day_ctx ~temporal:sunday ~sanctoral:[ transfiguration; sixtus ]
+ in
+ Alcotest.(check string) "the Transfiguration is observed, not the Sunday"
+ "transfiguration-of-our-lord" (S.to_string resolution.P.observed.P.cel.Cel.slug);
+ Alcotest.(check int)
+ "no commemorations at all -- RG16(a)'s own \"nulla fit commemoratio\" AND RG111(b)'s rank floor, both live"
+ 0 (List.length resolution.P.commemorations);
+ Alcotest.(check (list (pair string string)))
+ "both losers omitted, via two DIFFERENT mechanisms: the Sunday at disposition-level (RG16a), Sixtus at \
+ admit's own cut (RG111b)"
+ [ ("ef-time-after-pentecost-sunday-9", "omitted: yielded to a higher day");
+ ("pope-sixtus-ii-felicissimus-and-agapitus-martyrs", "omitted: admission limit reached") ]
+ (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted
+ |> List.sort compare)
+
(* Completes Task 7's carried fix (RG 91 entry 8, §4): on a real Sunday
landing on 2 November, All Souls does not merely lose (that was Task 7's
[band] fix, proved by [test_all_souls_yields_to_sunday] above) -- it must
@@ -960,7 +1249,10 @@ let test_all_souls_transfers_end_to_end () =
origin = P.Temporal }
in
let all_souls = cand ~origin:P.Sanctoral ~layer:PE.universal_layer "ef-all-souls" in
- let rules = { P.band = PE.band; disposition = PE.disposition; admit = (fun ~observed:_ cs -> cs) } in
+ let rules =
+ { P.band = PE.band; disposition = PE.disposition;
+ admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p, (_ : int)) -> (c, p)) cs) }
+ in
let resolution = P.resolve rules day_ctx ~temporal:sunday ~sanctoral:[ all_souls ] in
Alcotest.(check (list string)) "All Souls is deferred (transferred), not omitted or commemorated"
[ "ef-all-souls" ]
@@ -1150,13 +1442,16 @@ let suite =
Alcotest.test_case "All Souls transfers end-to-end (resolve, real rules)" `Quick
test_all_souls_transfers_end_to_end ]
@ List.map
- (fun (desc, observed, comms, expect) ->
+ (fun (desc, observed, temporal, comms, expect) ->
Alcotest.test_case desc `Quick (fun () ->
Alcotest.(check (list string)) desc expect
- (slugs_of (PE.admit ~observed comms))))
+ (slugs_of (PE.admit ~observed ~temporal comms))))
admit_cases
@ [ Alcotest.test_case "admit is order-independent (III-class, 3 candidates)" `Quick
test_admit_order_independent;
+ Alcotest.test_case
+ "RG113: admit picks by precedence order, not slug, when they disagree" `Quick
+ test_admit_uses_precedence_not_slug_when_they_disagree;
Alcotest.test_case "I-class day: full drop reported in omitted, not vanished" `Quick
test_i_class_day_drops_into_omitted;
Alcotest.test_case "II-class Sunday: second loser dropped into omitted" `Quick
@@ -1166,6 +1461,10 @@ let suite =
Alcotest.test_case
"II-class Sunday override: RG109(b) witness admitted over an ordinary saint, end-to-end"
`Quick test_ii_class_sunday_privileged_witness_admitted_end_to_end;
+ Alcotest.test_case
+ "RG16(a): a Feast of the Lord suppresses the Sunday's own commemoration entirely, \
+ end-to-end (2028-08-06)"
+ `Quick test_rg16a_lord_feast_suppresses_sunday_end_to_end;
Alcotest.test_case "transfer_target: general RG96 search walks past more than one blocked day"
`Quick test_transfer_target_general_multi_step_search;
Alcotest.test_case "transfer_target: Annunciation exception starts at Monday after Low Sunday"
diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml
index c150a6d..84dc060 100644
--- a/test/test_rite_ef.ml
+++ b/test/test_rite_ef.ml
@@ -87,6 +87,53 @@ let test_vigil_of_christmas_suppressed () =
Alcotest.(check bool) "vigil-of-christmas appears NOWHERE in the resolved year" false
appears_anywhere
+(* RG16(a) task (register §6.0 + the sanctoral subject audit, this task's
+ own report). data/ef/sanctoral.sexp is left untouched (still a faithful
+ mirror of lectio, subject `Lord` for every entry below except
+ `most-holy-name-of-mary` -- see test_sanctoral_ef.ml's own "explicit
+ class = lord" spot-check, which loads that file WITHOUT applying this
+ overlay and still passes); the one real correction lives entirely in
+ data/ef/adjustments.sexp's single remaining [Edit] directive, the same
+ mechanism [test_vigil_of_christmas_suppressed] above already proves for
+ a sibling bootstrap defect.
+
+ CORRECTED, fix round 1 (CRITICAL finding, item 1): this test used to
+ also assert `purification-of-the-blessed-virgin-mary` was retagged
+ `Bvm`. REVERTED -- the user has ruled: follow the oracle (register §6.0
+ has the full account, both the calendarium argument for `Bvm` and the
+ oracle evidence against it). The Purification is `Lord` again, one of
+ FIVE untouched entries this test now re-verifies, not four.
+
+ This is the ONE test in the suite that observes the one live retag
+ actually takes effect through the real pipeline -- without it, a typo in
+ the directive's slug (silently a no-op diagnostic, not a hard failure --
+ Overlay.apply's own contract) or a reverted adjustments.sexp would leave
+ every other test green ([test_sanctoral_ef.ml] deliberately never
+ applies the overlay). Also re-verifies the five entries the audit
+ confirmed correct and left untouched, so a future accidental retag of
+ one of THEM would be caught here too, not just the one that changed. *)
+let test_rg16a_subject_retag_in_effect () =
+ let layer = real_layer () in
+ let subject_of slug =
+ match Layer.find layer (Slug.of_string_exn slug) with
+ | Some e -> e.Layer.cel.Cel.subject
+ | None -> Alcotest.failf "slug %s not found in the overlaid layer" slug
+ in
+ Alcotest.(check bool) "Most Holy Name of Mary retagged Bvm (calendarium: \"Nominis Mariae\")" true
+ (subject_of "most-holy-name-of-mary" = Subject.Bvm);
+ Alcotest.(check bool)
+ "Purification stays Lord (reverted, fix round 1 -- the user's ruling: follow the oracle)" true
+ (subject_of "purification-of-the-blessed-virgin-mary" = Subject.Lord);
+ Alcotest.(check bool) "Precious Blood stays Lord (calendarium: \"D. N. I. C.\") -- audit, not touched" true
+ (subject_of "precious-blood-of-our-lord-jesus-christ" = Subject.Lord);
+ Alcotest.(check bool) "Transfiguration stays Lord (calendarium: \"D. N. I. C.\") -- audit, not touched" true
+ (subject_of "transfiguration-of-our-lord" = Subject.Lord);
+ Alcotest.(check bool) "Exaltation of the Holy Cross stays Lord -- audit, not touched" true
+ (subject_of "exaltation-of-the-holy-cross" = Subject.Lord);
+ Alcotest.(check bool)
+ "Dedication of the Archbasilica of the Most Holy Saviour stays Lord -- audit, not touched" true
+ (subject_of "dedication-of-the-archbasilica-of-our-holy-savior" = Subject.Lord)
+
(* Coordinator review, finding 2, reproduced through the project's OWN
extension path (an overlay), the same way the reviewer found it: adding
an I-class feast on 25 December (competing against, and losing to, the
@@ -251,10 +298,51 @@ let test_search_genuinely_enters_the_window () =
"the walked span is at least 8 days -- the octave alone (Easter..Easter+7), not a one-day hop"
true (List.length walked >= 8)
+(* Task B fix round 1 (coordinator finding 1), end to end with REAL data:
+ 22 September 2027 is a September Ember Wednesday -- the OBSERVED day is
+ the Ember office itself ([band] entry 18, RG 91, beats both sanctoral
+ candidates), and RG 111(c) ("other II class: one") admits exactly ONE
+ of the two competing losers, "maurice-and-companions-martyrs"
+ ([Commemoration_only], Class3) and "thomas-of-villanova" ([Feast],
+ Class3). Before the fix, [Precedence_ef.band] gave Maurice the SAME
+ table entry (24) as Thomas, so the residual slug tie-break picked
+ Maurice ('m' < 't') and OMITTED Thomas -- contrary to the calendarium's
+ own 22 September row ("S. Thomae de Villanova Ep. et Conf., III
+ classis. / Commemoratio Ss. Mauritii et Soc. Mm.": Thomas is the one
+ WITH a table entry) and to missalemeum (test/test_oracle.ml's own
+ former M17 allow-list entry -- oracle "commemorations": Thomas,
+ "displaced": Maurice -- deleted once this fix made the divergence
+ disappear). This is the SAME date the oracle harness itself checks,
+ pinned here too so a regression shows up at the OCaml level, not only
+ via the fixture comparison. *)
+let test_maurice_thomas_band_fidelity_end_to_end () =
+ let layer = real_layer () in
+ (* [Calendar.year]'s own liturgical-year convention (Advent-anchored, see
+ calendar.ml's [year_bounds]): the label [y] spans December of civil
+ year [y] through November of civil year [y+1], so 22 September 2027
+ is reached via [Cal.year ... 2026], not 2027 -- the same
+ [y-1]/straddling indexing test_oracle.ml's own header comment already
+ documents for exactly this reason. *)
+ let days = Cal.year Rite_ef.context layer 2026 in
+ let day = Array.to_list days |> List.find (fun d -> Date.compare d.LD.date (mk 2027 9 22) = 0) in
+ Alcotest.(check string) "the September Ember Wednesday office itself is observed (band entry 18)"
+ "ef-september-ember-wed" (slug_of day.LD.observed);
+ Alcotest.(check (list string))
+ "St Thomas of Villanova (band entry 24, a real table row) is the sole commemoration"
+ [ "thomas-of-villanova" ]
+ (List.map (fun (c, _) -> slug_of c) day.LD.commemorations);
+ Alcotest.(check (list string))
+ "St Maurice and Companions (Commemoration_only, unclassified -- no table row) is omitted, not \
+ commemorated"
+ [ "maurice-and-companions-martyrs" ]
+ (List.map (fun (c, _) -> slug_of c) day.LD.omitted)
+
let suite =
( "Rite_ef (real data: overlay-in-effect, domain-ceiling)",
[ Alcotest.test_case "the overlay suppression is observably in effect" `Quick
test_vigil_of_christmas_suppressed;
+ Alcotest.test_case "RG16(a) task: the two subject retags are in effect, the other four untouched"
+ `Quick test_rg16a_subject_retag_in_effect;
Alcotest.test_case "RG96 search does not raise at the domain ceiling (real data)" `Quick
test_transfer_search_does_not_raise_at_domain_ceiling;
Alcotest.test_case "no transfer ever lands inside [Easter, Easter+7], 2005-2050" `Quick
@@ -262,4 +350,8 @@ let suite =
Alcotest.test_case "transfer_target skips the whole Easter octave from inside Holy Week" `Quick
test_transfer_target_skips_the_whole_easter_octave;
Alcotest.test_case "the search genuinely enters the window (not vacuous)" `Quick
- test_search_genuinely_enters_the_window ] )
+ test_search_genuinely_enters_the_window;
+ Alcotest.test_case
+ "band fidelity end-to-end: Ember Wednesday observed, Thomas of Villanova the sole \
+ commemoration, Maurice omitted (2027-09-22)" `Quick
+ test_maurice_thomas_band_fidelity_end_to_end ] )
diff --git a/test/test_validate.ml b/test/test_validate.ml
index 89053c1..501dd2e 100644
--- a/test/test_validate.ml
+++ b/test/test_validate.ml
@@ -225,7 +225,7 @@ module Synthetic = struct
let rules : (season, rank) P.rules =
{ P.band = (fun _ _ -> 0);
disposition = (fun ~winner:_ ~loser:_ -> P.Omit);
- admit = (fun ~observed:_ _ -> []) }
+ admit = (fun ~observed:_ ~temporal:_ _ -> []) }
let year_start y = match D.make ~year:y ~month:1 ~day:1 with Ok d -> d | Error e -> failwith e
@@ -377,7 +377,9 @@ module Synthetic = struct
let dup_rules : (season, rank) P.rules =
{ P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10);
disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary);
- admit = (fun ~observed:_ cs -> List.map (fun (c, p) -> ({ c with P.origin = c.P.origin }, p)) cs) }
+ admit =
+ (fun ~observed:_ ~temporal:_ cs ->
+ List.map (fun (c, p, (_ : int)) -> ({ c with P.origin = c.P.origin }, p)) cs) }
(* "unconverged": two entries collide on one date (6 June), both beating
the temporal office and tied with each other, so slug decides:
@@ -416,7 +418,7 @@ module Synthetic = struct
disposition =
(fun ~winner:_ ~loser ->
match loser.P.cel.Cel.rank with R1 -> P.Transfer | R2 -> P.Commemorate P.Ordinary);
- admit = (fun ~observed:_ cs -> cs) }
+ admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p, (_ : int)) -> (c, p)) cs) }
let guard_transfer_target (_ : rank P.candidate) (origin : D.t) (_ : D.t -> rank Cel.t) = origin
@@ -434,7 +436,7 @@ module Synthetic = struct
let adm_c_entry = mk_entry ~month:9 ~day:9 ~slug:"adm-c" ~rank:R2
let adm_layer = Layer.of_entries ~id:"adm" ~name:"adm" [ adm_a_entry; adm_b_entry; adm_c_entry ]
- let adm_compare_slug (c1, _) (c2, _) = Slug.compare c1.P.cel.Cel.slug c2.P.cel.Cel.slug
+ let adm_compare_slug (c1, _, _) (c2, _, _) = Slug.compare c1.P.cel.Cel.slug c2.P.cel.Cel.slug
let rec adm_take n = function
| [] -> []
@@ -444,9 +446,10 @@ module Synthetic = struct
{ P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10);
disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary);
admit =
- (fun ~observed:_ cs ->
+ (fun ~observed:_ ~temporal:_ cs ->
let sorted = List.stable_sort adm_compare_slug cs in
- if List.length sorted mod 2 = 1 then adm_take 2 sorted else adm_take 1 sorted) }
+ let taken = if List.length sorted mod 2 = 1 then adm_take 2 sorted else adm_take 1 sorted in
+ List.map (fun (c, p, (_ : int)) -> (c, p)) taken) }
(* "observed": two DIFFERENT layer entries sharing one slug -- a realistic
data mistake (a renamed or duplicated entry), not prevented by
@@ -475,7 +478,7 @@ module Synthetic = struct
disposition =
(fun ~winner:_ ~loser ->
match loser.P.cel.Cel.rank with R1 -> P.Transfer | R2 -> P.Commemorate P.Ordinary);
- admit = (fun ~observed:_ cs -> cs) }
+ admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p, (_ : int)) -> (c, p)) cs) }
let collide_d2 = match D.make ~year:2026 ~month:2 ~day:10 with Ok d -> d | Error e -> failwith e
let collide_transfer_target (_ : rank P.candidate) (_ : D.t) (_ : D.t -> rank Cel.t) = collide_d2
@@ -492,7 +495,7 @@ module Synthetic = struct
let clean_sanctoral_rules : (season, rank) P.rules =
{ P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10);
disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary);
- admit = (fun ~observed:_ cs -> cs) }
+ admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p, (_ : int)) -> (c, p)) cs) }
end
open Synthetic
diff --git a/tools/extract_missalemeum_oracle.py b/tools/extract_missalemeum_oracle.py
index 044aa54..a010b52 100644
--- a/tools/extract_missalemeum_oracle.py
+++ b/tools/extract_missalemeum_oracle.py
@@ -18,7 +18,7 @@
# exists for every day.
#
# One line per day, pipe-separated:
-# date|rank|colors|title|tempora|commemorations|displaced|n_masses
+# date|rank|colors|title|tempora|commemorations|displaced|n_masses|commemoration_ids
#
# - rank/colors/title/tempora/commemorations/displaced are info.rank,
# info.colors (sorted, concatenated, e.g. "pv"), info.title, info.tempora
@@ -31,6 +31,17 @@
# colors/tempora/commemorations/displaced are IDENTICAL across every Mass
# of the same day for all 730 days -- checked below, not assumed; see the
# task report for why entry[0] loses nothing).
+# - commemoration_ids (Task B, branch ef-rg16a) is the ";"-joined info.
+# commemorations[*].id, index-aligned with the commemorations field ("-"
+# for an empty list, same convention) -- e.g. "sancti:01-05:4:r". Added so
+# test_oracle.ml's identity comparison has a second, independent signal
+# beyond the title text (the id encodes the commemorated saint's own rank
+# and colour too, verified across the whole fixture to always carry the
+# SAME calendar date as the day itself -- a commemoration's own natural
+# fixed date, by construction, since only a saint impeded on their own day
+# is ever commemorated there). Never parsed for its date component by this
+# fixture or the comparator (info.rank/colors already give the day's own
+# values); kept opaque and compared as a plain string.
# - Spaces in tempora are turned to "_" (matching the "no field has an
# internal space" convention test/fixtures/lectio-ef-2005-2050.txt already
# uses, so this fixture can be read the same simple way -- split on '|',
@@ -62,8 +73,9 @@ def main():
if first[k] != o[k]:
print(f"WARNING: {date} masses disagree on {k}: {first[k]!r} vs {o[k]!r}", file=sys.stderr)
comm_titles = [c["title"] for c in first["commemorations"]]
+ comm_ids = [c["id"] for c in first["commemorations"]]
disp_titles = [d["title"] for d in first["displaced"]]
- for t in [first["title"]] + comm_titles + disp_titles:
+ for t in [first["title"]] + comm_titles + comm_ids + disp_titles:
if "|" in t or ";" in t:
print(f"ERROR: {date}: field {t!r} contains a delimiter this fixture uses", file=sys.stderr)
return 1
@@ -71,7 +83,10 @@ def main():
tempora = (first["tempora"] or "-").replace(" ", "_")
comms = ";".join(comm_titles) or "-"
disp = ";".join(disp_titles) or "-"
- rows.append(f"{date}|{first['rank']}|{colors}|{first['title']}|{tempora}|{comms}|{disp}|{len(data)}")
+ ids = ";".join(comm_ids) or "-"
+ rows.append(
+ f"{date}|{first['rank']}|{colors}|{first['title']}|{tempora}|{comms}|{disp}|{len(data)}|{ids}"
+ )
if len(rows) != 730:
print(f"ERROR: expected 730 days, got {len(rows)}", file=sys.stderr)