aboutsummaryrefslogtreecommitdiff
path: root/test/test_precedence_ef.ml
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_precedence_ef.ml')
-rw-r--r--test/test_precedence_ef.ml102
1 files changed, 98 insertions, 4 deletions
diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml
index ed9a933..475ae6e 100644
--- a/test/test_precedence_ef.ml
+++ b/test/test_precedence_ef.ml
@@ -291,10 +291,21 @@ let cases =
cand ~origin:P.Sanctoral ~rank:V.Class3 ~layer:PE.universal_layer "vigil-of-st-lawrence",
260 );
(* Entry 27 -- RG 91 entry 27 (§4): an otherwise-unoccupied IV-class
- Saturday. *)
- ( "27 Office of the BVM on Saturday", off 62,
- cand ~rank:V.Class4 "ef-time-after-pentecost-1-sat",
- 270 );
+ Saturday. ef-bvm-saturday task: sourced from [Temporal_ef.temporal]'s
+ own real output (see [of_temporal], the same review-finding-3
+ discipline entry 18's/21's own rows above use), not a hand-typed
+ slug/rank pair -- this row used to be the one place in this whole
+ suite where [band]'s entry-27 branch was exercised by a value nothing
+ in [Temporal_ef.temporal] could actually produce (the office itself
+ was unbuilt): [band] read [rank = Class4 && weekday = Sat]
+ correctly, but nothing proved [temporal] ever handed it a candidate
+ shaped that way for the RIGHT reason. Now it does: [of_temporal (off
+ 62)] is 6 June 2026, a real otherwise-contested Time-after-Pentecost
+ Saturday (Norbert, Class3, wins the DAY outright in the real
+ pipeline -- irrelevant here, since this row tests [band] on the
+ TEMPORAL CANDIDATE alone, which [Temporal_ef.temporal] builds as the
+ BVM Saturday office regardless of what wins). *)
+ ( "27 Office of the BVM on Saturday (from Temporal_ef.temporal)", off 62, of_temporal (off 62), 270 );
(* Entry 28 -- RG 91 entry 28 (§4): the unqualified IV-class catch-all. *)
("28 IV-class feria", off 65, cand ~rank:V.Class4 "ef-time-after-pentecost-1-tue", 280);
(* Not an RG 91 row at all: a I-class candidate marked as a vigil, which
@@ -1421,6 +1432,81 @@ let test_ii_class_sunday_privileged_witness_admitted_end_to_end () =
[ ("ef-some-saint", "omitted: admission limit reached") ]
(List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted)
+(* RG 91 entry 27 / RG 78-79 (Caput IX, "De sancta Maria in sabbato") reached
+ end-to-end through the REAL pipeline -- this is THE hazard this task's own
+ brief names explicitly: {!PE.band}'s entry-27 branch has been reachable
+ only in isolation (the table-driven row above) since it was written, never
+ through a real [Temporal_ef.temporal] candidate winning an actual day, so
+ this test is checked for whether it exercises entry 27 for the RIGHT
+ reason -- proved by the mutation test recorded in the task report
+ (reverting temporal_ef.ml's own [is_bvm_saturday] branches back to the
+ generic ferial fallback reddens THIS test, not merely the [band]-table
+ row, which would still pass unchanged since it is sourced from real
+ [T.temporal] output either way).
+
+ 1 August 2026, matching the task brief's own worked example against the
+ oracle exactly: a Time-after-Pentecost Saturday, otherwise unoccupied but
+ for Holy Machabees (Commemoration_only, Class3, real data/ef/sanctoral.sexp
+ entry, 1 August) -- the office wins outright (band 270, ahead of Holy
+ Machabees's own [unclassified]) and the Commemoration_only loser still
+ rides along as an ordinary commemoration, the SAME shape the oracle's own
+ row for this date shows ("V Mass of the B. V. M. -- Salve, Sancta Parens",
+ commemorating Holy Machabees). *)
+let test_bvm_saturday_wins_and_commemorates_end_to_end () =
+ let date = mk 2026 8 1 in
+ let day_ctx = ctx date in
+ let bvm_saturday = of_temporal date in
+ let holy_machabees =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~status:Cel.Commemoration_only ~layer:PE.universal_layer
+ "holy-machabees"
+ in
+ let resolution = P.resolve real_rules day_ctx ~temporal:bvm_saturday ~sanctoral:[ holy_machabees ] in
+ Alcotest.(check string) "the BVM Saturday office is observed, not Holy Machabees"
+ "ef-time-after-pentecost-9-saturday" (S.to_string resolution.P.observed.P.cel.Cel.slug);
+ Alcotest.(check string) "observed rank is class-4, unconditional" "class-4"
+ (V.rank_to_string resolution.P.observed.P.cel.Cel.rank);
+ Alcotest.(check string) "observed colour is white, overriding the season's own green" "white"
+ (Col.to_string resolution.P.observed.P.cel.Cel.colour);
+ Alcotest.(check bool) "observed subject is Bvm" true (resolution.P.observed.P.cel.Cel.subject = Sub.Bvm);
+ Alcotest.(check (list (pair string string))) "Holy Machabees still rides along as an ordinary commemoration"
+ [ ("holy-machabees", "Ordinary") ]
+ (List.map
+ (fun (c, p) -> (S.to_string c.P.cel.Cel.slug, match p with P.Privileged -> "Privileged" | P.Ordinary -> "Ordinary"))
+ resolution.P.commemorations);
+ Alcotest.(check int) "nothing omitted" 0 (List.length resolution.P.omitted)
+
+(* The other half of the SAME hazard: a real Saturday where RG 78's own
+ protasis is FALSE (a genuine sanctoral feast wins the day outright), so
+ the BVM-Saturday-shaped temporal candidate must lose, and be OMITTED under
+ RG 26 (a temporal Class4 non-vigil loser is never commemorated) exactly
+ like the plain ferial candidate it replaces always was -- proving [band]/
+ [disposition] need no special case for this office at all, the design
+ claim the task report makes explicitly. 12 September 2026 is a Saturday
+ where `most-holy-name-of-mary` (data/ef/adjustments.sexp's own [Set_subject
+ Bvm] entry, Class3 Feast) wins outright -- ALSO tagged [subject = Bvm],
+ the one live data witness that could in principle confuse a
+ subject-keyed disposition rule with RG 26's own rank-keyed one: this test
+ proves they do NOT collide (RG 26 fires first, unconditionally, on the
+ loser's own [rank = Class4], never reaching a subject comparison at all). *)
+let test_bvm_saturday_loses_to_a_real_feast_end_to_end () =
+ let date = mk 2026 9 12 in
+ let day_ctx = ctx date in
+ let bvm_saturday = of_temporal date in
+ let name_of_mary =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~subject:Sub.Bvm ~layer:PE.universal_layer
+ "most-holy-name-of-mary"
+ in
+ let resolution = P.resolve real_rules day_ctx ~temporal:bvm_saturday ~sanctoral:[ name_of_mary ] in
+ Alcotest.(check string) "Most Holy Name of Mary is observed, not the BVM Saturday office"
+ "most-holy-name-of-mary" (S.to_string resolution.P.observed.P.cel.Cel.slug);
+ Alcotest.(check (list string)) "nothing is commemorated" []
+ (List.map (fun (c, _) -> S.to_string c.P.cel.Cel.slug) resolution.P.commemorations);
+ Alcotest.(check (list (pair string string)))
+ "the BVM-Saturday-shaped temporal candidate is omitted under RG26, not commemorated -- no Bvm-vs-Bvm \
+ confusion with RG112(a)-style subject logic"
+ [ ("ef-time-after-pentecost-15-saturday", "omitted: yielded to a higher day") ]
+ (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted)
+
(* RG 16(a) (register §6.0) reached end-to-end through the REAL pipeline
([PE.band], [PE.disposition] AND [PE.admit] together, not any one of
them in isolation as this file's own hand-tagged rows test them
@@ -1895,6 +1981,14 @@ let suite =
"II-class Sunday override: RG109(b) witness admitted over an ordinary saint, end-to-end"
`Quick test_ii_class_sunday_privileged_witness_admitted_end_to_end;
Alcotest.test_case
+ "RG91 e27/RG78: the BVM Saturday office wins and commemorates Holy Machabees, end-to-end \
+ (2026-08-01)"
+ `Quick test_bvm_saturday_wins_and_commemorates_end_to_end;
+ Alcotest.test_case
+ "RG91 e27/RG78/RG26: the BVM Saturday office loses to a real feast and is omitted, end-to-end \
+ (2026-09-12)"
+ `Quick test_bvm_saturday_loses_to_a_real_feast_end_to_end;
+ Alcotest.test_case
"RG16(a): a Feast of the Lord suppresses the Sunday's own commemoration entirely, \
end-to-end (2028-08-06)"
`Quick test_rg16a_lord_feast_suppresses_sunday_end_to_end;