diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-24 16:29:23 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-24 16:29:23 +0200 |
| commit | 8a5da8756cf6b57aa36c01b71ce893f7967d3a29 (patch) | |
| tree | 10873a692400fa25ce54c67ac9fc34d46af86272 /lib/rites/rite_ef/lectionary_ef.ml | |
| parent | 4f87cbde4ee79ac96aa7ebfed105b3a5ec02be43 (diff) | |
| parent | 73b15551804bb63ee0081005e2869d36afb54be2 (diff) | |
| download | colitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.tar.gz colitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.zip | |
merge: celebrant Mass rubrics, and four rubrical corrections
colitur now prints what a real ordo prints for the Mass: which formulary is
said and how it was reached, the Gloria, the Creed, the preface, and the
commemorations with their Low-Mass/sung distinction. colitur rubrics joins
day and readings.
Four defects were found and fixed on the way, each by an external witness
rather than by inspection: the Creed said at Requiem Masses (RG 476(f)),
the missing bissextile shift of St Matthias and St Gabriel (2 041 leap
years), Rogation Monday and Tuesday coloured violet in Paschaltide (RG
119(b)), and the ferias after the Ascension resuming the wrong Sunday's
Mass rather than the Ascension's.
Validation gained a sixth layer and then some: the preface is checked
against three independent publishers over seven witness-years (FIUV, three
LMS editions, three extraordinaryform.org editions), none of which shares
the Divinum Officium -> missalemeum -> lectio lineage the older layers all
descend from.
Diffstat (limited to 'lib/rites/rite_ef/lectionary_ef.ml')
| -rw-r--r-- | lib/rites/rite_ef/lectionary_ef.ml | 99 |
1 files changed, 86 insertions, 13 deletions
diff --git a/lib/rites/rite_ef/lectionary_ef.ml b/lib/rites/rite_ef/lectionary_ef.ml index d7b2497..b996412 100644 --- a/lib/rites/rite_ef/lectionary_ef.ml +++ b/lib/rites/rite_ef/lectionary_ef.ml @@ -51,9 +51,9 @@ module Commons = struct | None -> ( (* A formulary with no citations is indistinguishable at the call site from "this saint has no Common" -- [commons_for] would - return [Some []] and [readings] would emit [] either way. That - is exactly the silent hole this project does not allow, so it - is rejected here where it is still nameable. *) + return [Some (common, [])] and [readings] would emit [] either + way. That is exactly the silent hole this project does not + allow, so it is rejected here where it is still nameable. *) match List.find_opt (fun (_, cs) -> cs = []) commons with | Some (s, _) -> Error (Printf.sprintf "commons: common %S has no citations" (Slug.to_string s)) @@ -72,10 +72,19 @@ module Commons = struct (Slug.to_string saint) (Slug.to_string common)) | None -> Ok { commons; assigned }))) + (* Returns the Common's own id ALONGSIDE its citations, not the citations + alone: [readings]' step 4 needs the id to build the day's + {!Colitur_kernel.Mass_formulary.t} ("the Common's own id as its slug"), + and the id is only ever in scope here, at the point [common] is looked + up -- re-deriving it afterwards would mean a second [assoc_opt] search + over [t.assigned] for a value this function already held. *) let find t saint = match List.assoc_opt saint t.assigned with | None -> None - | Some common -> List.assoc_opt common t.commons + | Some common -> ( + match List.assoc_opt common t.commons with + | None -> None + | Some cs -> Some (common, cs)) (* Byte-for-byte the failure discipline of [Lectionary.load] (see its own comments for why each catch-all is placed where it is): every parse and @@ -250,7 +259,8 @@ let is_bvm_saturday_office (observed : Vocab_ef.rank Celebration.t) let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = match observed.Celebration.citations with - | _ :: _ as cs -> cs + | _ :: _ as cs -> + (Some { Mass_formulary.said = Some observed.Celebration.slug; via = Mass_formulary.Proper }, cs) | [] -> ( (* Step 4: a saint who is the day's observed office and has no proper says his assigned Common. The assignment is explicit, never @@ -346,7 +356,8 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = match if sanctoral_office then commons_for ~commons observed.Celebration.slug else None with - | Some cs -> cs + | Some (common_id, cs) -> + (Some { Mass_formulary.said = Some common_id; via = Mass_formulary.Common }, cs) | None -> ( (* The votive Mass of Our Lady on Saturday (RG 309(a)) runs HERE: after the proper (step 1) and the Common (step 4), which answer @@ -354,13 +365,73 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = lookup -- which is exactly what used to answer, with the feria's own Mass, on a day whose office is Our Lady's. Placing it later would be dead code; placing it earlier would let it outrank a - real saint's proper. *) + real saint's proper. + + FORMULARY PROVENANCE: [Votive], not [Own_slug] (CORRECTED, fix + round 1, coordinator review -- the first pass tagged this + [Own_slug] for lack of a better constructor and flagged it as a + judgement call; [Mass_formulary.source] has grown a [Votive] + case since, precisely for this branch). RG 431(e) + (docs/research/LT.txt, verbatim): "e) in Missis votivis IV + classis de Angelis, quocumque die, et de B. Maria Virg. quae in + sabbato celebrantur" -- votive Masses of the IV class, of the + Angels on any day, and of the BVM WHICH ARE CELEBRATED ON + SATURDAY: the Missal's own words classify this exact Mass as a + "Missa votiva", not as the day's own office's Mass, corroborated + by RG 309(a) (this branch's own header comment above, "iuxta + temporum diversitatem") naming the FIVE seasonal Masses RG 431(e) + is speaking of. Together: a votive Mass said IN PLACE of the + day's own office's Mass, the office (RG 78, Officium sanctae + Mariae in sabbato) being kept unchanged. + + CORRECTED, fix round 2 (coordinator review): fix round 1's own + comment here claimed the Latin Mass Society Ordo witnesses + [Votive] directly, printing "V Mass of BVM" with "V" read as an + abbreviation for "votive". That was the coordinator's + misreading, not this codebase's, and it was wrong: the Ordo's + "I"-"V" are ROMAN NUMERALS naming WHICH of the Missal's five + seasonal "Missae de sancta Maria in sabbato" (this branch's own + header comment; RG 309(a)'s "iuxta temporum diversitatem") is + said on a given Saturday -- not an abbreviation of anything, and + not a marker of the Mass's class or kind. All five numerals + occur through the Ordo (I x1, II x4, III x3, IV x3, V x8, + counted across the whole document); "V Mass of BVM" merely also + happens to be substring-matched by a naive search for "V Mass of + BVM" inside "IV Mass of BVM", which is what produced the + original false reading. [Votive] itself is UNAFFECTED by this + correction and stays right, on RG 431(e) alone -- only the + Ordo-witness claim is retracted, not softened, removed. A + genuinely useful consequence survives the mistake: because the + Ordo's own numeral names WHICH seasonal Mass is said, a future + comparison against it (Task 6 of this plan) can validate + [bvm_saturday_citations]'s own season-keyed SELECTION, not + merely that some BVM Mass was chosen. + + [said] used to be set HERE to the day's own temporal slug + (reasoning: [is_bvm_saturday_office] only ever fires when + [sanctoral_office] above is false, i.e. the observed + celebration already IS the day's own temporal office, which + deliberately reuses the ordinary ferial slug, [Temporal_ef]'s + own [bvm_saturday_names]). CORRECTED (whole-branch review fix + round): that value is the OFFICE's slug, not the slug whose + Mass is actually said -- the five seasonal Masses RG 309(a) + names have no slug of their own anywhere in the shipped data, + so [said] is [None] here, honestly, rather than silently + naming the wrong thing. See {!Colitur_kernel.Mass_formulary.t}'s + own [said] citation for the full account; the office itself is + not lost, it is still [observed.slug] on the very same + {!Colitur_kernel.Liturgical_day.t} this formulary lives on. *) if is_bvm_saturday_office observed temporal then - bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date) - ~day:(Date.day date) + ( Some { Mass_formulary.said = None; via = Mass_formulary.Votive }, + bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date) + ~day:(Date.day date) ) else match Lectionary.find lectionary temporal.Temporal.office.Celebration.slug with - | Some cs -> cs + | Some cs -> + ( Some + { Mass_formulary.said = Some temporal.Temporal.office.Celebration.slug; + via = Mass_formulary.Own_slug }, + cs ) | None -> ( (* Step 3: a feria with no proper of its own says the preceding Sunday's Mass. WARRANT is the same as step 2's -- lectio's own @@ -404,12 +475,14 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at = season name), so deriving one from the other textually would be a latent bug the moment a season's naming convention differs. *) let offset = days_since_sunday temporal.Temporal.weekday in - if offset = 0 then [] + if offset = 0 then (None, []) else let sunday = Date.add_days date (-offset) in let sunday_temporal = temporal_at sunday in match Lectionary.find lectionary sunday_temporal.Temporal.office.Celebration.slug with - | Some cs -> cs - | None -> []))) + | Some cs -> + let said = sunday_temporal.Temporal.office.Celebration.slug in + (Some { Mass_formulary.said = Some said; via = Mass_formulary.Preceding_sunday }, cs) + | None -> (None, [])))) |
