From 853351fad8aebc71c5341e6ff90371ca0caf8cf9 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 12:01:25 +0200 Subject: fix round 1: RG 110(c)'s ordering was inverted; M19 lacked an identity gate RG 110(c), word for word: "quoties vero oratio unius Apostoli addenda est ad modum commemorationis, huic orationi additur altera immediate, ante omnes alias commemorationes." "Huic orationi" (dative, "to this oration") refers to the trigger's own oration; "additur altera" means the companion is added to it, i.e. follows it. "Ante omnes alias commemorationes" governs the pair's position relative to other, unrelated commemorations, not the pair's own internal order. The previous build prepended the companion uniformly in both RG 110 shapes, citing this same clause for both -- correct for (a)/(b) (the day's own oration, not a list member, has nothing to order against), backwards for (c), where the trigger is itself a list member and the companion belongs after it. Fixed in rg110_additions: shape (a)/(b) still prepends; shape (c) now splices the companion in immediately after its own trigger. Re-pinned the unit test that had asserted the wrong order, and corrected both rows' comments to cite the clause that actually governs each shape. No layer in this codebase compares commemoration order: the lectio differential never compares commemorations, the oracle sorts both sides into a multiset, and the golden tests' own describe function sorts its commemorations field too. Recorded as a new, permanent blind spot in CLAUDE.md and the register, not merely fixed around -- the admit_cases unit table is the only place order is asserted at all. Re-measured the full blast radius against the same pre-change binary: same 14,627 differing days, same four shapes and counts, confirming the fix changed only the content of the 593 shape-(c) rows and nothing else. Mutation-tested: reverting the splice back to a uniform prepend reddens exactly the shape-(c) unit test; a new golden pin for a real shape-(c) day (2004-02-22) stays green under the same mutation, living proof that golden pins cannot see this axis, not merely a claim. Separately, M19's own predicate checked a date and a diff shape but not which candidate -- proved insufficient by fabricating a second, bogus companion on 30 June and confirming the whole suite stayed green. Fixed by requiring the admitted commemoration to be exactly commemoration-of-st-peter, mirroring C16's own identity guard. Added a golden pin for 30 June, the only assertion of that entry's identity outside the allow-list. Also: corrected a false claim in the task report that the electronic transcription carries no corroboration of the Holy Name fallback -- its own table of contents does, at a line not checked on the first pass. Added two further citations, both re-verified against the scan: RG 17's own closing paragraph, settling the Sunday shape's Sunday- exclusion at the rubric level rather than only in the propers; RG 124(c), which assigns red to 30 June by paragraph number rather than by the generic apostle/martyr default. Noted the fragility of deriving the Sunday shape's RG 109(a) privilege from a slug-substring match rather than from a citation. Cosmetic: a stray blank line and an indentation inconsistency. --- test/test_golden.ml | 52 ++++++++++++++++++++++++++++++++++++++++++++++ test/test_oracle.ml | 28 +++++++++++++++++++++++-- test/test_precedence_ef.ml | 35 ++++++++++++++++++++++++------- 3 files changed, 105 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/test/test_golden.ml b/test/test_golden.ml index 80e2c9d..0f90ee7 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -691,6 +691,51 @@ let test_holy_name_fallback_2029 () = "2029-01-02 tuesday season=christmastide week=- slug=ef-holy-name rank=class-2 colour=white \ subject=lord comms=[] in=- out=[]" +(* RG 110 (docs/research/rules-register.md §4, Caput XIV), fix round 1 + (coordinator findings F1/F2): two golden pins neither existed before this + round -- F2 named 30 June's own total absence of golden coverage + directly ("no golden pin on any 30 June date"), and F1 named the + shape-(c) collision as a real day this suite otherwise never exercises + end-to-end against real data (both new [admit_cases] rows are synthetic + candidates, not `Calendar.day` over the real committed layer). + + *** BOTH PINS ARE BLIND TO COMMEMORATION ORDER -- STATED HONESTLY, NOT + CLAIMED AS PROOF OF F1's OWN FIX *** + + [describe]'s own `comms` field (this file's header, above) sorts the + commemoration list alphabetically before rendering + (`List.sort compare`) -- deliberately, so a golden pin's own STRING + comparison is not accidentally order-sensitive where nothing textual + requires it to be. That means this file, like the differential and the + oracle's own [identity_diff] (test_oracle.ml), CANNOT see whether + [rg110_additions] emits `chair-of-st-peter, paul` or `paul, + chair-of-st-peter` -- both sort to the same string. The ONLY place in + this codebase's test suite that asserts commemoration ORDER at all is + `test_precedence_ef.ml`'s own [admit_cases] table (`Alcotest.(check + (list string))`, not a sorted string) -- see precedence_ef.ml's own + [rg110_additions] comment for the citation this uses to fix the order, + and CLAUDE.md's "know what each layer cannot see" section for this as a + permanent, structural limit, not a gap this task's own pins happened not + to close. These two pins prove PRESENCE and IDENTITY of both + commemorations on a real, `Calendar.day`-resolved date -- genuine + ground no other pin in this file currently covers -- not order. *) +let test_rg110_june_30_2026 () = + check ~msg:"2026-06-30: RG 110's 30-June direction -- In Commemoratione Sancti Pauli Apostoli observed, \ + +commemoration-of-st-peter (data/ef/adjustments.sexp's own `Add` directive) the sole \ + commemoration -- missalemeum shows neither (M19, verdict colitur)" + 2026 6 30 + "2026-06-30 tuesday season=time-after-pentecost week=5 slug=in-commemoratione-sancti-pauli-apostoli \ + rank=class-3 colour=red subject=saint comms=[commemoration-of-st-peter:ordinary] in=- out=[]" + +let test_rg110_shape_c_2004 () = + check ~msg:"2004-02-22: RG 110 shape (c) -- Chair of St Peter itself loses the day to an ordinary \ + (Septuagesima, not I-class) II-class Sunday and is admitted only as a commemoration under \ + RG 111(b)'s own rank floor; Paul rides along too, uncapped (`date -d 2004-02-22 +%A` = \ + Sunday, independently confirmed)" + 2004 2 22 + "2004-02-22 sunday season=septuagesima week=3 slug=ef-septuagesima-sunday-3 rank=class-2 colour=violet \ + subject=temporal comms=[chair-of-st-peter:ordinary,paul:ordinary] in=- out=[]" + (* 2025-02-02, the other real instance of the SAME pattern -- not a contrasting second direction, per this task's fix round 1 (CRITICAL finding, item 1, reverted; see register §6.0 for the full account). @@ -856,6 +901,13 @@ let suite = "Holy Name of Jesus, fallback shape (RG17(a) \"secus die 2 ianuarii\", 2029-01-02 -- no Sunday in \ the window)" `Quick test_holy_name_fallback_2029; + Alcotest.test_case + "RG110: 30 June, In Commemoratione S. Pauli Apostoli + commemoration-of-st-peter (2026-06-30)" `Quick + test_rg110_june_30_2026; + Alcotest.test_case + "RG110 shape (c): Chair of St Peter admitted only as a commemoration of an ordinary Sunday, Paul \ + rides along (2004-02-22)" + `Quick test_rg110_shape_c_2004; Alcotest.test_case "ef-rebootstrap: RG91 entry24 (III-class feast) outranks entry28 (class-4 feria) -- the six dates \ deferred since 2038's own Easter-extreme pin (2008-04-02/04/05, 2038-03-06/08/09)" diff --git a/test/test_oracle.ml b/test/test_oracle.ml index 370eec0..58ceb26 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -796,9 +796,32 @@ let m16_dates = [ "2026-03-27" ] citation-count coincidence: RG 110's own text is unconditional ("in Officio et Missa S. Petri semper fit commemoratio S. Pauli, ET VICISSIM"), and the calendarium's own June table states the SAME - pattern already built for the other two pairs, word for word. *) + pattern already built for the other two pairs, word for word. + + IDENTITY-GATED, fix round 1 (coordinator finding F2): the predicate + below now also requires [c.c_commemorations] to be EXACTLY the single + entry [commemoration-of-st-peter] -- not merely that some [Comm_presence] + diff exists on these two dates. Proved necessary, not decorative: the + reviewer added a SECOND, fabricated `Add` directive on 30 June (a + `bogus-fabricated-companion` slug) to a scratch copy of + data/ef/adjustments.sexp and found the whole suite stayed green with the + pre-fix, presence-only predicate -- the exact C6/C14 failure mode (a + Layer-C-style predicate that pins a date and a diff SHAPE but not WHICH + candidate). This matters more here than for any other entry in this + file: `commemoration-of-st-peter` is corroborated by NEITHER oracle (it + rests on a scan reading alone, data/ef/adjustments.sexp's own citation), + so this allow-list predicate is the only place in the whole suite that + could assert what colitur actually emits here -- and, pre-fix, asserted + nothing about it. Mirrors C16's own identity guard + (`String.equal c.slug "ef-holy-name"`, test_differential.ml) at the + analogous decision point in this file. *) let m19_dates = [ "2026-06-30"; "2027-06-30" ] +let m19_commemoration_matches (c : colitur_row) = + match c.c_commemorations with + | [ (slug, _, _, _) ] -> String.equal slug "commemoration-of-st-peter" + | _ -> false + let layer_m_reason (c : colitur_row) (o : oracle_row) diffs = if diffs = [] then None (* M1's own subset widened (this task): colitur's observed day on both @@ -850,7 +873,8 @@ let layer_m_reason (c : colitur_row) (o : oracle_row) diffs = && subset diffs [ Comm_identity_mismatch; Observed_identity_unresolved ] then Some "M16" else if diffs = [ Observed_identity_unresolved ] then Some "M18" - else if List.mem c.c_date m19_dates && diffs = [ Comm_presence ] then Some "M19" + else if List.mem c.c_date m19_dates && diffs = [ Comm_presence ] && m19_commemoration_matches c then + Some "M19" else None (* ---------------------------------------------------------------------- *) diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml index af7f65e..639f64c 100644 --- a/test/test_precedence_ef.ml +++ b/test/test_precedence_ef.ml @@ -1146,8 +1146,14 @@ let admit_cases = precedence_ef.ml's own measured defect (3,533 of 8,417 domain-wide years, this task's own report): Paul loses the slot outright and is never admitted at all. With RG 110, Paul is added ADDITIONALLY, - PREPENDED ahead of the feria per RG 110(c)'s own "ante omnes alias - commemorationes" -- both admitted, not one displacing the other. *) + PREPENDED ahead of the feria -- RG 110(a)/(b)'s own text ("oratio + alterius Apostoli additur ... orationi diei", the companion's oration + added to the DAY's own oration) governs here, not (c)'s "ante omnes + alias commemorationes" (CORRECTED, fix round 1, coordinator finding + F1: this comment previously cited (c) for both shapes uniformly -- + see [rg110_additions]'s own comment in precedence_ef.ml for why the + two shapes need, and get, DIFFERENT orderings, not the same one for + different reasons) -- both admitted, not one displacing the other. *) ( "RG110 (a)/(b): chair-of-st-peter observed, Paul rides alongside a \ competing privileged Lent feria, uncapped and prepended", chair_of_st_peter_synth, chair_of_st_peter_synth, @@ -1157,16 +1163,29 @@ let admit_cases = (observed is some unrelated II-class Sunday) but is admitted, on its OWN Class2 dignity, as RG 111(b)'s single ordinary commemoration -- exactly the domain-wide 593-year pattern this task's own report - measures. RG 110(c)'s own text ("quoties vero oratio unius Apostoli - addenda est ad modum commemorationis...") governs precisely this: the + measures. RG 110(c)'s own text, word for word ("quoties vero oratio + unius Apostoli addenda est ad modum commemorationis, HUIC ORATIONI + ADDITUR ALTERA immediate, ante omnes alias commemorationes"): the companion (Paul, Class3, no standing of its OWN for this Sunday's - rank-floored slot) rides along anyway, uncapped. *) + rank-floored slot) rides along anyway, uncapped -- ADDED TO THE + TRIGGER'S own oration ("huic orationi additur altera"), i.e. + FOLLOWING it, not preceding it. CORRECTED, fix round 1 (coordinator + finding F1): this row originally asserted `["paul"; + "chair-of-st-peter"]` -- the companion BEFORE the trigger -- citing + the SAME "ante omnes alias commemorationes" clause that actually + governs the PAIR's position relative to OTHER, unrelated + commemorations, not the pair's own internal order. "Huic orationi" + (dative, "to THIS oration") refers back to "oratio unius Apostoli", + the trigger's own oration -- so the companion is added TO it, + following, not leading. Reproduced by mutation: reverting + [rg110_additions]'s shape-(c) branch back to a uniform prepend + reddens exactly this row's own expected order, nothing else. *) ( "RG110 (c): chair-of-st-peter admitted merely AS a commemoration \ - (loses the day to an ordinary II-class Sunday), Paul still rides \ - along", + (loses the day to an ordinary II-class Sunday), Paul rides along \ + AFTER it (RG110(c): \"huic orationi additur altera\")", cand ~rank:V.Class2 "ef-some-other-sunday", cand ~rank:V.Class2 "ef-some-other-sunday", [ po chair_of_st_peter_synth P.Ordinary; (paul_companion_synth, P.Ordinary, 999) ], - [ "paul"; "chair-of-st-peter" ] ); + [ "chair-of-st-peter"; "paul" ] ); (* Defensive: a trigger slug is [observed], but its companion is simply not present among [comms] at all (a data gap, or -- as this exact shape was for 30 June before this task's own [Add -- cgit v1.3