summaryrefslogtreecommitdiff
path: root/test/test_golden.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-21 14:42:30 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-21 14:42:30 +0200
commit12b97761019cfa02ca0da8a5fb50ef815d07685c (patch)
tree11e7306a1a5de2f5226eea06282515ff38b226d5 /test/test_golden.ml
parent0eae32f67145065b0e4960650ae06c293fd9f272 (diff)
downloadcolitur-12b97761019cfa02ca0da8a5fb50ef815d07685c.tar.gz
colitur-12b97761019cfa02ca0da8a5fb50ef815d07685c.zip
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.
Diffstat (limited to 'test/test_golden.ml')
-rw-r--r--test/test_golden.ml80
1 files changed, 72 insertions, 8 deletions
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