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_oracle.ml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test/test_oracle.ml') diff --git a/test/test_oracle.ml b/test/test_oracle.ml index 7ee3848..f1d1a89 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -1878,6 +1878,21 @@ let classify_2038 (c : colitur_row) (o : oracle_row) diffs = else if contains title "Mass of the B. V. M." then Some "BVM-SATURDAY-MASS (M26 shape 1)" else if first_is "Col 1:12-20" then Some "CHRIST-THE-KING-WEEK (M26 shape 2b)" else if diffs = [ Colour_f ] && List.mem c.c_observed_slug m21_2038_slugs then Some "COLOUR (M21)" + (* RG 33's third omission trigger (register 6.31, implemented + 2026-08-21). The Sacred Heart takes 24 June 2038, so the Nativity of St + John the Baptist is transferred under RG 96 and the vigil of 23 June is + "penitus omissa". missalemeum keeps it -- as does lectio, whose own C39 + covers this same date on the differential side, which is exactly what + one expects of two points on one lineage. Gated on the ORACLE's own + title rather than on the date, so a different divergence arriving on 23 + June could not be silently absorbed here. Cited to the register rather + than to an allow-list id because data/ef/expected-divergences-missalemeum.sexp + is scoped to the 2026-2027 window, which contains no instance of this + clause -- the same convention PERPETUA-COMMON and MISSAL-TWO-PART-CITATION + already follow. The tracked, full account is C39's own note in + data/ef/expected-divergences.sexp. *) + else if contains title "Vigil of the Nativity of St. John the Baptist" then + Some "RG33-THIRD-TRIGGER (colitur; register 6.31, see C39)" else if first_is "Judith" then Some "JUDITH (M28, register 6.6)" else if c.c_observed_slug = "sts-felicitas-perpetua" then Some "PERPETUA-COMMON (register 6.8)" else if c.c_observed_slug = "ef-nativity" then Some "CHRISTMAS-MULTI-MASS (M27)" @@ -2108,6 +2123,9 @@ let test_2038_class_counts () = ("COMM-ONLY-TIE-BREAK (RG-under-determined convention -- register 6.16)", 1); ("JOSEPH-ANNUNCIATION-TRANSFER-ORDER (C14's own collision)", 2); ("JUDITH (M28, register 6.6)", 2); + (* RG 33's third trigger: 23 June only -- the Sacred Heart takes 24 + June 2038 and St John the Baptist transfers. See M31. *) + ("RG33-THIRD-TRIGGER (colitur; register 6.31, see C39)", 1); ("MISSAL-TWO-PART-CITATION (register 6.9)", 1); ("COMM-IDENTITY-UNRESOLVED (temporal-origin, no English name -- M15's limit)", 2); ("PERPETUA-COMMON (register 6.8)", 1); -- cgit v1.3