summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-21 22:54:13 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-21 22:54:13 +0200
commit28dc226a31fa0cc72432f5607ab5cd74503ef43d (patch)
tree35dc78657b108a5b8e5d20092a9db4c00d609284
parent384b0789c0f4d9beb936080a5592bb4aa6134295 (diff)
downloadcolitur-28dc226a31fa0cc72432f5607ab5cd74503ef43d.tar.gz
colitur-28dc226a31fa0cc72432f5607ab5cd74503ef43d.zip
fix(kernel,ef): a votive Mass is not the day's own -- add Mass_formulary.Votive
Mass_formulary.source was missing a case for a Mass said IN PLACE of the day's own office's Mass while that office is itself kept unchanged -- RG 309(a) and RG 431(e) both classify the RG 78 Saturday Mass of Our Lady this way, in the Missal's own words, as a "Missa votiva IV classis... de B. Maria Virg.", not as the day's own office's Mass. The Latin Mass Society Ordo (docs/research/ordo/lms-ordo-2024-2025.pdf) witnesses it directly, printing that day as "V Mass of BVM". The BVM-Saturday branch in Lectionary_ef.readings was tagged Own_slug for lack of a better constructor when Task 2 landed, flagged there as a judgement call rather than a specified answer. That call was wrong: left as Own_slug, a future comparison against the LMS Ordo (a later task in this plan) would read every BVM Saturday as a manufactured divergence between colitur's "own" Mass and the Ordo's votive one. Retagged to Votive; said is unchanged (still the day's own, reused ferial, temporal slug) since the office itself is unaffected, only the Mass said for it. Added the new constructor's source_to_string case ("votive") and its own test row, and pinned the branch itself in test_lectionary_ef.ml's formulary cases at 1 August 2026, verified directly against the resolver rather than assumed. Both this session's own drifted pins that the earlier commit inherited from the task brief are unaffected by this change, and both are re-confirmed independently correct in this round: dune test and the exhaustive sweep are green, and colitur day stays byte-identical against the pre-fix-round binary.
-rw-r--r--lib/kernel/mass_formulary.ml3
-rw-r--r--lib/kernel/mass_formulary.mli16
-rw-r--r--lib/rites/rite_ef/lectionary_ef.ml38
-rw-r--r--lib/rites/rite_ef/lectionary_ef.mli14
-rw-r--r--test/test_lectionary_ef.ml22
-rw-r--r--test/test_mass_formulary.ml2
6 files changed, 69 insertions, 26 deletions
diff --git a/lib/kernel/mass_formulary.ml b/lib/kernel/mass_formulary.ml
index 8151720..cb3532b 100644
--- a/lib/kernel/mass_formulary.ml
+++ b/lib/kernel/mass_formulary.ml
@@ -1,4 +1,4 @@
-type source = Proper | Own_slug | Preceding_sunday | Common [@@deriving sexp]
+type source = Proper | Own_slug | Preceding_sunday | Common | Votive [@@deriving sexp]
type t = { said : Slug.t; via : source } [@@deriving sexp]
let source_to_string = function
@@ -6,3 +6,4 @@ let source_to_string = function
| Own_slug -> "own"
| Preceding_sunday -> "preceding-sunday"
| Common -> "common"
+ | Votive -> "votive"
diff --git a/lib/kernel/mass_formulary.mli b/lib/kernel/mass_formulary.mli
index caea3eb..a2faf64 100644
--- a/lib/kernel/mass_formulary.mli
+++ b/lib/kernel/mass_formulary.mli
@@ -15,12 +15,22 @@ type source =
| Own_slug (** the lectionary's entry for the day's own slug *)
| Preceding_sunday (** a weekday with no proper resumes the preceding Sunday *)
| Common (** a saint's assigned Common *)
+ | Votive
+ (** a Mass said IN PLACE of the day's own office's Mass, the office
+ itself being kept unchanged -- RG 309(a): "in Ecclesia universa,
+ Missae quae pro sancta Maria in sabbato, iuxta temporum
+ diversitatem, in Missali assignantur", corroborated by RG 431(e)'s
+ own classification of that Mass as "Missa votiva IV classis ...
+ de B. Maria Virg." The office/Mass split this constructor exists
+ to name is general (any rite may say a votive Mass on a day whose
+ OFFICE is not itself votive), even though EF's only witness today
+ is the RG 78/309(a) Saturday Mass of Our Lady. *)
[@@deriving sexp]
type t = { said : Slug.t; via : source } [@@deriving sexp]
-(** The slug whose Mass is said. For {!Proper} and {!Own_slug} this is the day's
- own; for {!Preceding_sunday} it is that Sunday's TEMPORAL slug; for
- {!Common} it is the Common's own id. *)
+(** The slug whose Mass is said. For {!Proper}, {!Own_slug} and {!Votive}
+ this is the day's own; for {!Preceding_sunday} it is that Sunday's
+ TEMPORAL slug; for {!Common} it is the Common's own id. *)
val source_to_string : source -> string
diff --git a/lib/rites/rite_ef/lectionary_ef.ml b/lib/rites/rite_ef/lectionary_ef.ml
index 4325bed..13ff5d5 100644
--- a/lib/rites/rite_ef/lectionary_ef.ml
+++ b/lib/rites/rite_ef/lectionary_ef.ml
@@ -367,21 +367,33 @@ let readings ~lectionary ~commons ~observed ~temporal ~date ~temporal_at =
would be dead code; placing it earlier would let it outrank a
real saint's proper.
- FORMULARY PROVENANCE, a genuine judgement call: {!Mass_formulary.source}
- has no fifth constructor for "the RG 309(a) seasonal votive Mass",
- so this is tagged [Own_slug] -- [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 (the office
- deliberately reuses the ordinary ferial slug, [Temporal_ef]'s own
- [bvm_saturday_names]), so [said] is genuinely "the day's own
- slug" -- [Own_slug]'s own documented meaning
- (mass_formulary.mli's [said] comment) -- even though the
- citations themselves come from [bvm_saturday_citations]'s
- season table rather than a [Lectionary.find] hit. Flagged in the
- task report as an interpretation, not a specified answer. *)
+ 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 309(a) (this
+ branch's own header comment above) and RG 431(e) ("in Missis
+ votivis IV classis ... de B. Maria Virg. quae in sabbato
+ celebrantur", temporal_ef.ml's own colour-chain comment quotes
+ it in full) both classify this Mass itself, in the Missal's own
+ words, as a "Missa votiva" -- 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. WITNESSED, not merely
+ argued: the Latin Mass Society Ordo (docs/research/ordo/lms-
+ ordo-2024-2025.pdf) prints this exact day as "OUR LADY on
+ SATURDAY IV Cl W / V Mass of BVM" -- "V" is that Ordo's own
+ abbreviation for Votive.
+
+ [said] is UNCHANGED by this correction and stays the day's own
+ temporal slug: [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 (the office
+ deliberately reuses the ordinary ferial slug, [Temporal_ef]'s
+ own [bvm_saturday_names]) -- only [via] needed correcting, the
+ office/Mass split [Votive] exists to name. *)
if is_bvm_saturday_office observed temporal then
let said = temporal.Temporal.office.Celebration.slug in
- ( Some { Mass_formulary.said; via = Mass_formulary.Own_slug },
+ ( Some { Mass_formulary.said; via = Mass_formulary.Votive },
bvm_saturday_citations temporal.Temporal.season ~month:(Date.month date)
~day:(Date.day date) )
else
diff --git a/lib/rites/rite_ef/lectionary_ef.mli b/lib/rites/rite_ef/lectionary_ef.mli
index 2f36926..43763ff 100644
--- a/lib/rites/rite_ef/lectionary_ef.mli
+++ b/lib/rites/rite_ef/lectionary_ef.mli
@@ -109,10 +109,16 @@ val commons_for : commons:Commons.t -> Slug.t -> (Slug.t * Citation.t list) opti
- {b Step 2} -- the day's own temporal slug in the lectionary.
{!Colitur_kernel.Mass_formulary.Own_slug}, [said] that slug. The RG
309(a) Saturday votive Mass of Our Lady also answers here (structurally,
- not as a fifth numbered step): it is tagged the same way, because its
- own guard only ever fires when the observed celebration already IS the
- day's own temporal office (the office reuses the ordinary ferial
- slug) -- see the implementation comment on that branch.
+ not as a fifth numbered step), but is tagged
+ {!Colitur_kernel.Mass_formulary.Votive} instead, not [Own_slug]: RG
+ 309(a)/431(e) classify it, in the Missal's own words, as a "Missa
+ votiva" said IN PLACE of the day's own office's Mass, the office (RG
+ 78) itself being kept -- witnessed by the Latin Mass Society Ordo,
+ which prints this day's Mass as "V" (Votive). [said] is still that
+ slug: only the source constructor differs from an ordinary Step 2
+ lookup, because the guard that reaches this branch only ever fires
+ when the observed celebration already IS the day's own temporal
+ office -- see the implementation comment on that branch.
- {b Step 3} -- for a weekday whose own slug has no entry, the preceding
Sunday's temporal slug (never its observed one; a Sunday is guarded
out because it has no PRECEDING Sunday to resume, not because
diff --git a/test/test_lectionary_ef.ml b/test/test_lectionary_ef.ml
index bc2be8c..5bdce12 100644
--- a/test/test_lectionary_ef.ml
+++ b/test/test_lectionary_ef.ml
@@ -582,9 +582,10 @@ let test_commons_load_rejects_bad_data () =
(* ---------------------------------------------------------------------- *)
(* The formulary itself (Task 2): each step of the chain now reports HOW *)
-(* it resolved, not only what it resolved. One day per step -- the same *)
-(* dates this file already uses (and hand-verifies) elsewhere for the *)
-(* citations those days carry, so no new date needs independent checking. *)
+(* it resolved, not only what it resolved. One day per step, plus the RG *)
+(* 309(a) votive branch (fix round 1) -- the same dates this file already *)
+(* uses (and hand-verifies) elsewhere for the citations those days carry, *)
+(* so no new date needs independent checking. *)
(* ---------------------------------------------------------------------- *)
let formulary_cases =
@@ -605,7 +606,20 @@ let formulary_cases =
(* step 4: a saint sent to a Common -- same date as
[test_step4_commons_perpetua_and_felicity]; [said] is the Common's
OWN id (data/ef/commons.sexp), not the saint's slug. *)
- (2038, 3, 6, "common-of-non-virgins-1", Colitur_kernel.Mass_formulary.Common) ]
+ (2038, 3, 6, "common-of-non-virgins-1", Colitur_kernel.Mass_formulary.Common);
+ (* Fix round 1 (coordinator review): the RG 309(a)/RG 78 Saturday votive
+ Mass of Our Lady, structurally reached between steps 4 and 2 (see
+ [readings]' own implementation comment) but tagged [Votive], not
+ [Own_slug] -- the Missal's own RG 309(a)/431(e) classify this Mass as
+ a "Missa votiva", said in place of the day's own office's Mass while
+ the office (RG 78) itself is kept; witnessed by the Latin Mass
+ Society Ordo, which prints this day's Mass as "V" (Votive). 1 August
+ 2026 verified directly against the real resolver (`colitur day
+ 2026`), not trusted from a supplied date, given this session's own
+ drifted-pin history: a IV-class Saturday, "Officium sanctae Mariae in
+ sabbato", temporal slug [ef-time-after-pentecost-9-saturday]. [said]
+ is unaffected by the retag and stays that same (reused ferial) slug. *)
+ (2026, 8, 1, "ef-time-after-pentecost-9-saturday", Colitur_kernel.Mass_formulary.Votive) ]
let test_formulary_reports_its_source () =
List.iter
diff --git a/test/test_mass_formulary.ml b/test/test_mass_formulary.ml
index b940161..824e0c7 100644
--- a/test/test_mass_formulary.ml
+++ b/test/test_mass_formulary.ml
@@ -14,7 +14,7 @@ let test_round_trips_through_sexp () =
let test_to_string_names_the_source () =
let cases =
[ (MF.Proper, "proper"); (MF.Own_slug, "own"); (MF.Preceding_sunday, "preceding-sunday");
- (MF.Common, "common") ]
+ (MF.Common, "common"); (MF.Votive, "votive") ]
in
List.iter
(fun (via, expected) ->