diff options
| -rw-r--r-- | lib/rites/rite_ef/precedence_ef.ml | 108 | ||||
| -rw-r--r-- | lib/rites/rite_ef/precedence_ef.mli | 17 | ||||
| -rw-r--r-- | test/test_precedence_ef.ml | 131 |
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" |
