From 04f7521a9143d8888d1e29a3e5c2d60eaae56951 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 12 Aug 2026 12:16:53 +0200 Subject: kernel(rite-ef): apply RG16(a) -- a Feast of the Lord leaves the impeded Sunday uncommemorated Caput III "De Dominicis", RG 16(a): a Feast of the Lord, I or II class, occurring on a II-class Sunday takes the Sunday's own place with all its rights and privileges -- of the Sunday, therefore, no commemoration is made. band's entry 14 already ranked such a feast above the Sunday correctly; disposition had no exception for the collision, so the impeded Sunday fell through to the ordinary RG 95/109(a) commemorate-or-omit catch-all and was wrongly admitted as a privileged commemoration. Adds a branch to Rite_ef.Precedence_ef.disposition, gated on all four of: loser is temporal-origin, loser rank Class2, loser carries the Sunday slug marker, winner rank Class1-or-2 with subject Lord. No signature change -- disposition already receives the winner (RG 33's own vigil-omission branch already reads it); each conjunct is proved independently load-bearing by a dedicated disposition_cases row, including one real-data case each for the winner's subject and rank conjuncts, and a defensive synthetic case for the winner rank conjunct's currently-unreachable Class3 shape. A new end-to-end resolve-level test (2028-08-06, the Transfiguration) proves the real band/disposition pipeline together, checking the Omit reason string distinguishes this from admit's own admission-limit cut. --- test/test_precedence_ef.ml | 137 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml index a0e1db1..facf3eb 100644 --- a/test/test_precedence_ef.ml +++ b/test/test_precedence_ef.ml @@ -540,7 +540,100 @@ let disposition_cases = Omit under the refuted privilege_of=Ordinary gate", an_ordinary_sunday, cand ~rank:V.Class3 "ef-synthetic-ordinary-class3-feria", - "Commemorate(Ordinary)" ) + "Commemorate(Ordinary)" ); + (* RG 16(a) (register §6.0, Caput III "De Dominicis"): "festum Domini I + aut II classis, in dominica II classis occurrens, ... de dominica, + proinde, nulla fit commemoratio" -- a Feast of the Lord, I or II + class, impeding a II-class Sunday, leaves the Sunday with NO + commemoration at all, unlike every other impeded II-class Sunday + (contrast the very first row of this table, and [privilege_cases]'s + own (a): both plain [Class1]/other-sanctoral winners still admit the + Sunday, [Commemorate(Privileged)]). Two positive rows, I and II + class, both real slugs/ranks/subjects this project's own audit + confirmed against the calendarium (this task's own report): the + Transfiguration (6 Aug, II class, "IN TRANSFIGURATIONE D. N. I. C.") + and the Precious Blood (1 Jul, I class, "PRETIOSISSIMI SANGUINIS + D. N. I. C."). *) + ( "RG16(a): a Feast of the Lord, II class, impedes a II-class Sunday -> \ + Omit, no commemoration at all", + cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer + "transfiguration-of-our-lord", + an_ordinary_sunday, + "Omit" ); + ( "RG16(a): a Feast of the Lord, I class, impedes a II-class Sunday -> \ + Omit, no commemoration at all", + cand ~origin:P.Sanctoral ~rank:V.Class1 ~subject:Sub.Lord ~layer:PE.universal_layer + "precious-blood-of-our-lord-jesus-christ", + an_ordinary_sunday, + "Omit" ); + (* Conjunct 1/4, WINNER subject: RG 16(a) names a feast "Domini", not any + I-class feast. {!band} entries 11-13 admit any I-class feast ahead of + a II-class Sunday with no subject test (unlike entry 14, see that + entry's own comment) -- so a real I-class SAINT feast can win the day + exactly as a Lord feast would, and must NOT trigger RG 16(a). Real + slug/rank/subject from data/ef/sanctoral.sexp (24 June, I class, + "NATIVITAS S. IOANNIS BAPTISTAE", subject Saint): 24 June falls on a + Time-after-Pentecost Sunday in real years (e.g. 2029), so this is a + live, not merely synthetic, shape -- {!band} entries 11-13 rank it + ahead of the ordinary Sunday's own entry 15 regardless of subject. + Dropping the [subject = Lord] conjunct would wrongly Omit the Sunday + here too. *) + ( "RG16(a) does NOT fire for a I-class feast of a SAINT (not the Lord) \ + impeding a II-class Sunday -- stays Commemorate(Privileged)", + cand ~origin:P.Sanctoral ~rank:V.Class1 ~subject:Sub.Saint ~layer:PE.universal_layer + "nativity-of-st-john-the-baptist", + an_ordinary_sunday, + "Commemorate(Privileged)" ); + (* Conjunct 2/4, LOSER rank: RG 16(a) names "Dominica II classis", not + any Sunday. A I-class Sunday (Advent/Lent/Passiontide, Low Sunday, + {!band} entry 6) can never actually reach here as a loser against a + Class1-or-2 Lord winner in real banding (entry 6's own band value, 6, + beats every entry such a winner could occupy, 3/11-14), which is + exactly why the primary text restricts itself to II class -- but + [disposition] takes no [context] and cannot itself re-derive that + band fact, so the rank check is what actually enforces it here. + Sourced from [Temporal_ef.temporal]'s own real output (Advent I + Sunday 2026, Class1, "ef-advent-sunday-1"), the same row + [disposition_cases]'s own RG95/RG109(a) entry above already uses. + Dropping the [rank = Class2] conjunct on the loser would wrongly Omit + this Sunday's commemoration too. *) + ( "RG16(a) does NOT fire for a I-class Sunday, even losing to a Feast of \ + the Lord -- stays Commemorate(Privileged)", + cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer + "transfiguration-of-our-lord", + of_temporal (T.advent_start 2026), + "Commemorate(Privileged)" ); + (* Conjunct 3/4, LOSER is a Sunday at all: RG 16(a) protects "de + dominica" specifically, not every ordinary office a Feast of the Lord + happens to impede. An ordinary sanctoral SAINT losing to the same + Lord-subject Class2 winner as the row above must still reach the + ordinary RG 95/111(c) commemorate-or-omit flow, not RG 16(a)'s + special no-commemoration rule. Dropping [is_sunday_slug] (or its + [is_temporal] companion) here would wrongly Omit this ordinary + saint's commemoration too. *) + ( "RG16(a) does NOT fire for an ordinary (non-Sunday) SAINT losing to a \ + Feast of the Lord -- stays Commemorate(Ordinary)", + cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer + "transfiguration-of-our-lord", + cand ~origin:P.Sanctoral ~rank:V.Class2 ~layer:PE.universal_layer "ef-some-other-saint", + "Commemorate(Ordinary)" ); + (* Conjunct 4/4, WINNER rank: RG 16(a) says "I aut II classis", not any + class. Every real [subject = Lord] entry this project's own sanctoral + audit found is Class1 or Class2 (this task's own report), so this + conjunct is not independently reachable on real data -- SYNTHETIC, + the same defensive-but-not-load-bearing status this file already + gives the RG26 branch's own [not is_vigil] guard above. Without the + rank conjunct, [subject = Lord] alone would wrongly Omit this + Sunday's commemoration under a hypothetical Class3 "feast of the + Lord" too, which RG 16(a)'s own "I aut II classis" text does not + cover. *) + ( "SYNTHETIC: RG16(a) does NOT fire for a Class3 feast of the Lord \ + (outside \"I aut II classis\") impeding a II-class Sunday -- stays \ + Commemorate(Privileged)", + cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Lord ~layer:PE.universal_layer + "ef-synthetic-class3-lord-feast", + an_ordinary_sunday, + "Commemorate(Privileged)" ) ] (* Task 9: [privilege_of]'s RG 109 categories (§4, "Commemorations"), @@ -929,6 +1022,44 @@ let test_ii_class_sunday_privileged_witness_admitted_end_to_end () = [ ("ef-some-saint", "omitted: admission limit reached") ] (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted) +(* RG 16(a) (register §6.0) reached end-to-end through the REAL pipeline + ([PE.band] AND [PE.disposition] together, not [disposition] in + isolation as [disposition_cases]'s own rows above test it): a real civil + date this task's own blast-radius measurement names as a live instance + of the bug this branch fixes -- 6 August 2028 is a Sunday (independently + checked with `date -d 2028-08-06 +%A`, the same cross-check discipline + [test_golden.ml]'s own header requires), Time after Pentecost week 9, and + the Transfiguration (6 Aug, II class, "IN TRANSFIGURATIONE D. N. I. C.") + falls on it. Before this fix `colitur day` emitted this Sunday as an + admitted [+ef-time-after-pentecost-sunday-9] commemoration on that date + (register §6.0's own reproduction); this proves the full pipeline now + agrees with the isolated [disposition] rows above: [observed] is the + Transfiguration ({!band} entry 14 already did this correctly before this + task), [commemorations] is EMPTY (not merely missing the Sunday from + [admit]'s cut -- RG 16(a) is a [disposition]-level Omit, before [admit] + ever runs), and the Sunday appears in [omitted] with + ["omitted: yielded to a higher day"] ({!Precedence.resolve}'s own Omit + reason), never ["omitted: admission limit reached"] (that reason would + mean the Sunday was tagged [Commemorate] and then cut by [admit] -- a + different, wrong mechanism for the same wrong end state). *) +let test_rg16a_lord_feast_suppresses_sunday_end_to_end () = + let date = mk 2028 8 6 in + let day_ctx = ctx date in + let sunday = of_temporal date in + let transfiguration = + cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer + "transfiguration-of-our-lord" + in + let resolution = P.resolve real_rules day_ctx ~temporal:sunday ~sanctoral:[ transfiguration ] in + Alcotest.(check string) "the Transfiguration is observed, not the Sunday" + "transfiguration-of-our-lord" (S.to_string resolution.P.observed.P.cel.Cel.slug); + Alcotest.(check int) "no commemorations at all -- RG16(a)'s own \"nulla fit commemoratio\"" + 0 (List.length resolution.P.commemorations); + Alcotest.(check (list (pair string string))) + "the Sunday is omitted with RG16(a)'s own disposition-level reason, not admit's cut" + [ ("ef-time-after-pentecost-sunday-9", "omitted: yielded to a higher day") ] + (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) 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 @@ -1166,6 +1297,10 @@ let suite = Alcotest.test_case "II-class Sunday override: RG109(b) witness admitted over an ordinary saint, end-to-end" `Quick test_ii_class_sunday_privileged_witness_admitted_end_to_end; + Alcotest.test_case + "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 "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" -- cgit v1.3