diff options
| -rw-r--r-- | lib/rites/rite_ef/precedence_ef.ml | 41 | ||||
| -rw-r--r-- | test/test_precedence_ef.ml | 28 |
2 files changed, 68 insertions, 1 deletions
diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml index dd75765..b69ee52 100644 --- a/lib/rites/rite_ef/precedence_ef.ml +++ b/lib/rites/rite_ef/precedence_ef.ml @@ -1532,6 +1532,45 @@ let rg110_find_companion comms companion_slug = codebase's test suite where commemoration order is asserted at all -- flagged here, and in CLAUDE.md's own "know what each layer cannot see" section, as a genuine, permanent limit, not merely this fix's own gap. *) +(* RG 113, sentence ONE -- "Commemoratio de Tempore fit primo loco" (the + commemoration of the Season is made in the first place), verified in the + electronic transcription docs/research/LT.txt and in both photographic + scans; register §6.26. + + §4 of the register and this file's own {!admit} already implement RG 113's + SECOND sentence ("In admittendis et ordinandis ALIIS commemorationibus, + servetur ordo tabellae praecedentiae") as the admission/ordering criterion, + adopted on the ef-rg16a branch. The first sentence was never implemented: + ordering was by {!band} alone, for every commemoration including the + seasonal one. + + RECONCILED WITH RG 110(c), which says the inseparable Peter/Paul pair is + added "ante omnes alias commemorationes". The two rubrics share a technical + term: RG 113's own sentence fixes the sense of *aliae commemorationes* as + "the ones other than the de Tempore commemoration it has just placed primo + loco", and RG 110(c) sits three paragraphs earlier in the same code. Read + consistently, RG 110(c) puts the pair at the head of the OTHERS, not ahead + of the season. Hence this runs AFTER {!rg110_additions}, not before: + RG 110(c)'s own "immediate" adjacency (trigger then companion, fix round 1, + register §6.3) is preserved by {!List.partition}'s stability, and the + seasonal commemoration then steps in front of the pair rather than + splitting it. + + [origin] is the exact discriminator the kernel already carries -- a + candidate is {!Precedence.Temporal} iff it came from the rite's temporal + cycle, which is what "de Tempore" means. Measured over 1583-9999, no day + ever carries more than one such commemoration (RG 112(c), "an Office, Mass + or commemoration of the season excludes another seasonal commemoration", + holding empirically), so this promotes at most one entry; [partition] is + used rather than a find-and-move so the zero case and the never-observed + many case are both total without a special branch. *) +let rg113_season_first + (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list) : + (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list = + let de_tempore (c, _) = c.Precedence.origin = Precedence.Temporal in + let seasonal, others = List.partition de_tempore comms in + seasonal @ others + let rg110_additions (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege * int) list) ~(observed : Vocab_ef.rank Precedence.candidate) (normal : (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list) : @@ -1702,7 +1741,7 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate) as the non-Sunday II-class case, just with room for two. *) List.map drop_band (take 2 sorted) in - rg110_additions comms ~observed normal + rg113_season_first (rg110_additions comms ~observed normal) (* Task 11: RG 96 -- where an impeded I-class feast lands (docs/research/ rules-register.md §4, "Transfer/translation"). [band] decides who is diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml index 790dab6..3f3e070 100644 --- a/test/test_precedence_ef.ml +++ b/test/test_precedence_ef.ml @@ -1170,12 +1170,40 @@ let unrelated_comm_synth = contest; it adds Paul regardless. *) let lent_feria_synth = (cand ~origin:P.Temporal ~rank:V.Class3 "ef-lent-2-monday-synth", P.Privileged, 180) +(* RG 113 sentence ONE (docs/research/rules-register.md §6.26): + "Commemoratio de Tempore fit primo loco." The commemoration OF THE SEASON + is made in the first place; the second sentence's table order governs the + OTHERS. Every other candidate in this table is [origin = P.Temporal] by + [cand]'s own default, so the rule is an identity on them and no existing + row's expectation moves; these two candidates exist to make a MIXED-origin + row possible, which is the only shape that can witness it. + + This file's [admit_cases] is the ONLY place in the whole suite that + asserts commemoration ORDER -- the differential never compares + commemorations, the oracle sorts both sides into a multiset, and + test_golden.ml's own [describe] deliberately sorts its comms field. So a + row here is the only thing standing between this rule and a silent + regression. *) +let sanctoral_hi = + { (cand ~rank:V.Class2 "ef-sanctoral-hi") with P.origin = P.Sanctoral } + +let seasonal_lo = cand ~rank:V.Class3 "ef-seasonal-lo" + let admit_cases = [ (* RG 111 (§4): "I class: none save one privileged." *) ( "I-class day, only an ordinary commemoration due -> none admitted", observed_class1, observed_class1, [ po ordinary_hi P.Ordinary ], [] ); + (* RG 113 s1: the de Tempore commemoration leads, even though the + sanctoral one outranks it on RG 91's table (Class2 beats Class3) and + would therefore come first under sentence TWO alone. Both slots of a + III-class day are filled, so this row tests ORDER, not selection. *) + ( "III-class day, seasonal + sanctoral both admitted -> the SEASONAL one \ + first (RG 113 s1), despite the sanctoral one's higher table position", + observed_class3, observed_class3, + [ po sanctoral_hi P.Ordinary; po seasonal_lo P.Ordinary ], + [ "ef-seasonal-lo"; "ef-sanctoral-hi" ] ); ( "I-class day, ordinary + privileged both due -> only the privileged \ one, regardless of the ordinary one's higher dignity", observed_class1, observed_class1, |
