summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md55
-rw-r--r--lib/rites/rite_ef/temporal_ef.ml32
-rw-r--r--test/test_golden.ml6
-rw-r--r--test/test_temporal_ef.ml6
4 files changed, 78 insertions, 21 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index f1a673f..68cb906 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -531,20 +531,47 @@ candidate is exactly one and already spoken for).
date's own candidate pool (both Peter and Paul are ordinary Fixed-date
sanctoral entries); neither the Major Litanies' Easter+2 target nor
Rogation Wednesday's own Mass commemoration has any such pre-existing
- candidate to find. Major Litanies' ORDINARY case (the ≈97.7% of years
- RG 80's transfer clause does not trigger) is independently buildable
- today with zero new machinery — a `Commemoration_only` `Fixed(4,25)`
- sanctoral entry, `Precedence_ef.privilege_of`'s already-present, dead RG
- 109(f) branch wired to it — but building only that would leave the
- transfer years with a NEW wrong answer (a phantom commemoration on
- Easter Sunday/Monday itself, which RG 80 explicitly forbids), not merely
- the old, understood gap, so it was not built either. Full reasoning,
- including the paths considered and rejected (a kernel signature
- extension threading Easter-offset into `disposition`/`admit` closes half
- of the Major Litanies problem — suppression — but not the relocation
- half, and Rogation Wednesday has no equivalent half-solution at all): the
- `ef-triduum-litanies` task report and register (Rogations/§4, and the two
- narrowed open items in §6).
+ candidate to find.
+
+ **The real reason to defer the Major Litanies, corrected by the
+ fix-round review** — the version above was wrong in two load-bearing
+ ways and is retracted:
+
+ - It said the suppression half needs "a kernel signature extension
+ threading Easter-offset into `disposition`/`admit`". It does not.
+ `admit` **already** takes `~temporal` (added for exactly this class of
+ question during the RG 16(a) task) and `disposition` already takes
+ `~winner`; on 25 April in a transfer year both carry the Easter Sunday
+ or Easter Monday office. A rite-local slug test suppresses it with
+ **zero** kernel surface.
+ - It implied Easter Monday is unmarkable. Measured over the whole
+ domain: `ef-easter-1-monday` occurs **exactly 8 417 times in 8 417
+ years** — once every year, never displaced, since it is an I-class
+ octave day — making it precisely as reliable a marker as
+ `ef-easter-sunday`. The stated asymmetry between the two trigger
+ conditions does not exist.
+
+ So the **guarded** build (a `Commemoration_only` `Fixed(4,25)` entry, RG
+ 109(f) wired, plus slug-based suppression on the two Easter slugs) is a
+ strict improvement, not a regression: 8 223 years newly correct, 194
+ unchanged, zero new wrong answers. "Worse than the recorded gap" was
+ true only of the *unguarded* build, which is the only option that was
+ scored.
+
+ Deferring is still right, for a reason nobody had identified: **25 April
+ is St Mark, II class**, so under **RG 111(c)** a *privileged* Litanies
+ commemoration (RG 109(f)) would **displace** whatever ordinary
+ commemoration the day currently carries, in ≈97.7% of years — a live,
+ unmeasured blast radius straight through layers 3 and 4. That
+ measurement is the prerequisite, and it makes this its own task rather
+ than a rider on another. The 194 figure is exact and reproduced twice
+ (Easter = 25 April in 67 years, Easter Monday = 25 April in 127).
+
+ Full reasoning: the `ef-triduum-litanies` task report and register
+ (Rogations/§4, and the two narrowed open items in §6). **Rogation
+ Wednesday remains genuinely blocked** — Easter+38 coincides with the
+ Ascension Vigil by construction, so there is no `(month, day)` pair a
+ `Fixed` spec could anchor to and no partial build exists at all.
## How to work here
diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml
index 4aa8aea..4b59ff4 100644
--- a/lib/rites/rite_ef/temporal_ef.ml
+++ b/lib/rites/rite_ef/temporal_ef.ml
@@ -199,7 +199,9 @@ let holy_name_names =
[Lord]-subject entry 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, August, September or November)
+ 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)
-- and any [Class1] sanctoral entry that DOES land there (e.g. a
transferred Annunciation) reaches Precedence_ef.disposition's EARLIER,
subject-blind "I class, not a Sunday -> Transfer" branch first
@@ -208,13 +210,39 @@ let holy_name_names =
sweep (git archive, pre- vs post-change) shows zero
[observed]/[commemorations]/[transferred_*] difference traceable to this
tag anywhere in the domain -- see the task report. *)
+(* SOURCE NOTE on the three literals below (corrected, fix-round review):
+ each is the Missal's own RUNNING HEADER for that Office, which is the
+ convention every other Latin name in this file already follows
+ ([holy_family_sunday], [holy_name_sunday]). Counted across both
+ photographic scans:
+ "Feria V in Cena Domini" heading FERIA QUINTA IN CENA
+ DOMINI; running header 1:1
+ "Feria VI in Passione et Morte Domini" heading FERIA SEXTA / IN
+ PASSIONE ET MORTE DOMINI;
+ running header 1:1. NOT
+ "Feria VI Parasceve", which
+ occurs ZERO times as a title in
+ either scan -- every occurrence
+ of Parasceve is inside the
+ Johannine Passion text. RG
+ 132(a) writes "feriae VI in
+ Passione et Morte Domini".
+ "Sabbato sancto" heading SABBATO SANCTO (1x);
+ running header "Sabbato sancto"
+ 28x / 30x.
+ The last was previously shipped as "Sabbato Sancto", a third casing
+ attested in NEITHER scan -- it appears only in the electronic
+ transcription's own table of contents, i.e. the source this project's
+ methodology rule deprecates -- while the comment called it "both
+ photographic scans, word for word". Recased to the running-header form
+ the other names use. *)
let triduum_names = function
| -3 -> Some (Colitur_kernel.Names.of_list [ (Colitur_kernel.Lang.of_string_exn "la", "Feria V in Cena Domini") ])
| -2 ->
Some
(Colitur_kernel.Names.of_list
[ (Colitur_kernel.Lang.of_string_exn "la", "Feria VI in Passione et Morte Domini") ])
- | -1 -> Some (Colitur_kernel.Names.of_list [ (Colitur_kernel.Lang.of_string_exn "la", "Sabbato Sancto") ])
+ | -1 -> Some (Colitur_kernel.Names.of_list [ (Colitur_kernel.Lang.of_string_exn "la", "Sabbato sancto") ])
| _ -> None
let same a b = Date.compare a b = 0
diff --git a/test/test_golden.ml b/test/test_golden.ml
index 68478ec..594ea6b 100644
--- a/test/test_golden.ml
+++ b/test/test_golden.ml
@@ -165,7 +165,7 @@ let omitted_has (day : (V.season, V.rank) LD.t) slug =
let test_easter_extreme_1598 () =
check ~msg:"1598-03-21 Holy Saturday: still Passiontide, violet (RG 128)" 1598 3 21
"1598-03-21 saturday season=passiontide week=2 slug=ef-passiontide-2-saturday rank=class-1 colour=violet subject=lord \
- name_la=Sabbato Sancto comms=[] in=- out=[]";
+ name_la=Sabbato sancto comms=[] in=- out=[]";
check ~msg:"1598-03-22 earliest possible Easter (Gauss-verified): Paschaltide begins, white, class-1" 1598 3
22
"1598-03-22 sunday season=paschaltide week=1 slug=ef-easter-sunday rank=class-1 colour=white subject=temporal name_la=- comms=[] in=- \
@@ -177,7 +177,7 @@ let test_easter_extreme_1598 () =
let test_easter_extreme_1666 () =
check ~msg:"1666-04-24 Holy Saturday: still Passiontide, violet (RG 128)" 1666 4 24
"1666-04-24 saturday season=passiontide week=2 slug=ef-passiontide-2-saturday rank=class-1 colour=violet subject=lord \
- name_la=Sabbato Sancto comms=[] in=- out=[]";
+ name_la=Sabbato sancto comms=[] in=- out=[]";
check ~msg:"1666-04-25 latest possible Easter (Gauss-verified): Paschaltide begins, white, class-1" 1666 4
25
"1666-04-25 sunday season=paschaltide week=1 slug=ef-easter-sunday rank=class-1 colour=white subject=temporal name_la=- comms=[] in=- \
@@ -206,7 +206,7 @@ let test_easter_extreme_1666 () =
let test_easter_extreme_2038_late_modern () =
check ~msg:"2038-04-24 Holy Saturday: still Passiontide, violet (RG 128)" 2038 4 24
"2038-04-24 saturday season=passiontide week=2 slug=ef-passiontide-2-saturday rank=class-1 colour=violet subject=lord \
- name_la=Sabbato Sancto comms=[] in=- out=[]";
+ name_la=Sabbato sancto comms=[] in=- out=[]";
check ~msg:"2038-04-25 late-modern instance of the latest possible Easter (Gauss-verified)" 2038 4 25
"2038-04-25 sunday season=paschaltide week=1 slug=ef-easter-sunday rank=class-1 colour=white subject=temporal name_la=- comms=[] in=- \
out=[]"
diff --git a/test/test_temporal_ef.ml b/test/test_temporal_ef.ml
index a979700..5394173 100644
--- a/test/test_temporal_ef.ml
+++ b/test/test_temporal_ef.ml
@@ -764,7 +764,9 @@ let test_holy_name_fallback_anchor_present_and_erosion_is_caught () =
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, August, September or November);
+ 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
@@ -792,7 +794,7 @@ let test_sacred_triduum_identity () =
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));
+ (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"