summaryrefslogtreecommitdiff
path: root/test/test_temporal_ef.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 15:20:24 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 15:20:24 +0200
commit36eba4eff58162cbe4c7b4ff1b9d049432fc1acc (patch)
treeaad8cd588a8a33202bfed990fec99d5eafc25dcd /test/test_temporal_ef.ml
parentdc00d1f730b23fa99cd15ff142ecba515a9fe0b7 (diff)
parent67855ae3125148116df870bf1a9abeac5b501d5b (diff)
downloadcolitur-36eba4eff58162cbe4c7b4ff1b9d049432fc1acc.tar.gz
colitur-36eba4eff58162cbe4c7b4ff1b9d049432fc1acc.zip
Merge branch 'ef-triduum-litanies': the Sacred Triduum's Latin identity
Gives Holy Thursday, Good Friday and Holy Saturday the names the Missal prints for them, taken from each Office's own running header: 'Feria V in Cena Domini', 'Feria VI in Passione et Morte Domini', 'Sabbato sancto'. Rank and colour were already correct; only the identity was missing, the same shape the Holy Family had. The slug is deliberately unchanged -- it is the lectionary key -- and the names are Latin, which avoids promoting an English value from the oracle the engine is checked against. Not 'Feria VI Parasceve': that phrase occurs zero times as a title in either photographic scan, appearing only inside the Johannine Passion text, and RG 132(a) writes 'feriae VI in Passione et Morte Domini'. Output is byte-identical across all 8417 years -- colitur day prints no name column -- but layer 5 does see it: describe gained name_la, and reverting the change reddens six pins. The Major Litanies (RG 80) and the Rogation Wednesday commemoration were investigated to the same depth, scan-verified, cited, and deliberately not built. Rogation Wednesday is genuinely blocked: Easter+38 coincides with the Ascension Vigil, so no Fixed date-spec can anchor it. The Major Litanies are tractable in the rite module -- the two blockers first recorded for them were false, and are retracted here -- but 25 April is St Mark, II class, so under RG 111(c) a privileged Litanies commemoration would displace the day's existing ordinary commemoration in ~97.7% of years. That blast radius is unmeasured, and measuring it is the prerequisite for its own task.
Diffstat (limited to 'test/test_temporal_ef.ml')
-rw-r--r--test/test_temporal_ef.ml83
1 files changed, 83 insertions, 0 deletions
diff --git a/test/test_temporal_ef.ml b/test/test_temporal_ef.ml
index f341533..5394173 100644
--- a/test/test_temporal_ef.ml
+++ b/test/test_temporal_ef.ml
@@ -732,6 +732,87 @@ let test_holy_name_fallback_anchor_present_and_erosion_is_caught () =
Alcotest.(check string) "sanity: temporal itself is unaffected by the anchors-list erosion"
expected_slug (slug_of expected_date)
+(* Gap 1 (ef-triduum-litanies, docs/research/rules-register.md, "the Sacred
+ Triduum has no proper office"): the Missal's own Mass-propers headings for
+ Holy Thursday/Good Friday/Holy Saturday, both photographic scans, word for
+ word (missale-romanum-1962.pdf and "Missale Romanum 1962_text.pdf",
+ corroborated by the electronic transcription's own table-of-contents-style
+ listing at the identical three headings -- three-way agreement, no
+ scan-vs-transcription conflict to adjudicate): "FERIA QUINTA IN CENA
+ DOMINI" / running header "Feria V in Cena Domini"; "FERIA SEXTA / IN
+ PASSIONE ET MORTE DOMINI"; "SABBATO SANCTO". The slug stays the generic
+ Passiontide ferial one (RG 91 entry 2 already identifies the Triduum
+ structurally, off the day's own Easter offset and rank --
+ {!Rite_ef.Precedence_ef.band}'s own entry-2 branch -- never off the slug,
+ so renaming it would touch precedence for no reason and would break the
+ lectio differential's own slug mapping for these three lectionary keys);
+ the missing IDENTITY is carried in [names], the same treatment RG
+ 17(b)/(a) (Holy Family/Holy Name) already established -- Latin, not
+ English, for the same zero-circularity reason those two entries give
+ (would otherwise read the oracle this exact axis is compared against).
+
+ [subject] is ALSO set to [Lord] here, going further than Holy Family/Holy
+ Name's own precedent strictly required (they needed it because
+ {!Rite_ef.Precedence_ef.band}'s entry 14 reads [subject] to outrank a
+ colliding fixed feast). The Triduum has no such live need: entry 2 is
+ decided purely by [rank]/Easter-offset, never [subject] -- confirmed by
+ reading {!Rite_ef.Precedence_ef.band}'s own entry-2 branch, which tests
+ neither. Tagged anyway because it is simply true (the Last Supper, the
+ Passion and Death, the entombment are textbook mysteries of the Lord) and
+ safe: {!Rite_ef.Precedence_ef.disposition}'s own RG 112(a) branch (Lord vs
+ Lord) only fires when BOTH sides are tagged [Lord], and no [Lord]-subject
+ sanctoral entry anywhere in data/ef/sanctoral.sexp has a FIXED civil date
+ inside Holy Week's own movable range (earliest 19 March, latest 24 April
+ -- the register's own subject audit lists exactly six [Lord]-tagged
+ entries, all fixed in January, February, JULY, August, September or
+ November -- the Precious Blood, 1 July, was omitted from this list until
+ the fix-round review counted six entries against five months);
+ any [Class1] sanctoral entry that DOES land there (e.g. a transferred
+ Annunciation) reaches {!Rite_ef.Precedence_ef.disposition}'s EARLIER,
+ subject-blind "I class, not a Sunday -> Transfer" branch first, so RG
+ 112(a)'s own branch is never reached for it regardless of this tag.
+ Measured empirically too: this task's own full 1583-9999 blast-radius
+ sweep shows no [observed]/[commemorations]/[transferred_*] difference
+ traceable to this tag anywhere in the domain. *)
+let test_sacred_triduum_identity () =
+ (* 2026: Easter 5 April, so Holy Thursday/Good Friday/Holy Saturday are
+ 2/3/4 April. *)
+ Alcotest.(check string) "2026-04-02 Holy Thursday: slug stays the generic ferial key"
+ "ef-passiontide-2-thursday" (slug_of (d 2026 4 2));
+ Alcotest.(check bool) "2026-04-02 Holy Thursday: subject Lord" true
+ (subject_of (d 2026 4 2) = Sub.Lord);
+ Alcotest.(check (option string)) "2026-04-02 Holy Thursday: Latin name, both photographic scans verbatim"
+ (Some "Feria V in Cena Domini") (name_la_of (d 2026 4 2));
+ Alcotest.(check string) "2026-04-03 Good Friday: slug stays the generic ferial key"
+ "ef-passiontide-2-friday" (slug_of (d 2026 4 3));
+ Alcotest.(check bool) "2026-04-03 Good Friday: subject Lord" true
+ (subject_of (d 2026 4 3) = Sub.Lord);
+ Alcotest.(check (option string)) "2026-04-03 Good Friday: Latin name, both photographic scans verbatim"
+ (Some "Feria VI in Passione et Morte Domini") (name_la_of (d 2026 4 3));
+ Alcotest.(check string) "2026-04-04 Holy Saturday: slug stays the generic ferial key"
+ "ef-passiontide-2-saturday" (slug_of (d 2026 4 4));
+ Alcotest.(check bool) "2026-04-04 Holy Saturday: subject Lord" true
+ (subject_of (d 2026 4 4) = Sub.Lord);
+ Alcotest.(check (option string)) "2026-04-04 Holy Saturday: Latin name, both photographic scans verbatim"
+ (Some "Sabbato sancto") (name_la_of (d 2026 4 4));
+ (* Neighbouring days carry no name/subject override -- the tag is exactly
+ three days wide, not the whole Passiontide-2 week. *)
+ Alcotest.(check (option string)) "2026-04-01 (Wednesday of Holy Week): no Latin name"
+ None (name_la_of (d 2026 4 1));
+ Alcotest.(check bool) "2026-04-01 (Wednesday of Holy Week): subject stays temporal" true
+ (subject_of (d 2026 4 1) = Sub.Temporal);
+ Alcotest.(check (option string)) "2026-04-05 Easter Sunday: no Latin name from this branch"
+ None (name_la_of (d 2026 4 5));
+ (* A second, independent year (1666: the latest possible Easter, 25 April,
+ already this file's own Easter-extreme witness elsewhere) -- proves the
+ mechanism generalises off [days_between easter d], not hand-pinned to
+ 2026's own civil dates. Holy Thursday/Good Friday/Holy Saturday are
+ 22/23/24 April 1666. *)
+ Alcotest.(check (option string)) "1666-04-22 Holy Thursday (latest-Easter year): Latin name still fires"
+ (Some "Feria V in Cena Domini") (name_la_of (d 1666 4 22));
+ Alcotest.(check bool) "1666-04-22 Holy Thursday: subject Lord" true
+ (subject_of (d 1666 4 22) = Sub.Lord)
+
let test_totality () =
(* Every day of 2026 yields an office without raising. Not a slug
re-validation -- Slug.t is a private string validated on construction,
@@ -765,6 +846,8 @@ let suite_extra =
Alcotest.test_case "ember days" `Quick test_ember_days;
Alcotest.test_case "rogations" `Quick test_rogations;
Alcotest.test_case "colours" `Quick test_colours;
+ Alcotest.test_case "sacred triduum identity (RG 91 entry 2, Gap 1)" `Quick
+ test_sacred_triduum_identity;
Alcotest.test_case "christmastide feria slugs" `Quick test_christmastide_feria_slugs;
Alcotest.test_case "named days carry their week" `Quick test_named_days_carry_their_week;
Alcotest.test_case "totality" `Quick test_totality;