aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/cli.t13
-rw-r--r--test/test_precedence_ef.ml74
2 files changed, 72 insertions, 15 deletions
diff --git a/test/cli.t b/test/cli.t
index 77968e6..5a646a4 100644
--- a/test/cli.t
+++ b/test/cli.t
@@ -101,6 +101,19 @@ Sunday: 2 Nov 2026 is a Monday (1 Jan 2026 is a Thursday, same day-of-year
(week 23: Pentecost 2026 is 24 May (colitur easter 2026); 24 May - 2 Nov is
162 days, floor_div(162, 7) = 23 -- same formula, same independent check.)
+RG 96's Annunciation exception (25 March) is CONDITIONAL, not unconditional
+-- fix round 1, coordinator review, register corrected 2026-08-12. In 2057,
+25 March is Lent III Sunday (I class, impedes it); 26 March is an ordinary
+Lent feria (III class, well before Easter, 22 April 2057), so the GENERAL
+RG 96 target -- not the Monday after Low Sunday -- is what governs, since
+the general walk never crosses Easter. Before this fix the unconditional
+reading sent it to 30 April (Easter + 8) instead:
+
+ $ colitur day 2057 | grep '^2057-03-26 '
+ 2057-03-26 monday lent 3 annunciation-of-the-blessed-virgin-mary class-1 white +ef-lent-3-monday
+ $ colitur day 2057 | grep -c 'annunciation-of-the-blessed-virgin-mary'
+ 1
+
A year outside the supported domain is rejected (exit 2):
$ colitur day 1000
diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml
index 0973a93..aa98686 100644
--- a/test/test_precedence_ef.ml
+++ b/test/test_precedence_ef.ml
@@ -844,36 +844,76 @@ let test_transfer_target_general_multi_step_search () =
Alcotest.(check string) "lands on the first day past the blocked run"
"2026-01-13" (D.to_iso8601 target)
-(* RG 96's Annunciation exception: starts the search at the Monday after Low
- Sunday, NOT [origin + 1] -- occupant is unconditionally free, so a
- general-path implementation would return [origin + 1] (26 March), a date
- this test explicitly rules out as well as pinning the real expected one,
- so the assertion genuinely discriminates the two starting points rather
- than merely checking "some date after origin". *)
+(* Coordinator review (fix round 1): RG 96 Attamen (a) (register-transcribed,
+ primary-source-verified) makes the Annunciation exception CONDITIONAL on
+ the general RG 96 walk carrying the feast past Easter Sunday -- NOT
+ unconditional as the first transcription had it. The occupant here blocks
+ every day from [origin + 1] through the day after Easter (26 March - 6
+ April 2026 inclusive), so the GENERAL target itself would land at 7
+ April -- after Easter (5 April) -- which is exactly the trigger
+ condition, not merely "the Annunciation is impeded at all". *)
let test_transfer_target_annunciation_starts_at_monday_after_low_sunday () =
let origin = mk 2026 3 25 in
- let occupant = occupant_blocking_on [] in
+ let easter_2026 = Comp.gregorian_easter 2026 in
+ let blocked_through_day_after_easter =
+ let rec range a b = if D.compare a b > 0 then [] else a :: range (D.add_days a 1) b in
+ range (D.add_days origin 1) (D.add_days easter_2026 1)
+ in
+ let occupant = occupant_blocking_on blocked_through_day_after_easter in
let c = cand ~origin:P.Sanctoral ~layer:PE.universal_layer PE.annunciation_slug in
let target = PE.transfer_target c origin occupant in
- let monday_after_low_sunday = D.add_days (Comp.gregorian_easter 2026) 8 in
- Alcotest.(check string) "lands on the Monday after Low Sunday (Easter + 8)"
+ let monday_after_low_sunday = D.add_days easter_2026 8 in
+ Alcotest.(check string) "lands on the Monday after Low Sunday (Easter + 8), the general \
+ walk having crossed Easter itself"
(D.to_iso8601 monday_after_low_sunday) (D.to_iso8601 target);
- Alcotest.(check bool) "NOT the general path's origin + 1 (discriminates the branch)" true
- (D.compare target (D.add_days origin 1) <> 0)
+ Alcotest.(check bool) "NOT the general target (2 days after Easter, discriminates the branch)"
+ true
+ (D.compare target (D.add_days easter_2026 2) <> 0)
(* RG 96's own qualifier on the exception -- "searching onward from there
only if that day is itself blocked" (rite.mli) -- is [search_from]'s
- ORDINARY behaviour, not a second mechanism: block the Monday after Low
- Sunday itself and confirm the search continues exactly one more day. *)
+ ORDINARY behaviour, not a second mechanism: same blocked run as above
+ (forcing the general target past Easter, so the exception fires), PLUS
+ the Monday after Low Sunday itself blocked, confirming the search
+ continues exactly one more day from there. *)
let test_transfer_target_annunciation_searches_onward_if_blocked () =
let origin = mk 2026 3 25 in
- let monday_after_low_sunday = D.add_days (Comp.gregorian_easter 2026) 8 in
- let occupant = occupant_blocking_on [ monday_after_low_sunday ] in
+ let easter_2026 = Comp.gregorian_easter 2026 in
+ let monday_after_low_sunday = D.add_days easter_2026 8 in
+ let blocked =
+ let rec range a b = if D.compare a b > 0 then [] else a :: range (D.add_days a 1) b in
+ range (D.add_days origin 1) (D.add_days easter_2026 1) @ [ monday_after_low_sunday ]
+ in
+ let occupant = occupant_blocking_on blocked in
let c = cand ~origin:P.Sanctoral ~layer:PE.universal_layer PE.annunciation_slug in
let target = PE.transfer_target c origin occupant in
Alcotest.(check string) "searches onward one more day when that Monday is itself blocked"
(D.to_iso8601 (D.add_days monday_after_low_sunday 1)) (D.to_iso8601 target)
+(* THE REGRESSION PIN (coordinator review): the bug an unconditional
+ exception produced. 25 March 2057 is Lent III Sunday (I class, RG 91
+ entry 6), impeding the Annunciation; 26 March 2057 is an ordinary Lent
+ feria (III class, well before Easter, 22 April 2057) -- the general RG
+ 96 target. The general target does NOT fall after Easter, so the
+ exception must NOT fire: the Annunciation lands on 26 March, not 13
+ April (Easter + 8), which is what the unconditional reading produced
+ (verified by reverting the fix and re-running this exact test -- see the
+ task report's mutation record). Uses the REAL [Temporal_ef.temporal] as
+ [occupant] (not a synthetic stand-in), the same coupling-safety
+ convention [of_temporal]'s callers use elsewhere in this file, so this
+ is also effectively an end-to-end check of the real 2057 calendar
+ shape, not just the search's own logic in isolation. *)
+let test_transfer_target_annunciation_not_overridden_when_general_target_precedes_easter () =
+ let origin = mk 2057 3 25 in
+ Alcotest.(check string) "25 March 2057 is a Sunday (Lent III)" "sunday"
+ (D.weekday_to_string (D.weekday origin));
+ let occupant d = (T.temporal d).Colitur_kernel.Temporal.office in
+ let c = cand ~origin:P.Sanctoral ~layer:PE.universal_layer PE.annunciation_slug in
+ let target = PE.transfer_target c origin occupant in
+ Alcotest.(check string) "lands on 26 March 2057 (the general RG96 target), NOT the \
+ Annunciation exception's Monday after Low Sunday"
+ "2057-03-26" (D.to_iso8601 target)
+
(* rite.mli's own obligations on [transfer_target] (Task 11 brief): the call
must TERMINATE and its result must be STRICTLY AFTER [origin], even for a
rite/data shape this function cannot have anticipated -- an occupant that
@@ -974,6 +1014,10 @@ let suite =
Alcotest.test_case
"transfer_target: Annunciation exception searches onward if that Monday is blocked" `Quick
test_transfer_target_annunciation_searches_onward_if_blocked;
+ Alcotest.test_case
+ "transfer_target: Annunciation NOT overridden when the general target precedes Easter \
+ (2057 regression)"
+ `Quick test_transfer_target_annunciation_not_overridden_when_general_target_precedes_easter;
Alcotest.test_case "transfer_target: terminates and stays forward under a pathological occupant"
`Quick test_transfer_target_terminates_under_pathological_occupant;
Alcotest.test_case "transfer_target: does not raise probing past the domain ceiling" `Quick