aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/rites/rite_ef/precedence_ef.ml108
-rw-r--r--lib/rites/rite_ef/precedence_ef.mli17
-rw-r--r--test/test_precedence_ef.ml131
3 files changed, 248 insertions, 8 deletions
diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml
index 750da8b..87cdeeb 100644
--- a/lib/rites/rite_ef/precedence_ef.ml
+++ b/lib/rites/rite_ef/precedence_ef.ml
@@ -48,6 +48,34 @@ let universal_layer = "ef-universal"
let indult_prefix = "indult:"
let unclassified = max_int
+(* Not an RG citation -- an ordering device for RG 91 entry 14's own text
+ (scan-verified, docs/research/rules-register.md §4): "14. Festa Domini II
+ classis, PRIMUM MOBILIA, DEINDE FIXA" -- feasts of the Lord, II class,
+ MOVABLE FIRST, then fixed. Both halves are the SAME numbered table row,
+ but the primary text states a real priority between them, not merely two
+ disjoint categories -- [band]'s own entry-14 branches below must not
+ literally TIE at the shared integer 14, because a tie would fall to
+ {!Precedence.resolve}'s own kernel-level fallback ([compare_by],
+ Slug.compare), which is deliberately NOT rubric-authoritative (the exact
+ anti-pattern RG 113's own fix already corrected once for commemoration
+ ordering, this file's own header) and would in fact pick the WRONG side
+ here: "commemoration-of-the-baptism-of-the-lord" sorts before
+ "ef-time-after-epiphany-sunday-1" alphabetically, backwards from "primum
+ mobilia". Negative, so it can never collide with any real table position
+ (1..28) or [unclassified] (positive [max_int]) by construction -- not a
+ citation to some entry "13.5" that does not exist in the primary text,
+ just an ordering fact this integer has to carry because RG 91's own two
+ half-rows must compare unequal here. The one real witness today: Holy
+ Family (RG 17(b), temporal_ef.ml's own [holy_family_sunday]) against the
+ fixed Commemoration of the Baptism of the Lord (13 January) -- the only
+ date they can ever coincide, since Holy Family only ever falls 7-13
+ January and no OTHER fixed Class2-Lord sanctoral entry shares that
+ window (register §6.0's own subject audit: Transfiguration 6 Aug,
+ Exaltation of the Cross 14 Sep, Dedication of the Archbasilica 9 Nov,
+ the Purification 2 Feb, the Baptism 13 Jan -- the Baptism alone falls in
+ Holy Family's own window). *)
+let entry_14_movable_band = -14
+
let is_indult layer = String.starts_with ~prefix:indult_prefix layer
let is_universal layer = String.equal layer universal_layer
@@ -223,13 +251,28 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc
not the universal layer (11), and marked as an indult overlay (12's
"not indult" test having just failed). *)
else if (not is_temporal) && (not is_vigil) && rank = Class1 then 13
- (* 14: Feasts of the Lord, II class -- RG 91 entry 14, deliberately
- UNQUALIFIED (contrast entry 16, which explicitly says "not
- of the Lord"; RG 37c (§4, "Sundays") speaks of "II-class feasts of
- the Lord" replacing an occurring II-class Sunday with no universal
- qualifier either). No layer test here, unlike 11/12/13 and 16/19/20:
- the register does not split this entry into universal/proper/indult,
- so a proper or indult feast of the Lord still bands 14, not 19/20. *)
+ (* 14, MOVABLE half -- RG 91 entry 14's own "primum mobilia, deinde
+ fixa" ({!entry_14_movable_band}'s own comment has the full citation
+ and reasoning). Checked before the FIXED half immediately below,
+ matching the primary text's own order, though [is_temporal] already
+ makes the two branches structurally disjoint on any one candidate
+ regardless of which is checked first -- the ordering here is for a
+ reader following RG 91's own prose, not for correctness. The only
+ witness this codebase currently constructs is Holy Family
+ (temporal_ef.ml's own [holy_family_sunday] branch, the one place
+ [subject] is ever [Lord] on a temporal-origin candidate); a
+ hypothetical movable Holy-Name-of-Jesus office (RG 17(a), still
+ unbuilt as its own named day, register §6) would reach this same
+ branch too, once built, since nothing here is keyed to Holy Family's
+ own slug. *)
+ else if is_temporal && rank = Class2 && subject = Subject.Lord then entry_14_movable_band
+ (* 14, FIXED half -- RG 91 entry 14, deliberately UNQUALIFIED (contrast
+ entry 16, which explicitly says "not of the Lord"; RG 37c (§4,
+ "Sundays") speaks of "II-class feasts of the Lord" replacing an
+ occurring II-class Sunday with no universal qualifier either). No
+ layer test here, unlike 11/12/13 and 16/19/20: the register does not
+ split this entry into universal/proper/indult, so a proper or
+ indult feast of the Lord still bands 14, not 19/20. *)
else if (not is_temporal) && (not is_vigil) && rank = Class2 && subject = Subject.Lord then 14
(* 15: Sundays, II class (every Sunday not already named at 6). *)
else if is_temporal && rank = Class2 && is_sunday then entry_15_band
@@ -732,6 +775,57 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate)
the RG26 branch above gives its own [not is_vigil] guard, rather than
relying on that absence silently. *)
Precedence.Omit
+ else if winner.Precedence.cel.Celebration.subject = Subject.Lord && cel.Celebration.subject = Subject.Lord
+ then
+ (* RG 112(a) (docs/research/rules-register.md §4/§6.0, primary text,
+ verified against BOTH photographic scans -- missale-romanum-1962.pdf
+ and "Missale Romanum 1962_text.pdf" -- the electronic transcription,
+ 1962-06-23,_SS_Ioannes_XXIII,_Missale_Romanum,_LT.pdf, carries
+ NEITHER this paragraph's own worked example NOR its own more
+ specific Mass-proper rubric below, exactly the transcription's
+ documented defect, this project's own methodology note): "112. Ad
+ commemorationes et orationes quod attinet, haec insuper serventur:
+ a) Officium, Missa aut commemoratio de aliquo festo vel mysterio
+ UNIUS DIVINAE PERSONAE excludit commemorationem aut orationem de
+ alio festo vel mysterio EIUSDEM DIVINAE PERSONAE" -- the Office,
+ Mass, or commemoration of some feast or MYSTERY of ONE Divine Person
+ excludes a commemoration or oration of ANOTHER feast or mystery of
+ the SAME Divine Person.
+
+ {!Subject.t} has no finer split within [Lord] than "a mystery
+ touching the Divine Person of the Son" -- every real [subject =
+ Lord] entry this codebase's own data carries concerns Christ
+ specifically (register §6.0's subject audit: the Precious Blood, the
+ Transfiguration, the Exaltation of the Cross, the Dedication of the
+ Archbasilica, the Purification, the Baptism, and now Holy Family),
+ so reading "same Divine Person" as simply "both [Lord]" is safe at
+ today's data's own granularity -- a rite that ever needed to
+ distinguish, say, a Trinity-specific mystery from a Son-specific one
+ by Person would need a finer [Subject.t] first, not a special case
+ added here.
+
+ The one live witness -- confirmed DIRECTLY, not only by this general
+ paragraph: the Holy Family Mass propers' own note, immediately
+ following the Postcommunion, word for word on BOTH photographic
+ scans: "Si festum S. Familiae occurrerit die 13 ianuarii, Missa
+ dicitur de festo S. Familiae, SINE COMMEMORATIONE BAPTISMATIS
+ D.N.I.C., et sine commemoratione dominicae" -- if the feast of the
+ Holy Family occurs on 13 January, the Mass is said of the Holy
+ Family, WITHOUT commemoration of the Baptism of Our Lord Jesus
+ Christ, and without commemoration of the Sunday (RG 17(b)'s own
+ general rule, restated for this specific date). Independently
+ confirmed against missalemeum (register §6.0): title "The Holy
+ Family: Jesus, Mary & Joseph", commemorations [], the Baptism
+ listed only under "displaced", never commemorated.
+
+ Checked after RG 16(a) above (so a genuine RG 16(a) Sunday-
+ suppression is never re-explained under this citation instead) and
+ before the final ordinary-commemoration catch-all below, since
+ without it a [Feast]-status loser of this shape would otherwise
+ reach RG 95's ordinary "commemorated or omitted" branch and be
+ admitted as an ordinary Class2 commemoration under RG 111(b) --
+ confirmed wrong against both primary sources above. *)
+ Precedence.Omit
else
(* RG 95's other branch: "aut commemorantur aut penitus omittuntur" --
commemorated or wholly omitted. Reached by every SANCTORAL loser
diff --git a/lib/rites/rite_ef/precedence_ef.mli b/lib/rites/rite_ef/precedence_ef.mli
index b283a17..86a0ead 100644
--- a/lib/rites/rite_ef/precedence_ef.mli
+++ b/lib/rites/rite_ef/precedence_ef.mli
@@ -62,6 +62,15 @@ val ember_prefixes : string list
new rule, not a silently wrong one. *)
val unclassified : int
+(** RG 91 entry 14's own text (§4): "Festa Domini II classis, primum
+ mobilia, deinde fixa" -- feasts of the Lord, II class, MOVABLE first,
+ then fixed. {!band}'s value for the movable half (Holy Family, RG
+ 17(b)) -- strictly better than the fixed half's own literal [14],
+ negative so it can never collide with a real table position or
+ {!unclassified}. See precedence_ef.ml's own comment for the full
+ citation and why the two halves must not literally tie. *)
+val entry_14_movable_band : int
+
(** [band ctx c]: RG 91's Table of Precedence. Returns the table's own entry
number -- I class 1-13, II class 14-21, III class 22-26, IV class 27-28;
lower wins (see {!Precedence.rules.band}) -- EXCEPT where the table's own
@@ -134,6 +143,14 @@ val sunday_marker : string
weekday, never a saint's day, and RG 111(c)/(d) admit an "ordinary"
commemoration of a losing SAINT freely, with no such class-keyed
gate);
+ - a loser whose [subject] is [Lord] AND whose WINNER's [subject] is also
+ [Lord] is [Omit] (RG 112(a) -- a feast or mystery of one Divine Person
+ excludes a commemoration of another feast or mystery of the SAME
+ Divine Person; live witness: Holy Family, RG 17(b), excluding the
+ fixed Commemoration of the Baptism of the Lord on the years 13
+ January is itself Holy Family's own date -- see the .ml's own comment
+ for the primary text, including the Holy Family Mass propers' own
+ more specific 13-January rubric, on both photographic scans);
- everything else -- including an impeded I-class Sunday, and a
SANCTORAL loser of any rank below I class -- is [Commemorate],
carrying its real RG 109 privilege (see {!admit} below); RG 109(a)
diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml
index 2935e40..01a54c0 100644
--- a/test/test_precedence_ef.ml
+++ b/test/test_precedence_ef.ml
@@ -138,6 +138,30 @@ let cases =
cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:"diocese-warsaw"
"ef-local-feast-of-the-lord",
14 );
+ (* Entry 14, MOVABLE half -- RG 91 entry 14's own text (§4, scan-verified):
+ "Festa Domini II classis, PRIMUM MOBILIA, DEINDE FIXA" -- movable
+ FIRST, then fixed. Holy Family (RG 17(b), temporal_ef.ml's own
+ [holy_family_sunday]) is the one movable Class2 Lord feast this
+ codebase builds -- sourced from [Temporal_ef.temporal]'s own real
+ output ([of_temporal], the same review-finding-3 discipline entry
+ 18's own Ember row above uses), not a hand-typed slug, so a rename
+ or a dropped [~subject:Lord] on temporal_ef.ml's own side fails this
+ row too, not only test_temporal_ef.ml's. Must be a value STRICTLY
+ BETTER than the fixed half's own literal 14 immediately above (not
+ merely different) -- the two are structurally disjoint by [is_temporal]
+ alone so they can never literally collide on any one candidate, but
+ {!compare_by}'s own kernel-level tie-break (Slug.compare, deliberately
+ NOT rubric-authoritative -- the exact anti-pattern RG 113's own fix
+ already corrected once, this file's own header) is what would decide
+ between them if they returned the SAME band on the one date they can
+ coincide (13 January, when it is itself Holy Family's date) --
+ "commemoration-of-the-baptism-of-the-lord" sorts before
+ "ef-time-after-epiphany-sunday-1" alphabetically, backwards from RG
+ 91's own stated order. See [PE.entry_14_movable_band]'s own comment
+ in precedence_ef.ml for why the value is negative rather than some
+ other distinct integer. *)
+ ( "14 Feast of the Lord, II class, MOVABLE half (Holy Family, RG 17(b))",
+ T.holy_family_sunday 2026, of_temporal (T.holy_family_sunday 2026), PE.entry_14_movable_band );
(* Entry 15 -- RG 91 entry 15 (§4): an ordinary Sunday not named at entry 6
-- Septuagesima is II class (RG 11-12 names only Advent/Lent/
Passiontide/Easter/Low/Pentecost as I class). *)
@@ -662,7 +686,70 @@ let disposition_cases =
cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Lord ~layer:PE.universal_layer
"ef-synthetic-class3-lord-feast",
an_ordinary_sunday,
- "Commemorate(Privileged)" )
+ "Commemorate(Privileged)" );
+ (* RG 112(a) (docs/research/rules-register.md §4/§6.0, primary text,
+ verified against BOTH photographic scans): "112. Ad commemorationes
+ et orationes quod attinet, haec insuper serventur: a) Officium, Missa
+ aut commemoratio de aliquo festo vel mysterio unius Divinae Personae
+ excludit commemorationem aut orationem de alio festo vel mysterio
+ eiusdem Divinae personae" -- the Office, Mass or commemoration of
+ some feast or MYSTERY of ONE Divine Person excludes a commemoration
+ or oration of ANOTHER feast or mystery of the SAME Divine Person.
+ Real witness, the ONE date these two candidates can ever coincide:
+ Holy Family (RG 17(b)) as winner, the Commemoration of the Baptism
+ of the Lord (13 January, data/ef/sanctoral.sexp: Class2, subject
+ Lord, status Feast) as loser, on the seven years 13 January is
+ itself Holy Family's own date (2008, 2013, 2019, 2030, 2036, 2041,
+ 2047). Directly confirmed by the Missal's own MORE SPECIFIC rubric,
+ found in the Holy Family Mass propers themselves (both photographic
+ scans, word for word): "Si festum S. Familiae occurrerit die 13
+ ianuarii, Missa dicitur de festo S. Familiae, SINE COMMEMORATIONE
+ BAPTISMATIS D.N.I.C., et sine commemoratione dominicae" -- if the
+ feast of the Holy Family occurs on 13 January, the Mass is said of
+ the Holy Family, WITHOUT commemoration of the Baptism, and without
+ commemoration of the Sunday (RG 17(b)'s own general rule, restated).
+ The electronic transcription (1962-06-23,_SS_Ioannes_XXIII,_Missale
+ _Romanum,_LT.pdf) carries NEITHER sentence at all -- exactly the
+ transcription's own documented defect (this project's methodology
+ note), not merely absent from this one check. *)
+ ( "RG112(a): a feast/mystery of the Lord excludes a commemoration of \
+ ANOTHER feast/mystery of the Lord -- Omit, not Commemorate (Holy \
+ Family vs the Baptism of the Lord, 13 January)",
+ of_temporal (T.holy_family_sunday 2019),
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "commemoration-of-the-baptism-of-the-lord",
+ "Omit" );
+ (* Conjunct 1/2, LOSER subject: an ORDINARY saint losing to the SAME
+ Lord-subject winner must still reach the ordinary commemorate flow,
+ not RG 112(a)'s exclusion -- RG 112(a) excludes another mystery of
+ the SAME Divine Person, not every commemoration a Lord feast happens
+ to outrank. Dropping the loser's own [subject = Lord] test would
+ wrongly Omit this ordinary saint's commemoration too. *)
+ ( "RG112(a) does NOT fire when only the WINNER is a mystery of the Lord \
+ -- an ordinary saint stays Commemorate(Ordinary)",
+ of_temporal (T.holy_family_sunday 2019),
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Saint ~layer:PE.universal_layer
+ "ef-synthetic-ordinary-saint",
+ "Commemorate(Ordinary)" );
+ (* Conjunct 2/2, WINNER subject: a Class2 SAINT'S feast (not of the
+ Lord) impeding an ordinary temporal candidate must not exclude an
+ otherwise-due Lord commemoration either -- RG 112(a) is keyed on the
+ WINNER's own subject too, not just the loser's. Real slug/rank from
+ data/ef/sanctoral.sexp (25 January, Class3, "Conversion of St
+ Paul") standing in for a same-rank saint winner; only the [subject]
+ distinction is under test here, not a real-date collision (Holy
+ Family's own subject is what makes this branch reachable at all --
+ an ordinary sanctoral saint never wins against Holy Family in
+ practice, {!band}'s [entry_14_movable_band] sees to that, so this
+ row is SYNTHETIC in the same sense the RG16(a) block's own Class3
+ row above is: defensive, not a live witness). *)
+ ( "SYNTHETIC: RG112(a) does NOT fire when only the LOSER is a mystery \
+ of the Lord -- stays Commemorate(Ordinary)",
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Saint ~layer:PE.universal_layer
+ "conversion-of-st-paul",
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "commemoration-of-the-baptism-of-the-lord",
+ "Commemorate(Ordinary)" )
]
(* Task 9: [privilege_of]'s RG 109 categories (§4, "Commemorations"),
@@ -1218,6 +1305,44 @@ let test_rg16a_lord_feast_suppresses_sunday_end_to_end () =
(List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted
|> List.sort compare)
+(* End-to-end proof of BOTH fixes this task adds together, {!P.resolve} in
+ full (band picks the winner, disposition and admit decide the loser's
+ fate), not just the two isolated functions [cases]/[disposition_cases]
+ already prove: 13 January 2019, the latest possible date Holy Family can
+ fall on (Epiphany itself a Sunday) and one of the seven years it
+ coincides with the fixed Commemoration of the Baptism of the Lord.
+ {!band}'s [entry_14_movable_band] (RG 91 entry 14, "primum mobilia") must
+ pick Holy Family as [observed], not the fixed Baptism candidate (which,
+ absent that fix, would win outright via {!compare_by}'s own alphabetical
+ tie-break at the shared literal 14 -- backwards from the primary text);
+ {!PE.disposition}'s new RG 112(a) branch must then Omit the Baptism
+ entirely, not merely demote it to a commemoration -- confirmed against
+ BOTH the general rubric (RG 112(a)) and the Holy Family Mass propers' own
+ more specific 13-January note (this file's own citation on the
+ RG112(a) [disposition_cases] rows above), and independently against
+ missalemeum's own JSON for this exact date (register §6.0): title "The
+ Holy Family: Jesus, Mary & Joseph", commemorations [], the Baptism
+ listed only under "displaced". *)
+let test_holy_family_excludes_baptism_end_to_end () =
+ let date = T.holy_family_sunday 2019 in
+ Alcotest.(check string) "sanity: this really is 13 January 2019" "2019-01-13" (D.to_iso8601 date);
+ let day_ctx = ctx date in
+ let holy_family = of_temporal date in
+ let baptism =
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "commemoration-of-the-baptism-of-the-lord"
+ in
+ let resolution = P.resolve real_rules day_ctx ~temporal:holy_family ~sanctoral:[ baptism ] in
+ Alcotest.(check string) "Holy Family is observed, not the fixed Baptism (RG91 e14: movable first)"
+ "ef-time-after-epiphany-sunday-1" (S.to_string resolution.P.observed.P.cel.Cel.slug);
+ Alcotest.(check string) "II class" "class-2" (V.rank_to_string resolution.P.observed.P.cel.Cel.rank);
+ Alcotest.(check int)
+ "no commemorations at all -- RG112(a)'s own exclusion, not merely dropped by an admission count"
+ 0 (List.length resolution.P.commemorations);
+ Alcotest.(check (list string)) "the Baptism is OMITTED, not merely uncommemorated"
+ [ "commemoration-of-the-baptism-of-the-lord" ]
+ (List.map (fun (c, _) -> S.to_string c.P.cel.Cel.slug) resolution.P.omitted)
+
(* 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
@@ -1465,6 +1590,10 @@ let suite =
"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
+ "RG112(a) + RG91 e14 \"primum mobilia\": Holy Family excludes the Baptism of the Lord \
+ entirely, end-to-end (13 Jan 2019)"
+ `Quick test_holy_family_excludes_baptism_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"