From 12b97761019cfa02ca0da8a5fb50ef815d07685c Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 21 Aug 2026 14:42:30 +0200 Subject: feat(ef): implement RG 33's third omission trigger RG 33 omits a II/III-class vigil in three cases: it falls on a Sunday, it falls on a I-class feast, "vel si festum cui praemittitur in alium diem transferri aut ad commemorationem reduci contingat". Only the first two were built; the third was recorded in precedence_ef.ml as unimplemented on the grounds that no witness existed in the shipped data. That reasoning was wrong, and the rule fires on 1 744 days across 1583-9999. Both halves of the clause reduce to one observable question -- is the feast the OBSERVED office on the following day (RG 34 puts it there) -- so the kernel asks it once per candidate, after place_transfers has settled the year. No fixed point is needed: a vigil is a candidate only on its own day, never on its feast's, so suppressing it cannot change what the next day observes. Precedence.rules gains vigil_feast, which returns the slug of the feast a vigil precedes; the kernel cannot infer that itself, because only two of the five vigil/feast pairs share a slug stem. Blast radius, measured pre-change binary vs HEAD over the whole domain and classified: 1 744 days, three shapes, zero unexplained. 1 199 are the feast reduced to a commemoration (10 August on a Sunday, St Lawrence); 478 and 67 are the feast transferred under RG 96 after the Sacred Heart or Corpus Christi takes its day. The Assumption's and the Ascension's vigils never qualify -- their I-class feasts always keep their own day. Independently witnessed, which is unusual here. The published Ordo -- the only witness outside the Divinum Officium -> missalemeum -> lectio lineage -- omits St Lawrence's vigil on 2025-08-09, agreeing with colitur against both engines. That date had been read earlier as an Ordo gap; the Ordo was right, and correcting the misreading is what surfaced this clause. On 2027-08-09 the feast does keep its day and the Ordo omits a vigil colitur correctly keeps, which is a genuine Ordo gap. Allow-lists: C39 (lectio, 10 rows) and a 2038 oracle class citing the register, the 2026-2027 window having no instance. The golden pin asserting St Lawrence's vigil is violet moved 2025 -> 2027; its own comment had reasoned about the vigil's weekday and missed that RG 33 also looks at the feast's. Two new pins cover both shapes of the clause. The vigil/feast table is built with Slug.of_string_exn: mutation testing showed that of_string plus Result.to_option turns a typo into None, which this hook's contract reads as "not a vigil", switching the rule off in silence. Two tests assert the table against the shipped data in both directions. --- test/test_golden.ml | 80 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 8 deletions(-) (limited to 'test/test_golden.ml') diff --git a/test/test_golden.ml b/test/test_golden.ml index 33ca362..b882596 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -1327,14 +1327,70 @@ let test_rogation_wednesday_yields_to_a_feast_2026 () = white" -- which colitur already emits correctly (ef-ascension-vigil, white, pinned by the two Rogation Wednesday cases just above). - Pinned in years where each vigil is actually OBSERVED rather than impeded: - 9 August 2025 is a Saturday and 14 August 2025 a Thursday, both checked - with `date -d`. In 2026, 9 August is a Sunday and the vigil never appears. *) -let test_vigil_of_st_lawrence_is_violet_2025 () = - check ~msg:"RG 128: III-class vigil outside Paschaltide is violet, not red" 2025 8 9 - "2025-08-09 saturday season=time-after-pentecost week=8 slug=vigil-of-st-lawrence \ + Pinned in years where each vigil is actually OBSERVED rather than impeded. + 14 August 2025 is a Thursday and the Assumption always keeps 15 August (I + class, nothing in the universal calendar outranks it), so that pin is + stable in any year the vigil's own day is free. + + ST LAWRENCE'S PIN MOVED 2025 -> 2027 when RG 33's third omission trigger + was implemented. Its original comment reasoned only about the vigil's OWN + weekday -- "9 August 2025 is a Saturday", true, so RG 33's Sunday trigger + does not fire -- and missed that the rule also looks at the FEAST: 10 + August 2025 is a Sunday, the II-class Sunday reduces St Lawrence to a + commemoration, and "vel si festum cui praemittitur... ad commemorationem + reduci contingat" omits the vigil entirely. The day now keeps the BVM + Saturday Office instead, pinned separately just below. 9 August 2027 is a + Monday and 10 August 2027 a Tuesday (both `date -d`-checked), so St + Lawrence keeps his own day there and the vigil genuinely is observed -- + which is what this pin has always been trying to assert about RG 128's + colour rule. *) +let test_vigil_of_st_lawrence_is_violet_2027 () = + check ~msg:"RG 128: III-class vigil outside Paschaltide is violet, not red" 2027 8 9 + "2027-08-09 monday season=time-after-pentecost week=12 slug=vigil-of-st-lawrence \ rank=class-3 colour=violet subject=saint name_la=- comms=[romanus:ordinary] in=- out=[]" +(* RG 33's THIRD omission trigger -- "vel si festum cui praemittitur in alium + diem transferri aut ad commemorationem reduci contingat" -- on the shipped + universal calendar, no overlay involved. 10 August 2025 is a Sunday; the + II-class Sunday outranks St Lawrence's II-class feast (RG 15), so the feast + is "ad commemorationem reducta" on its own day and the vigil of 9 August is + "penitus omissa". + + This is the clause's most common live shape by a wide margin: 1 199 of the + 1 744 days it fires on across 1583-9999 are St Lawrence's vigil dropped + because 10 August fell on a Sunday. The day does not become a bare feria -- + 9 August 2025 is a Saturday, so RG 78's votive Office of the BVM takes the + freed IV-class Saturday, which is why this pin reads white and subject=bvm. + St Romanus keeps his commemoration either way (RG 111). + + Independently witnessed. The published Ordo -- the project's only witness + outside the Divinum Officium -> missalemeum -> lectio lineage -- omits the + vigil on this exact date, and lectio (and so missalemeum) keeps it; both + allow-lists gained cited entries for that disagreement. *) +let test_rg33_vigil_omitted_when_its_feast_is_commemorated_2025 () = + check + ~msg:"RG 33: 10 Aug 2025 is a Sunday, so St Lawrence is only commemorated and his vigil is \ + omitted entirely -- the BVM Saturday Office (RG 78) takes the freed day" + 2025 8 9 + "2025-08-09 saturday season=time-after-pentecost week=8 \ + slug=ef-time-after-pentecost-8-saturday rank=class-4 colour=white subject=bvm \ + name_la=Officium sanctae Mariae in sabbato comms=[romanus:ordinary] in=- out=[]" + +(* The same clause's OTHER half, "in alium diem transferri". 24 June 2038 is + impeded by the Sacred Heart (I class, movable), so the Nativity of St John + the Baptist is TRANSFERRED under RG 96 and its vigil of 23 June is omitted. + 478 days across the domain take this shape (a further 67 via Corpus + Christi). Pinned in 2038 because that year already carries an oracle + fixture, so the divergence this creates is visible to layer 4 as well. *) +let test_rg33_vigil_omitted_when_its_feast_transfers_2038 () = + check + ~msg:"RG 33: the Sacred Heart takes 24 June 2038, St John the Baptist transfers, \ + and his vigil of 23 June is omitted entirely" + 2038 6 23 + "2038-06-23 wednesday season=time-after-pentecost week=1 \ + slug=ef-time-after-pentecost-1-wednesday rank=class-4 colour=green subject=temporal \ + name_la=- comms=[] in=- out=[]" + let test_vigil_of_the_assumption_is_violet_2025 () = check ~msg:"RG 128: II-class vigil outside Paschaltide is violet, not white" 2025 8 14 "2025-08-14 thursday season=time-after-pentecost week=9 slug=vigil-of-the-assumption \ @@ -1342,8 +1398,16 @@ let test_vigil_of_the_assumption_is_violet_2025 () = let suite = ( "golden pins (known-tricky years)", - [ Alcotest.test_case "RG128: St Lawrence's vigil is violet (2025)" `Quick - test_vigil_of_st_lawrence_is_violet_2025; + [ Alcotest.test_case "RG128: St Lawrence's vigil is violet (2027)" `Quick + test_vigil_of_st_lawrence_is_violet_2027; + Alcotest.test_case + "RG33 third trigger: the vigil is omitted when its feast is reduced to a commemoration \ + (2025-08-09, St Lawrence)" + `Quick test_rg33_vigil_omitted_when_its_feast_is_commemorated_2025; + Alcotest.test_case + "RG33 third trigger: the vigil is omitted when its feast is transferred away \ + (2038-06-23, St John the Baptist)" + `Quick test_rg33_vigil_omitted_when_its_feast_transfers_2038; Alcotest.test_case "RG128: the Assumption's vigil is violet (2025)" `Quick test_vigil_of_the_assumption_is_violet_2025; Alcotest.test_case "Easter extreme: 1598 earliest (22 Mar, Gauss-verified)" `Quick -- cgit v1.3 From afd82f97ff440add51ea3e87c7ab53938443d5a0 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 21 Aug 2026 15:00:03 +0200 Subject: docs(C39): withdraw the Ordo corroboration claim C39 and the 2025 golden pin both claimed the published Ordo independently confirms RG 33's third trigger, because it omits St Lawrence's vigil on 2025-08-09 where lectio and missalemeum keep it. It does not. The Ordo omits that vigil on 2027-08-09 as well, where the clause says to keep it (10 August is a Tuesday, the feast holds its day), and 2026-08-09 is a Sunday where the rule's first trigger omits it anyway. The 2024 date has no row. So the Ordo never shows St Lawrence's vigil on any date it covers, and the 2025 agreement is a blanket gap coinciding with the right answer, not evidence. The rule itself is unaffected: it rests on RG 33's text, which admits no latitude, and on lectio not evaluating the clause at all -- "RG 33" appears nowhere in its production code, and the third trigger cannot emerge from per-day rank comparison because it turns on what is observed the following day. The divergence is architectural, not a disagreement about the rubric. Recorded rather than deleted: the withdrawn claim is why this entry was first written up as unusually well corroborated. --- data/ef/expected-divergences.sexp | 4 +++- test/test_golden.ml | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'test/test_golden.ml') diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index bba21c1..8078611 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -96,7 +96,9 @@ Two shapes, both in the rubric's own words. SIX rows are 'ad commemorationem red Domain-wide this clause fires on 1 744 of the 3 074 246 days in 1583-9999 -- 1 199 St Lawrence, 347 St John the Baptist, 198 Sts Peter and Paul -- measured by diffing a pre-change binary against HEAD over the whole domain and classifying every changed day: three shapes, zero unexplained, and every one independently re-checked to confirm the feast really is absent from its own day. -INDEPENDENTLY WITNESSED, which is rare in this file and is the reason this entry is verdict colitur rather than open. The published Ordo -- the project's only witness outside the Divinum Officium -> missalemeum -> lectio lineage (see CLAUDE.md's own account of why layers 3 and 4 are one lineage, not two) -- omits the vigil on 2025-08-09, agreeing with colitur against both engines. It had been examined earlier in the same session that implemented this rule and misread as an Ordo GAP, on the reasoning that the Missal's calendarium lists the vigil; the calendarium lists it as a fixed entry, which is not a claim about whether it survives a given year's occurrence. The Ordo was right. Two dates were compared and they part company for the correct reason: on 2027-08-09 (10 August a Tuesday, the feast keeps its day) the Ordo omits a vigil colitur correctly keeps, and that one IS an Ordo gap. +CORRECTED 2026-08-21, BEFORE THIS ENTRY WAS EVER REVIEWED: an earlier version of this note claimed the published Ordo -- the project's one witness outside the Divinum Officium -> missalemeum -> lectio lineage -- INDEPENDENTLY CONFIRMS colitur here, because it omits St Lawrence's vigil on 2025-08-09 where both software engines keep it. That claim does not survive its own check and is withdrawn. The Ordo covers 2024-2027 and omits that vigil on BOTH 2025-08-09 (where this clause says omit) and 2027-08-09 (where it says keep, 10 August being a Tuesday); 2026-08-09 is a Sunday, omitted by the rule's FIRST trigger anyway, and the fixture has no row for 2024-08-09. So the Ordo never shows St Lawrence's vigil on any date it covers, and its agreement on 2025-08-09 is a coincidence of a blanket gap, not evidence of the third trigger. The Ordo has nothing to say here in either direction. Recorded rather than quietly deleted because the withdrawn claim was the reason this entry was first written up as unusually well corroborated, and a reader who saw that framing should be able to see it retracted. + +WHAT THIS ENTRY ACTUALLY RESTS ON, then. Two things, neither of them a second witness. FIRST, the primary text, which admits no interpretive latitude: RG 33 joins three triggers with 'vel'/'aut' and the third is a plain conditional on the feast's own fate. SECOND -- and this is the substantive point -- lectio does not DISAGREE with the clause, it never evaluates it. 'RG 33' appears nowhere in lectio's production code, only in one test file's comments; its Sunday behaviour is emergent from ordinary rank comparison (a II-class Sunday outranks a III-class vigil), not from a transcribed rule. The third trigger cannot emerge that way at all, because it turns on what is observed the day AFTER, and a per-day precedence contest has no access to it. That is exactly why implementing it in colitur required a whole-year pass and a new field on Precedence.rules rather than a branch in disposition. So the divergence is architectural, not exegetical: on these 10 days lectio is not asserting that the vigil survives, it is producing the only answer its shape can produce. missalemeum and Divinum Officium inherit the same limit by lineage. Gated on lectio's own slug being one of the three vigils this clause can reach and colitur's not being a vigil -- identity on both sides, not a diff-set shape. The Assumption's and the Ascension's vigils are absent from that list because their I-class feasts always keep their own day: 0 occurrences across the whole domain, measured rather than assumed.") (expected_rows 10)) diff --git a/test/test_golden.ml b/test/test_golden.ml index b882596..14fbec4 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -1363,10 +1363,14 @@ let test_vigil_of_st_lawrence_is_violet_2027 () = freed IV-class Saturday, which is why this pin reads white and subject=bvm. St Romanus keeps his commemoration either way (RG 111). - Independently witnessed. The published Ordo -- the project's only witness - outside the Divinum Officium -> missalemeum -> lectio lineage -- omits the - vigil on this exact date, and lectio (and so missalemeum) keeps it; both - allow-lists gained cited entries for that disagreement. *) + NOT independently witnessed, and an earlier version of this comment wrongly + said it was. The published Ordo does omit the vigil on this date -- but it + also omits it on 2027-08-09, where this clause says to KEEP it, so it never + shows St Lawrence's vigil at all in the years it covers and cannot + corroborate anything here. This pin rests on RG 33's own text and on the + fact that lectio never evaluates the clause (it appears nowhere in its + production code); see C39's own note in + data/ef/expected-divergences.sexp. *) let test_rg33_vigil_omitted_when_its_feast_is_commemorated_2025 () = check ~msg:"RG 33: 10 Aug 2025 is a Sunday, so St Lawrence is only commemorated and his vigil is \ -- cgit v1.3