aboutsummaryrefslogtreecommitdiff
path: root/lib/rites/rite_ef
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 15:57:00 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 15:57:00 +0200
commit044aa0dccbfe76ac9afd299af6074296eeb2cca3 (patch)
tree9644322df6125db398060b6b24481a65dda29912 /lib/rites/rite_ef
parent36eba4eff58162cbe4c7b4ff1b9d049432fc1acc (diff)
downloadcolitur-044aa0dccbfe76ac9afd299af6074296eeb2cca3.tar.gz
colitur-044aa0dccbfe76ac9afd299af6074296eeb2cca3.zip
temporal(ef): the votive Office of the BVM on Saturday, RG 91 entry 27
RG 91 entry 27, "Officium sanctae Mariae in sabbato", sits in the Table of Precedence between entry 26 (III-class vigils) and entry 28 (IV-class ferias). Precedence_ef.band already routed a plain IV-class Saturday feria to entry 27's own band value, but nothing in Temporal_ef.temporal ever constructed the office itself, so an otherwise-unoccupied Saturday still surfaced with a bare ferial slug and its season's ordinary colour. Established from Caput IX of the Rubricae Generales, both photographic scans and the electronic transcription, word for word (no scan-vs-transcription conflict: RG 78/79 are General Rubrics prose, not the Mass-propers body text the transcription is documented elsewhere as missing almost all of): "78. In sabbatis, in quibus occurrit Officium de feria IV classis, fit de sancta Maria in sabbato. 79. Officium sanctae Mariae in sabbato incipit a Matutino et explicit post Nonam." RG 78's own protasis IS "otherwise unoccupied IV-class Saturday" -- every Saturday whose temporal candidate would otherwise be Class4, across every season that rank reaches (Christmastide, Septuagesima, Time after Epiphany, Time after Pentecost, ordinary Paschaltide). Nothing else was needed to decide "otherwise unoccupied": band's own entry-27 branch already reads rank/weekday on the temporal candidate unconditionally and only wins the day when nothing outranks it -- RG 78's own condition, decided by the existing occurrence machinery. Colour is white, unconditionally, per RG 120(b) ("Adhibetur color albus in Officio et Missa de festis: ... b) B. Mariae Virg."), not RG 119/127/ 128's seasonal rules -- this office is never "de Tempore" for colour purposes, so it overrides the season's own violet/green. The slug is deliberately left UNCHANGED (reused from whatever the generic <season>-<week>-<weekday> ferial fallback would already have produced), for two independent reasons: it matches the Sacred Triduum's own precedent (identified structurally, off rank/weekday, never off the slug), and a bespoke uniform slug would have broken Colitur_kernel.Validate's own slug-uniqueness-per-liturgical-year invariant, sighted zero times before this task -- confirmed directly by writing it that way first and watching the landmark-years test fail. Subject is tagged Bvm (currently inert for precedence -- only Lord is ever read by band/disposition/admit) and the name is the Latin "Officium sanctae Mariae in sabbato" (RG 91 entry 27's own table title and RG 79's own heading), deliberately not English, the same zero-circularity discipline Holy Family/Holy Name/the Sacred Triduum already established. The I-V numbered "Missae de sancta Maria in sabbato" (both scans) are a Mass-propers selection detail (RG 309(a): "iuxta temporum diversitatem") governing which readings/texts are said, not which office is kept -- colitur computes no citations yet (Plan 4), so this is deliberately not modelled here. Two pre-existing tests needed correction, not because they were wrong before, but because RG 78 genuinely changes their dates' own facts: a Saturday inside the Holy Name of Jesus window (3 January) and two Saturdays inside christmastide_feria_slug's own "-0-"/"-2-" stretches (26 December, 10 January) are all otherwise-unoccupied Class4 Saturdays, so they now legitimately carry the BVM office instead of staying a bare Temporal-subject feria.
Diffstat (limited to 'lib/rites/rite_ef')
-rw-r--r--lib/rites/rite_ef/temporal_ef.ml180
1 files changed, 173 insertions, 7 deletions
diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml
index 4b59ff4..2188ce3 100644
--- a/lib/rites/rite_ef/temporal_ef.ml
+++ b/lib/rites/rite_ef/temporal_ef.ml
@@ -580,6 +580,143 @@ let ferial_rank d s =
let weekday_word d = Date.weekday_to_string (Date.weekday d)
+(* RG 91 entry 27, "Officium sanctae Mariae in sabbato" -- the votive Office of
+ the BVM on Saturday. Caput IX of the Rubricae Generales, both photographic
+ scans and the electronic transcription, word for word (docs/research/
+ rules-register.md §4/§6; no scan-vs-transcription conflict -- RG 78/79 are
+ General Rubrics prose, not the Mass-propers body text the transcription is
+ documented elsewhere as missing almost all of):
+
+ "78. In sabbatis, in quibus occurrit Officium de feria IV classis, fit
+ de sancta Maria in sabbato.
+ 79. Officium sanctae Mariae in sabbato incipit a Matutino et explicit
+ post Nonam."
+
+ -- "On Saturdays on which the Office of a IV-class feria occurs, [the
+ Office] is made of Holy Mary on Saturday [instead]. The Office of Holy
+ Mary on Saturday begins at Matins and ends after None." RG 78's own
+ protasis is exactly "otherwise unoccupied IV-class Saturday": WHICH
+ Saturdays qualify is not a season list to hand-maintain -- it is simply
+ every Saturday whose temporal candidate would otherwise be
+ {!Vocab_ef.Class4} (RG 91 entry 28's own unqualified ferial catch-all,
+ [ferial_rank] above), from ANY season that ferial rank reaches
+ (Septuagesima, Time after Epiphany, Time after Pentecost, and ordinary
+ Paschaltide Saturdays outside the privileged Easter/Pentecost octaves, and
+ the Christmastide ferial stretches [christmastide_feria_slug] builds --
+ Advent/Lent/Passiontide Saturdays are already Class2/Class3, higher than
+ IV class, so RG 78's protasis never fires there, and Ember/Rogation/
+ privileged-octave Saturdays are excluded the same way). Nothing else is
+ needed to decide "otherwise unoccupied": {!Precedence_ef.band}'s own
+ entry-27 branch already reads [rank = Class4 && weekday = Sat] on the
+ TEMPORAL candidate unconditionally (312 966 times across the domain, per
+ the task report) and only ever WINS the day (becomes [observed]) when
+ nothing of better table position contests it -- exactly RG 78's own
+ condition, decided by the existing occurrence machinery, not re-derived
+ here. When a real sanctoral feast DOES win such a Saturday outright, RG
+ 78's protasis is false for that day (the IV-class Office never "occurs"
+ there to begin with), and this candidate simply loses/omits exactly as
+ the plain ferial candidate it replaces already did (RG 26, {!disposition}
+ in precedence_ef.ml) -- verified: no change to {!Precedence_ef.band},
+ {!Precedence_ef.disposition} or {!Precedence_ef.admit} was needed for
+ this, since RANK stays {!Vocab_ef.Class4} either way and none of those
+ three functions reads slug/colour/name to decide who wins, what a loser's
+ fate is, or how many commemorations are admitted.
+
+ Rank: IV class, RG 91's own table position, unconditional ("Dies
+ liturgici IV classis: 27. Officium sanctae Mariae in sabbato. 28. Feriae
+ IV classis." -- both scans, register §4).
+
+ Colour: white, ALWAYS, regardless of season -- RG 120(b) (Caput XVIII,
+ "De coloribus paramentorum", "B) De colore albo"), both photographic
+ scans: "120. Adhibetur color albus in Officio et Missa de festis: ... b)
+ B. Mariae Virg." -- white is used in the Office and Mass of feasts ... of
+ the Blessed Virgin Mary. NOT RG 119 (the "de Tempore" white rule for
+ Christmastide/Paschaltide) or RG 127/128 (season green/violet): this
+ Office is never "de Tempore" for colour purposes, so it overrides
+ [season_colour] unconditionally, including on Septuagesima (violet) and
+ Time-after-Epiphany/-Pentecost (green) Saturdays -- confirmed against the
+ oracle (missalemeum, 1 August 2026, a Time-after-Pentecost Saturday:
+ white, not the season's green). The Missal's own "Missae de sancta Maria
+ in sabbato" section (both scans) carries no per-Mass colour override the
+ way some other votive Masses do elsewhere in the same scan ("In hac Missa
+ adhibetur color albus") -- it needs none, RG 120(b) already settles it
+ unconditionally for every occurrence.
+
+ Name: "Officium sanctae Mariae in sabbato" -- RG 91 entry 27's own table
+ title AND RG 79's own heading, both photographic scans and the electronic
+ transcription, word for word. Latin only, not English -- the same
+ zero-circularity discipline {!holy_family_sunday}/{!holy_name_names}/
+ {!triduum_names} already established: an English name would mean reading
+ missalemeum's own title text, the oracle this axis is compared against,
+ to decide colitur's own "ground truth" name.
+
+ Subject: [Bvm] -- simply true (RG 91 entry 27's own title names the BVM
+ directly) and currently inert for precedence purposes: neither
+ {!Precedence_ef.band}, {!Precedence_ef.disposition} nor
+ {!Precedence_ef.admit} tests [subject = Bvm] anywhere today (only [=
+ Lord] is ever read) -- the same "tagged anyway because it is simply true"
+ reasoning {!triduum_names}'s own [subject = Lord] tag already used for
+ the identical shape. Checked for a live interaction with the one other
+ [Bvm]-tagged entry this codebase's data carries
+ (data/ef/adjustments.sexp's `most-holy-name-of-mary`, 12 September,
+ Class3 Feast, not Commemoration_only): whenever 12 September falls on a
+ Saturday it wins outright over any Class4 candidate ({!Precedence_ef.band}
+ entry 24 beats entry 27 on table order alone), so this Office and that
+ entry can never coexist as a winner/commemorated-loser pair -- no live
+ RG 112(d) witness is created by this tag.
+
+ Slug: UNCHANGED -- deliberately reuses whatever
+ [christmastide_feria_slug]/the generic <season>-<week>-<weekday> ferial
+ fallback would already have produced for this date (e.g.
+ "ef-septuagesima-2-saturday", "ef-time-after-pentecost-8-saturday"), not
+ a new bespoke key. Two independent reasons, not one:
+ (1) PRECEDENT: the SAME shape as the Sacred Triduum ({!triduum_names}'s
+ own citation above) -- "the slug deliberately STAYS the generic ...
+ key... identified structurally... never off the slug" -- and
+ {!Precedence_ef.band}'s own entry-27 branch already reads [rank = Class4
+ && weekday = Sat] on the temporal candidate structurally, never its slug,
+ so nothing needs a bespoke key to find this office.
+ (2) A bespoke season-independent slug would have been actively WRONG:
+ [Colitur_kernel.Validate]'s own ["slugs"] check (validate.ml) asserts
+ every OBSERVED slug is sighted at most once per liturgical year, verified
+ with ZERO exceptions across the whole 1583-9999 domain before this task
+ (register/CLAUDE.md's own carried item 4) -- a single uniform
+ "ef-bvm-saturday" would be sighted 4-9 times in most liturgical years
+ (every otherwise-unoccupied Saturday), breaking that invariant for real,
+ not merely in theory (confirmed by writing it that way first: [Validate]'s
+ own landmark-years test failed immediately, 1583 alone sighting it on 5
+ dates). Reusing the season-keyed ferial slug keeps the invariant intact
+ with no change to [Validate] at all, since season+week+weekday is already
+ guaranteed unique within a liturgical year by construction. It also
+ dovetails with the FIVE numbered "Missae de sancta Maria in sabbato" the
+ Missal's own Common of the BVM prints immediately afterward ("MISSAE DE
+ S. MARIA IN SABBATO QUAE DICI ETIAM POSSUNT ALIIS DIEBUS UT VOTIVAE DE B.
+ MARIA VIRGINE, IUXTA RUBRICAS VEL, EX INDULTO, PRO TEMPORUM DIVERSITATE":
+ I "Tempore Adventus", II "A Nativitate Domini usque ad Purificationem",
+ III "A die 3 Februarii usque ad feriam IV Hebdomadae sanctae", IV
+ "Tempore Paschali", V "A festo Ss. Trinitatis usque ad sabbatum ante
+ dominicam I Adventus" -- both photographic scans, word for word, matching
+ the oracle's own "V Mass of the B. V. M." title on a Time-after-Pentecost
+ Saturday): a season-keyed slug leaves room for a future lectionary
+ bootstrap (Plan 4) to map each one onto its corresponding numbered Mass's
+ propers, the same way [sunday_slug]'s own season-keyed Sunday slugs
+ already anchor the ordinary lectionary. RG 309(a)'s own words -- "Missae
+ quae pro sancta Maria in sabbato, IUXTA TEMPORUM DIVERSITATEM, in Missali
+ assignantur" -- confirm this is a MASS-TEXT selection detail (which
+ PROPERS are said), not an OFFICE-identity one; colitur computes no
+ citations/readings at all yet ([citations] is empty on every day) --
+ deliberately not modelled further here, recorded per the task report. The
+ Missal's own five-season partition for the Mass numbering does not even
+ align with this rite's own RG 71-77 season boundaries (its own "III"
+ spans Septuagesima, all of Lent and most of Passiontide as ONE bracket),
+ one further reason not to try to derive a "Mass number" field from
+ [Vocab_ef.season] here. *)
+let bvm_saturday_names =
+ Colitur_kernel.Names.of_list
+ [ (Colitur_kernel.Lang.of_string_exn "la", "Officium sanctae Mariae in sabbato") ]
+
+let is_bvm_saturday d (rank : Vocab_ef.rank) = Date.weekday d = Date.Sat && rank = Class4
+
let temporal d =
let y = Date.year d in
let easter = Computus.gregorian_easter y in
@@ -773,8 +910,22 @@ let temporal d =
else (
match christmastide_feria_slug d with
| Some slug ->
- build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s)
- ~week:(week d) ()
+ (* Every Christmastide feria this branch builds is
+ Class4 ([ferial_rank]'s own catch-all -- Christmastide
+ is never Advent/Lent/Passiontide), so
+ [is_bvm_saturday]'s rank test is always true here; the
+ weekday is the only real condition. See
+ [bvm_saturday_names]'s own citation above for the full
+ argument (rank/colour/name/subject) -- the SLUG stays
+ [slug], the same one this branch would otherwise have
+ built, per that same citation's own "Slug" paragraph
+ (not re-quoted at this function's two call sites). *)
+ if is_bvm_saturday d Class4 then
+ build ~subject:Colitur_kernel.Subject.Bvm ~names:bvm_saturday_names ~season:s ~slug
+ ~colour:Colour.White ~rank:Class4 ~week:(week d) ()
+ else
+ build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s)
+ ~week:(week d) ()
| None ->
(* The days between Ash Wednesday and Lent I have proper
Masses and belong to no numbered week. *)
@@ -784,6 +935,26 @@ let temporal d =
~slug:(Printf.sprintf "ef-lent-after-ashes-%s" (weekday_word d))
~colour:Colour.Violet ~rank:Class3 ~week:None ()
else
+ let week_n = week d in
+ let slug =
+ Printf.sprintf "ef-%s-%d-%s" (season_slug_word s)
+ (Option.value week_n ~default:0) (weekday_word d)
+ in
+ if is_bvm_saturday d (ferial_rank d s) then
+ (* RG 78 (Caput IX, "De sancta Maria in sabbato") --
+ see [bvm_saturday_names]'s own citation above for
+ the full argument. This is the ordinary-season
+ half of the two call sites: Septuagesima, Time
+ after Epiphany, Time after Pentecost, and
+ ordinary Paschaltide Saturdays outside the
+ privileged Easter/Pentecost octaves are exactly
+ the seasons [ferial_rank] gives Class4 outside
+ Christmastide (the other call site, above). The
+ SLUG stays [slug], just computed above, the same
+ one this branch would otherwise have built. *)
+ build ~subject:Colitur_kernel.Subject.Bvm ~names:bvm_saturday_names ~season:s ~slug
+ ~colour:Colour.White ~rank:Class4 ~week:week_n ()
+ else
let colour =
(* The Pentecost octave weekdays are red, not Paschaltide's white. *)
if days_between easter d >= 50 && days_between easter d <= 55 then Colour.Red
@@ -817,11 +988,6 @@ let temporal d =
else if days_between easter d = -3 then Colour.White
else season_colour s
in
- let week_n = week d in
- let slug =
- Printf.sprintf "ef-%s-%d-%s" (season_slug_word s)
- (Option.value week_n ~default:0) (weekday_word d)
- in
(* [triduum_names]'s own citation above: identity only,
for the three days of the Sacred Triduum -- every
other ferial day here stays unnamed, subject