summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 08:15:48 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 08:15:48 +0200
commit6319c8d5c012db40206b463dc912a1edf7aeec5d (patch)
tree65182f0ffc9c0fe6f256112354eb9fe8678466cc /test
parentbbc8ce26916ca92b3c2286c57342a6565323b66f (diff)
downloadcolitur-6319c8d5c012db40206b463dc912a1edf7aeec5d.tar.gz
colitur-6319c8d5c012db40206b463dc912a1edf7aeec5d.zip
precedence(ef): RG91 e14 "primum mobilia" + RG112(a) inseparable exclusion
Two related fixes, both needed for Holy Family to actually observe correctly on the seven years it coincides with the fixed Commemoration of the Baptism of the Lord (13 January): 2008, 2013, 2019, 2030, 2036, 2041, 2047. band's entry 14 ("Festa Domini II classis") gated on sanctoral origin only, so a movable Class2 Lord feast had no row in the table at all. RG 91 entry 14's own text says otherwise: "primum mobilia, deinde fixa" -- movable first, then fixed. entry_14_movable_band gives Holy Family (the one movable candidate this codebase builds with subject Lord) a value strictly better than the fixed half's own literal 14, negative so it can never collide with a real table position -- without it, the two would tie at 14 and fall to Precedence.resolve's own alphabetical tie-break, which picks the WRONG side ("commemoration-of-the-baptism-of-the-lord" sorts before "ef-time-after-epiphany-sunday-1"). disposition gets a new branch for RG 112(a) (Caput XVI, "De Commemorationibus"): the Office, Mass or commemoration of a mystery of one Divine Person excludes a commemoration of another mystery of the SAME Divine Person. Winner and loser both subject Lord -> Omit, not Commemorate -- without it, Holy Family observing correctly still left the Baptism admitted as an ordinary Class2 commemoration under RG111(b), which the primary text does not allow. Confirmed by a MORE SPECIFIC primary source than RG 112(a) alone: the Holy Family Mass propers' own note, found on both photographic scans, word for word, immediately after the Postcommunio -- "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." The electronic transcription carries neither this rubric nor RG 112(a)'s own worked example -- another instance of its documented defect, not merely absent from one check. Still expected red: the lectio differential (2005-2050) now shows a new, real divergence on those seven 13-January-Sunday dates -- lectio has no Holy Family at all, so it still shows the fixed Baptism observed there, unlike colitur now. The oracle's own M-series entries also still need widening for the observed-identity axis added two commits ago. Both are the next commits.
Diffstat (limited to 'test')
-rw-r--r--test/test_precedence_ef.ml131
1 files changed, 130 insertions, 1 deletions
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"