summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-17 21:45:47 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-17 21:45:47 +0200
commitcffb879fa124c22acd400f59152a57d20cec036f (patch)
treed44a6a1f80828b356ec122483f6fd71701b36e71 /lib
parent6e42b2f524b283f43e05a967295e244e4083725f (diff)
downloadcolitur-cffb879fa124c22acd400f59152a57d20cec036f.tar.gz
colitur-cffb879fa124c22acd400f59152a57d20cec036f.zip
feat(ef): the votive Mass of Our Lady on Saturday (RG 309(a))
RG 78's office has been built since ef-bvm-saturday: an otherwise unoccupied IV-class Saturday is de sancta Maria in sabbato, white, IV class. The Mass stayed the feria's, so the day observed Our Lady and then read Colossians on the parable of the weeds. That is M26 shape 1. RG 309(a) is the rule -- the Masses the Missal assigns "iuxta temporum diversitatem" -- and it prints five, each under its own season heading. All ten citations are transcribed from the scans with line numbers in the source. Masses II-V were confirmed twice, against the scan and against a live missalemeum capture of 2038 which names them and agrees on both readings. Mass I rests on the scan alone: no oracle year to hand has an Advent Saturday carrying this office. One witness where the others have two, and the code says so rather than blurring it. The mapping looked like the hard part and dissolved. The Missal's ranges are cut by civil dates and movable feasts, not by this rite's seasons -- II ends mid-season at the Purification, III spans four seasons. But measured against what a IV-class Saturday can actually be, it reduces to a seasonal mapping plus one date test at 2/3 February, with no Easter arithmetic at all: III's end to IV's start leaves the Triduum unassigned, unreachable because Holy Saturday is I class; IV's end to V's start leaves Pentecost week unassigned, also unreachable because that week's Saturday is an Ember Saturday. Time after Pentecost then begins exactly at Trinity, exactly where Mass V begins. Both gaps verified by sweep -- zero IV-class Saturdays in either across 2000-2059 -- not inferred. The office is identified structurally, never off the slug, which it deliberately shares with the ordinary feria: subject Bvm, IV class, Saturday. Blast radius: 87611 reading rows over the full domain, every one a Saturday. Allow-lists: M26 27 to 6, shape 1 gone, leaving only the Christ-the-King residue argued in colitur's favour last commit. The 2038 suite's BVM-SATURDAY-MASS class is removed rather than zeroed -- an id with no rows must not be declared. M18 355 to 376. C17 widened 397 to 445, taking its own Saturdays back from C1, C19 and C25, since one cause should not be filed under two ids; C31 89 to 103; C25 closed at 0 rows, its Holy-Name-week Saturdays now answered before step 3 is reached. Three unit tests pinned the old behaviour and are corrected rather than re-pinned: two asserted the day "keeps its ferial Mass", which was the honest thing to assert while this was unimplemented. The third still tests what it always did -- that step 4 refuses a temporal office -- and only what answers instead has changed. Register: section 6.13.
Diffstat (limited to 'lib')
-rw-r--r--lib/rites/rite_ef/lectionary_ef.ml99
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/rites/rite_ef/lectionary_ef.ml b/lib/rites/rite_ef/lectionary_ef.ml
index 329faff..216c2c4 100644
--- a/lib/rites/rite_ef/lectionary_ef.ml
+++ b/lib/rites/rite_ef/lectionary_ef.ml
@@ -141,6 +141,94 @@ let days_since_sunday : Date.weekday -> int = function
| Date.Fri -> 5
| Date.Sat -> 6
+(* ---- The votive Mass of Our Lady on Saturday (RG 309(a)) ----
+
+ RG 78 gives the OFFICE: "In sabbatis, in quibus occurrit Officium de feria
+ IV classis, fit de sancta Maria in sabbato" -- and Temporal_ef has built
+ that since the ef-bvm-saturday task, white and IV class. What it did NOT
+ build is WHICH MASS is said, so the day observed Our Lady and then read the
+ feria's own Epistle and Gospel: white, IV class, de sancta Maria, and
+ Colossians on the parable of the weeds. That is test_oracle.ml's own M26
+ shape 1.
+
+ RG 309(a) (LT.txt:2445-2447) is the rule: "in Ecclesia universa, Missae quae
+ pro sancta Maria in sabbato, IUXTA TEMPORUM DIVERSITATEM, in Missali
+ assignantur" -- the Masses the Missal assigns according to the diversity of
+ SEASONS. It prints five, each under its own season heading (the "Missae de
+ sancta Maria in sabbato" section, scan1.txt:42982-43290):
+
+ I TEMPORE ADVENTUS
+ II A NATIVITATE DOMINI USQUE AD PURIFICATIONEM
+ III A DIE 3 FEBRUARII USQUE AD FERIAM IV HEBDOMADAE SANCTAE
+ IV TEMPORE PASCHALI
+ V A FESTO SS. TRINITATIS USQUE AD SABBATUM ANTE DOMINICAM I ADVENTUS
+
+ THE MISSAL'S RANGES ARE NOT THIS RITE'S SEASONS, and that looked like the
+ hard part: II ends at the Purification, mid-season; III runs from a civil
+ date to a movable one, spanning four of the eight seasons. But measured
+ against what a IV-class Saturday can actually BE, it collapses to a
+ seasonal mapping plus one date test:
+
+ - Mass II vs III splits at 2/3 February, inside Time_after_epiphany. That
+ is the ONLY boundary needing a date, and it is a fixed civil one.
+ - III's end (Feria IV of Holy Week) and IV's start (Paschaltide) leave the
+ Triduum unassigned -- UNREACHABLE: Holy Saturday is I class, so no
+ IV-class Saturday exists there.
+ - IV's end and V's start (Trinity) leave Pentecost week unassigned --
+ ALSO UNREACHABLE, and verified rather than assumed: colitur puts
+ Pentecost week in Paschaltide and its Saturday is [ef-pentecost-ember-sat],
+ an Ember Saturday, never IV class. Time_after_pentecost then begins
+ exactly at Trinity Sunday, which is exactly where Mass V begins.
+
+ So no Easter arithmetic is needed here at all. Both gaps are covered by
+ dedicated tests rather than left to inference.
+
+ CITATION WITNESSES, stated because they differ: Masses II-V were each
+ confirmed twice, against the scan AND against a live missalemeum capture of
+ 2038 which names them ("II Mass of the B. V. M.", "III Mass...", and so
+ on). Mass I rests on the SCAN ALONE -- no oracle year to hand has an Advent
+ Saturday carrying this office, so its two citations have one witness where
+ the others have two. *)
+let bvm_saturday_citations season ~month ~day =
+ let cite first gospel =
+ [ { Citation.part = Citation.First; reference = first };
+ { Citation.part = Citation.Gospel; reference = gospel } ]
+ in
+ match (season : Vocab_ef.season) with
+ (* I -- Tempore Adventus. Isai. 7, 10-15 (scan1.txt:43008-43009) /
+ Luc. 1, 26-38 (scan1.txt:42998-42999). *)
+ | Vocab_ef.Advent -> cite "Isa 7:10-15" "Luke 1:26-38"
+ (* II -- A Nativitate Domini usque ad Purificationem. Tit. 3, 4-7
+ (scan1.txt:43056-43057) / Luc. 2, 15-20 (scan1.txt:43096-43097). *)
+ | Vocab_ef.Christmastide -> cite "Titus 3:4-7" "Luke 2:15-20"
+ | Vocab_ef.Time_after_epiphany when month = 1 || (month = 2 && day <= 2) ->
+ cite "Titus 3:4-7" "Luke 2:15-20"
+ (* III -- A die 3 februarii usque ad feriam IV Hebdomadae Sanctae.
+ Eccli. 24, 14-16 (scan1.txt:43121-43122) / Luc. 11, 27-28
+ (scan1.txt:43165-43166). *)
+ | Vocab_ef.Time_after_epiphany | Vocab_ef.Septuagesima | Vocab_ef.Lent | Vocab_ef.Passiontide ->
+ cite "Ecclus 24:14-16" "Luke 11:27-28"
+ (* IV -- Tempore paschali. Eccli. 24, 14-16 (scan1.txt:43177-43178) /
+ Io. 19, 25-27 (scan1.txt:43202-43203). *)
+ | Vocab_ef.Paschaltide -> cite "Ecclus 24:14-16" "John 19:25-27"
+ (* V -- A festo Ss. Trinitatis usque ad sabbatum ante dominicam I Adventus.
+ Eccli. 24, 14-16 (scan1.txt:43224-43226) / Luc. 11, 27-28
+ (scan1.txt:43250-43252). *)
+ | Vocab_ef.Time_after_pentecost -> cite "Ecclus 24:14-16" "Luke 11:27-28"
+
+(* The office is identified STRUCTURALLY, never off the slug -- it deliberately
+ reuses the ordinary ferial slug (ef-bvm-saturday task: a bespoke one would
+ have broken Validate's own slug-uniqueness-per-year invariant, since the
+ office recurs many times a year). Three conditions, all necessary: [Bvm]
+ subject, IV class, and a Saturday. A Marian FEAST on a Saturday carries
+ [Bvm] too, but has its own citations and so is answered by step 1 long
+ before reaching here; the rank and weekday tests close the gap anyway. *)
+let is_bvm_saturday_office (observed : Vocab_ef.rank Celebration.t)
+ (temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) =
+ observed.Celebration.subject = Subject.Bvm
+ && observed.Celebration.rank = Vocab_ef.Class4
+ && temporal.Temporal.weekday = Date.Sat
+
let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at =
match observed.Celebration.citations with
| _ :: _ as cs -> cs
@@ -241,6 +329,17 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at =
with
| Some cs -> cs
| None -> (
+ (* The votive Mass of Our Lady on Saturday (RG 309(a)) runs HERE:
+ after the proper (step 1) and the Common (step 4), which answer
+ for a saint who beat the feria, and BEFORE the temporal slug
+ lookup -- which is exactly what used to answer, with the feria's
+ own Mass, on a day whose office is Our Lady's. Placing it later
+ would be dead code; placing it earlier would let it outrank a
+ real saint's proper. *)
+ if is_bvm_saturday_office observed temporal then
+ bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date)
+ ~day:(Date.day date)
+ else
match Lectionary.find lectionary temporal.Temporal.office.Celebration.slug with
| Some cs -> cs
| None -> (