diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-27 00:38:40 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-27 00:38:40 +0200 |
| commit | e26d7da141f7985fadc53d8399a69dbaa1153c94 (patch) | |
| tree | 38737b17dbf71faf9c357d8d2098e8f3f42aab0b /test | |
| parent | 6e62e499aed1c5a31a18bcf5e9eaa7f2b0c4ff2e (diff) | |
| download | colitur-e26d7da141f7985fadc53d8399a69dbaa1153c94.tar.gz colitur-e26d7da141f7985fadc53d8399a69dbaa1153c94.zip | |
fix(of): correct the Annunciation's transfer_target slug, dead Rule 1
precedence_of.ml's transfer_target Rule 1 (Normae n. 60's fixed Easter+8
destination for the Annunciation falling in Holy Week) keyed off
"of-annunciation", a placeholder that never matched the real shipped
entry's own slug ("annunciation-of-the-lord",
data/of/calendar-2002.sexp). Rule 1 was therefore dead code: it could
only ever fire against test_precedence_of.ml's own synthetic candidate,
which happened to carry the identical placeholder.
Output was nonetheless correct on shipped data (latent, not live): Rule
3's general forward search structurally converges on the same Easter+8
target, because the Easter Octave occupies exactly Easter+1..+7 at band
20 and the 3-9 April window carries only memorials on the universal
calendar. The exposure is an overlay placing a proper solemnity (band
40) or proper feast (band 80) anywhere in 3-9 April, where Rule 3 would
diverge from Rule 1's fixed destination and Rule 1 would silently fail
to override it.
Fixed the slug, and updated the existing Rule-1 tests' own synthetic
candidate to the real slug so they keep exercising Rule 1 rather than
Rule 3's coincidental agreement. Added a test that tells the two rules
apart rather than only checking the output they happen to agree on: it
rigs the occupant callback to occupy Easter+8 with a synthetic
Tabula-entry-3 candidate, confirms (via a control case using a
different solemnity) that the rig genuinely forces Rule 3's search past
that date, then shows the real shipped Annunciation still lands on
Easter+8 despite the block -- only explicable by Rule 1 firing, not by
Rule 3 happening to agree.
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_precedence_of.ml | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/test/test_precedence_of.ml b/test/test_precedence_of.ml index e2e8540..01ba92c 100644 --- a/test/test_precedence_of.ml +++ b/test/test_precedence_of.ml @@ -375,8 +375,18 @@ let test_vigil_feast_is_always_none () = rather than a hand-made fiction. *) let occupant d = (Rite_of.Temporal_of.temporal d).Temporal.office +(* W6 (of-known-wrongs, 2026-08-26): this used to carry the placeholder slug + "of-annunciation" -- the very bug precedence_of.ml's own [annunciation_ + slug] carried, so this synthetic candidate coincidentally matched the + bug rather than testing against it. Now the REAL shipped slug + (data/of/calendar-2002.sexp: "annunciation-of-the-lord"), so the tests + below that use it (Rule 1/n. 60) actually exercise Rule 1 against the + slug production code now checks -- see + [test_annunciation_rule1_actually_fires] below for the test that tells + "Rule 1 fired" apart from "Rule 3 happened to agree", which none of + these did before it. *) let annunciation = - mk ~subject:Subject.Lord ~slug:"of-annunciation" ~rank:Vocab_of.Sollemnitas + mk ~subject:Subject.Lord ~slug:"annunciation-of-the-lord" ~rank:Vocab_of.Sollemnitas ~origin:Precedence.Sanctoral () let iso s = Date.of_iso8601 s |> Result.get_ok @@ -524,6 +534,62 @@ let test_all_souls_beats_an_ordinary_sunday () = Alcotest.(check bool) "All Souls, not the Sunday, is observed" true (resolution.Precedence.observed = all_souls_candidate) +(* W6 (of-known-wrongs, 2026-08-26). [annunciation_slug] used to read + "of-annunciation", a placeholder that never matched the real shipped + entry -- Rule 1 (Normae n. 60's fixed Easter+8 destination) was DEAD + CODE, only ever exercised by this file's own synthetic candidate, which + happened to carry the identical placeholder. Every test above this one + proves nothing about whether Rule 1 fires against real data: they all + land on Easter+8, but Rule 3's general forward search converges on the + IDENTICAL date whenever the 3-9 April window is empty of anything at + Tabula entries 1-8 (true on the shipped universal calendar), so the + output is the same whichever rule actually answers. + + This test tells the two apart. It loads the REAL shipped + "annunciation-of-the-lord" entry (not a synthetic reconstruction, the + same discipline [test_all_souls_beats_an_ordinary_sunday] above uses) + and RIGS the [occupant] callback to occupy Easter+8 itself with a + synthetic Tabula-entry-3 candidate (band 30, well inside entries 1-8). + Rule 3's search, if it were what answered, would have to step past that + occupied day onto Easter+9 -- confirmed by a CONTROL case, a different + solemnity on the same origin and the same rig, which can only reach + Rule 3 (it is neither the Annunciation nor St Joseph on Palm Sunday) and + does indeed land on Easter+9. Rule 1's own fixed computation never + consults [occupant] at all, so the rig has no effect on it: the real + Annunciation still landing on Easter+8 DESPITE the block is something + only Rule 1 firing can explain. *) +let test_annunciation_rule1_actually_fires () = + 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 annunciation_real = + match Colitur_kernel.Layer.find l (Slug.of_string_exn "annunciation-of-the-lord") with + | Some e -> { Precedence.cel = e.Colitur_kernel.Layer.cel; origin = Precedence.Sanctoral } + | None -> Alcotest.fail "\"annunciation-of-the-lord\" not found in the shipped calendar" + in + (* 2027: Easter 28 March, so 25 March is Holy Thursday -- inside Holy + Week -- and Easter+8 is 5 April, the date this rig occupies. *) + let origin = iso "2027-03-25" in + let blocked = iso "2027-04-05" in + let rigged d = + if Date.compare d blocked = 0 then + mk_cel ~slug:"of-w6-synthetic-blocker" ~rank:Vocab_of.Sollemnitas () + else occupant d + in + let control = + mk ~slug:"of-w6-control" ~rank:Vocab_of.Sollemnitas ~origin:Precedence.Sanctoral () in + let control_target = Rite_of.Precedence_of.transfer_target control origin rigged in + Alcotest.(check string) + "control (not the Annunciation, not St Joseph): the rig really blocks -- pushed past 5 April to 6 April" + "2027-04-06" (Date.to_iso8601 control_target); + let target = Rite_of.Precedence_of.transfer_target annunciation_real origin rigged in + Alcotest.(check string) + "the REAL shipped Annunciation still lands on Easter+8 despite the block -- Rule 1, not Rule 3, fired" + "2027-04-05" (Date.to_iso8601 target) + (* W3 (of-known-wrongs, 2026-08-26). Mary, Mother of the Church (Easter+50) and a fixed obligatory memorial (e.g. Anthony of Padua, 13 June) both used to band at Tabula III.10 (100) whenever they coincide -- a tie @@ -605,6 +671,9 @@ let suite = "fix round 2: shipped All Souls beats an ordinary per-annum Sunday (2025-11-02)" `Quick test_all_souls_beats_an_ordinary_sunday; Alcotest.test_case + "W6: the REAL shipped Annunciation slug makes Rule 1 fire (not merely agree with Rule 3)" `Quick + test_annunciation_rule1_actually_fires; + Alcotest.test_case "W3: a movable BVM obligatory memorial beats a fixed one, per the CDWDS's 24 March 2018 \ Notification" `Quick test_movable_bvm_memorial_beats_a_fixed_one ] |
