summaryrefslogtreecommitdiff
path: root/test/test_precedence_of.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-25 23:51:36 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-25 23:51:36 +0200
commit0994587b3694bb87d9a8ee32d60babf25c784acf (patch)
tree5585419d69e0b89fa839aba94ef50a3297251fbc /test/test_precedence_of.ml
parent98d698b261c75a287ba3992744032babfb6ad763 (diff)
downloadcolitur-0994587b3694bb87d9a8ee32d60babf25c784acf.tar.gz
colitur-0994587b3694bb87d9a8ee32d60babf25c784acf.zip
fix(of): correct subject over-match, provenance truth, and stale hazard comment
Four fixes from fix round 2 review: classify_subject's "maria"/"b.m.v" substring test over-matched 12 saints who merely carry "Maria" in their own name (Maximilian Mary Kolbe, John Mary Vianney, Mary Magdalene among them) as Bvm. Replaced with an explicit BVM_DATES table of the 13 genuinely Marian entries. Bvm 25 -> 13. The provenance header claimed lectio is "never a source", which omitted that slugs and English names both come from it. Corrected to state exactly what does (slugs, en names) and does not (every substantive field) come from lectio. A missing lectio file used to degrade silently to a different SHA-256 with no en names and no warning; it now fails loudly. lectio's own SHA-256 is now pinned alongside the Missal PDF's. Four more entries carried a second pdftotext artifact distinct from the letter-spacing already handled -- a combining diacritic rendered as a stray spacing character (Kim Taegŏn/Chŏng Ha-sang, Đũng Lạc, Makhlūf, Kęty). Hand-repaired the same way Peter Damian was, each corroborated by the identical corruption recurring in the Missal's own index. precedence_of.ml's PHASE 3 HAZARD comment about All Souls (2 November) was asserting a gap that no longer exists now that OF sanctoral data ships. Added test_all_souls_beats_an_ordinary_sunday, which resolves the shipped All Souls entry against a real per-annum Sunday (2025-11-02) through the actual Precedence.resolve pipeline, and updated the comment to record the resolution instead of demanding it.
Diffstat (limited to 'test/test_precedence_of.ml')
-rw-r--r--test/test_precedence_of.ml49
1 files changed, 48 insertions, 1 deletions
diff --git a/test/test_precedence_of.ml b/test/test_precedence_of.ml
index 610cbfb..e1af486 100644
--- a/test/test_precedence_of.ml
+++ b/test/test_precedence_of.ml
@@ -436,6 +436,50 @@ let test_target_is_free_of_entries_1_to_8 () =
true (b > 80))
[ "2027-03-25"; "2035-03-25"; "2026-03-25"; "2029-03-25" ]
+(* Fix round 2 (Task 1, 2026-08-25): the shipped All Souls entry (2
+ November, data/of/calendar-2002.sexp) actually beats an ordinary
+ per-annum Sunday when they coincide -- the exact hazard the [band]
+ comment above named ("PHASE 3 HAZARD ... before shipping OF sanctoral
+ data"). Loads the REAL shipped entry (not a synthetic reconstruction)
+ and resolves it through {!Colitur_kernel.Precedence.resolve} with
+ [Rite_of.Precedence_of.rules] -- not [band] in isolation -- against a
+ real per-annum Sunday context, 2 November 2025 (independently a real
+ Sunday: date -d confirms it, and it is the same date CLAUDE.md's own
+ EF golden pin "All Souls falling on a Sunday" already uses). *)
+let test_all_souls_beats_an_ordinary_sunday () =
+ let path = "../data/of/calendar-2002.sexp" in
+ let l =
+ match Colitur_kernel.Layer.load Vocab_of.rank_of_sexp path with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s: failed to load: %s" path e
+ in
+ let all_souls =
+ match Colitur_kernel.Layer.find l (Slug.of_string_exn "all-souls") with
+ | Some e -> e.Colitur_kernel.Layer.cel
+ | None -> Alcotest.fail "\"all-souls\" not found in the shipped calendar"
+ in
+ Alcotest.(check bool) "shipped All Souls is tagged Sollemnitas" true
+ (all_souls.Celebration.rank = Vocab_of.Sollemnitas);
+ let all_souls_candidate = { Precedence.cel = all_souls; origin = Precedence.Sanctoral } in
+ let d = Date.of_iso8601 "2025-11-02" |> Result.get_ok in
+ Alcotest.(check bool) "2025-11-02 is really a Sunday" true (Date.weekday d = Date.Sun);
+ let ctx = { Precedence.date = d; season = Vocab_of.Ordinary_time; weekday = Date.Sun } in
+ (* An ordinary per-annum Sunday's own candidate, shaped exactly as
+ Temporal_of.temporal builds one (rank Festum, Tabula II.6) --
+ independent of temporal_candidate/ctx_of_date above, which read the
+ office off Temporal_of.temporal directly; this test instead builds it
+ by hand so it does not depend on 2025-11-02 having no competing named
+ temporal office of its own. *)
+ let sunday_candidate =
+ mk ~slug:"of-ordinary-time-sunday" ~rank:Vocab_of.Festum ~origin:Precedence.Temporal ()
+ in
+ let resolution =
+ Precedence.resolve Rite_of.Precedence_of.rules ctx ~temporal:sunday_candidate
+ ~sanctoral:[ all_souls_candidate ]
+ in
+ Alcotest.(check bool) "All Souls, not the Sunday, is observed" true
+ (resolution.Precedence.observed = all_souls_candidate)
+
let suite =
( "precedence-of",
[ Alcotest.test_case "Tabula part I (entries 1-4)" `Quick test_part1;
@@ -455,5 +499,8 @@ let suite =
Alcotest.test_case "transfer_target is always strictly later" `Quick
test_target_is_strictly_later;
Alcotest.test_case "transfer_target lands free of Tabula entries 1-8" `Quick
- test_target_is_free_of_entries_1_to_8 ]
+ test_target_is_free_of_entries_1_to_8;
+ Alcotest.test_case
+ "fix round 2: shipped All Souls beats an ordinary per-annum Sunday (2025-11-02)" `Quick
+ test_all_souls_beats_an_ordinary_sunday ]
@ List.map QCheck_alcotest.to_alcotest [ prop_band_total ] )