From f8d694d0cc19b71598e1ab64254efb069969f0a0 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Sat, 15 Aug 2026 00:36:43 +0200 Subject: kernel+ef: fix round 1 -- lectionary caller-supplied, not eager Critical (coordinator review): a clean `dune build` produced a `colitur` that died at startup on EVERY subcommand, including ones touching no lectionary data at all. Root cause was two-fold: data/ef/lectionary.sexp was never added to the root default-build alias (only materialised as a side effect of the test suite's own deps, which is why every check in the prior report passed), and Rite_ef.context loaded it as a module-init side effect via failwith, undoing Lectionary.load's own "never raises" promise at a point no caller could catch. Fixed structurally: Rite_ef.context is now a function taking ~lectionary, Lectionary_ef.readings takes ~lectionary, and neither touches the filesystem any more -- the same caller-supplied discipline the sanctoral layer already had, restoring rite_ef.mli's own pre-existing claim about it and leaving a seam for a future diocesan lectionary overlay. bin/main.ml grows load_ef_lectionary, a sibling of load_ef_layer, routed through the same colitur: %s / exit 2 path. data/ef/lectionary.sexp added to the root default alias. Every caller of Rite_ef.context updated to supply it. Also: two new tests that genuinely distinguish chain step 1 from step 2 (19 March 2026, Joseph's own proper over a competing temporal entry; 13 January 2030, Holy Family reached only through the temporal slug, the Baptism entirely absent) -- the prior two tests both survived swapping the chain order. Both new pins verified directly against the real data. The chain's own comment now states plainly that its warrant is lectio's observed behaviour, not a confirmed Missal citation, per the rules register's own open item. --- test/test_rite_ef.ml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'test/test_rite_ef.ml') diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml index 67b42ce..7680545 100644 --- a/test/test_rite_ef.ml +++ b/test/test_rite_ef.ml @@ -49,6 +49,15 @@ let real_layer () = (List.map Overlay.diagnostic_to_string diagnostics); layer +(* [Rite_ef.context] takes [~lectionary] (fix round 1, coordinator review) -- + caller-supplied, same as [real_layer] above. *) +let real_lectionary () = + match Colitur_kernel.Lectionary.load "../data/ef/lectionary.sexp" with + | Ok l -> l + | Error e -> Alcotest.failf "../data/ef/lectionary.sexp: failed to load: %s" e + +let context () = Rite_ef.context ~lectionary:(real_lectionary ()) + let slug_of (c : V.rank Cel.t) = Slug.to_string c.Cel.slug (* Finding 3: the suppression's ONLY observable effect is on 24 December's @@ -64,7 +73,7 @@ let slug_of (c : V.rank Cel.t) = Slug.to_string c.Cel.slug alone structurally cannot. *) let test_vigil_of_christmas_suppressed () = let layer = real_layer () in - let days = Cal.year Rite_ef.context layer 2026 in + let days = Cal.year (context ()) layer 2026 in let christmas_eve = Array.to_list days |> List.find (fun d -> Date.compare d.LD.date (mk 2026 12 24) = 0) in @@ -251,7 +260,7 @@ let test_barbara_added () = Alcotest.(check bool) "barbara: Red (RG124(e), \"Virg. et Mart.\")" true (e.Layer.cel.Cel.colour = Colour.Red); Alcotest.(check bool) "barbara: appears as a commemoration on 4 December in real output" true - (let days = Cal.year Rite_ef.context layer 2026 in + (let days = Cal.year (context ()) layer 2026 in Array.to_list days |> List.exists (fun d -> Date.compare d.LD.date (mk 2026 12 4) = 0 @@ -281,7 +290,7 @@ let test_transfer_search_does_not_raise_at_domain_ceiling () = in let layer, _diagnostics = Overlay.apply layer overlay in (* Must not raise -- the whole point of the fix. *) - let days = Cal.year Rite_ef.context layer 9999 in + let days = Cal.year (context ()) layer 9999 in Alcotest.(check bool) "year 9999 resolves without raising, even with an impeded Christmas Day" true (Array.length days > 0); let impeder_placed_or_recorded = @@ -350,7 +359,7 @@ let test_no_transfer_lands_in_easter_octave () = let violations = ref [] in List.iter (fun y -> - let days = Cal.year Rite_ef.context layer y in + let days = Cal.year (context ()) layer y in Array.iter (fun (d : (V.season, V.rank) LD.t) -> (match d.LD.transferred_in with @@ -388,7 +397,7 @@ let test_major_litanies_transfers_inside_easter_octave_exactly_when_rg80_require let landings = ref [] in List.iter (fun y -> - let days = Cal.year Rite_ef.context layer y in + let days = Cal.year (context ()) layer y in Array.iter (fun (d : (V.season, V.rank) LD.t) -> List.iter @@ -491,7 +500,7 @@ let test_maurice_thomas_band_fidelity_end_to_end () = is reached via [Cal.year ... 2026], not 2027 -- the same [y-1]/straddling indexing test_oracle.ml's own header comment already documents for exactly this reason. *) - let days = Cal.year Rite_ef.context layer 2026 in + let days = Cal.year (context ()) layer 2026 in let day = Array.to_list days |> List.find (fun d -> Date.compare d.LD.date (mk 2027 9 22) = 0) in Alcotest.(check string) "the September Ember Wednesday office itself is observed (band entry 18)" "ef-september-ember-wed" (slug_of day.LD.observed); -- cgit v1.3