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.ml158
1 files changed, 119 insertions, 39 deletions
diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml
index facf3eb..52de989 100644
--- a/test/test_precedence_ef.ml
+++ b/test/test_precedence_ef.ml
@@ -290,7 +290,7 @@ let test_all_souls_yields_to_sunday () =
let rules =
{ P.band = (fun c cd -> PE.band c cd);
disposition = (fun ~winner:_ ~loser:_ -> P.Omit);
- admit = (fun ~observed:_ cs -> cs) }
+ admit = (fun ~observed:_ ~temporal:_ cs -> cs) }
in
let resolution = P.resolve rules day_ctx ~temporal:sunday ~sanctoral:[ all_souls ] in
Alcotest.(check string) "the Sunday is observed, not All Souls"
@@ -812,31 +812,58 @@ let observed_class3 = cand ~rank:V.Class3 "ef-some-class3-day"
let slugs_of admitted =
List.map (fun (c, _) -> S.to_string c.P.cel.Cel.slug) admitted
+(* Real-data shapes for the fix round's own RG16(a)/[admit] interaction
+ (below): a Feast of the Lord (subject Lord, Class2, sanctoral) as
+ [observed], oracle-confirmed real slugs/ranks rather than hand-typed
+ ones, the same coupling-safety reason [of_temporal] rows elsewhere in
+ this file use real data. *)
+let lord_winner =
+ cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
+ "transfiguration-of-our-lord"
+
+(* Pope Sixtus II et al. (6 August, real slug/rank/status from
+ data/ef/sanctoral.sexp): Class3, Commemoration_only, tagged [Ordinary]
+ here directly (as every other [admit_cases] row does, isolating
+ [admit]'s own selection logic from [privilege_of], per this table's own
+ header comment). *)
+let sixtus =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~status:Cel.Commemoration_only
+ ~layer:PE.universal_layer "pope-sixtus-ii-felicissimus-and-agapitus-martyrs"
+
+(* (description, observed, temporal, comms, expected). [temporal] --
+ {!Precedence.rules.admit}'s own new parameter, fix round 1 (RG16(a)
+ task): the day's temporal-cycle candidate, independent of who is
+ [observed]. Every row below except the last two repeats [observed] as
+ [temporal] -- no RG16(a) displacement occurs in those rows (the pattern
+ [PE.admit]'s pre-fix code implicitly, and wrongly, assumed held
+ UNIVERSALLY), so the two values coinciding is the faithful shape, not a
+ simplification that dodges the new parameter. The last two rows are
+ where they genuinely differ -- see their own comment. *)
let admit_cases =
[ (* RG 111 (§4): "I class: none save one privileged." *)
( "I-class day, only an ordinary commemoration due -> none admitted",
- observed_class1,
+ observed_class1, observed_class1,
[ (ordinary_hi, P.Ordinary) ],
[] );
( "I-class day, ordinary + privileged both due -> only the privileged \
one, regardless of the ordinary one's higher dignity",
- observed_class1,
+ observed_class1, observed_class1,
[ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
[ "ef-privileged-lo" ] );
( "I-class day, two privileged due -> only the higher-dignity one (still \
just \"one\")",
- observed_class1,
+ observed_class1, observed_class1,
[ (privileged_lo, P.Privileged); (privileged_hi, P.Privileged) ],
[ "ef-privileged-hi" ] );
(* RG 111: "II-class Sundays: one (dropped if a privileged one is due)." *)
( "II-class Sunday, only an ordinary commemoration due -> it is admitted",
- observed_class2_sunday,
+ observed_class2_sunday, observed_class2_sunday,
[ (ordinary_hi, P.Ordinary) ],
[ "ef-ordinary-hi" ] );
( "II-class Sunday, ordinary (higher dignity) + privileged (lower \
dignity) both due -> the PRIVILEGED one is admitted, the ordinary \
one dropped despite outranking it",
- observed_class2_sunday,
+ observed_class2_sunday, observed_class2_sunday,
[ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
[ "ef-privileged-lo" ] );
(* RG 111(b)'s own rank floor ("scilicet DE FESTO II CLASSIS"), fix
@@ -848,7 +875,7 @@ let admit_cases =
below, which has no such restriction. *)
( "II-class Sunday, sole candidate is an ORDINARY Class3 (not \
\"de festo II classis\") -> admitted nothing, not the best available",
- observed_class2_sunday,
+ observed_class2_sunday, observed_class2_sunday,
[ (ordinary_class3, P.Ordinary) ],
[] );
(* RG 111: "other II class: one" -- no privilege override, the exact
@@ -857,23 +884,55 @@ let admit_cases =
observed day, OPPOSITE winner. *)
( "other II-class day, only an ordinary commemoration due -> it is \
admitted",
- observed_class2_other,
+ observed_class2_other, observed_class2_other,
[ (ordinary_hi, P.Ordinary) ],
[ "ef-ordinary-hi" ] );
( "other II-class day, same ordinary+privileged pair as the Sunday row \
above -> the ORDINARY one wins on pure dignity this time, the \
privileged one dropped",
- observed_class2_other,
+ observed_class2_other, observed_class2_other,
[ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged) ],
[ "ef-ordinary-hi" ] );
(* RG 111: "III-IV class: at most two" -- three candidates due, top two
by dignity admitted, the third (lowest dignity) dropped. *)
( "III-class day, three commemorations due -> the top two by dignity, \
not merely \"two of them\"",
- observed_class3,
+ observed_class3, observed_class3,
[ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged);
(ordinary_lowest, P.Ordinary) ],
- [ "ef-ordinary-hi"; "ef-privileged-lo" ] )
+ [ "ef-ordinary-hi"; "ef-privileged-lo" ] );
+ (* Fix round 1, item 2 (RG16(a) task review): the CRITICAL witness for
+ [~temporal]. RG 16(a)'s own text -- the winning Feast of the Lord
+ holds the Sunday's place "cum omnibus iuribus et privilegiis" -- means
+ the day is STILL a "dominica II classis" for RG 111(b)'s own rank
+ floor, even though [observed] is now the FEAST (Transfiguration, real
+ slug/rank/subject), not the Sunday. [temporal] (a real Sunday
+ candidate, {!an_ordinary_sunday}) is what reveals that; nothing in
+ [observed] does, since its own slug carries no Sunday marker at all.
+ Oracle-confirmed (missalemeum, 2023-08-06, a Sunday):
+ "commemorations": [], Sixtus "displaced". Before this fix
+ [observed_is_sunday] read [observed]'s own slug and got [false] here,
+ wrongly taking the "other II class: one" branch below and admitting
+ Sixtus (Class3) despite RG 111(b)'s rank floor. *)
+ ( "RG16(a) interaction: a Feast of the Lord observed on a day whose \
+ TEMPORAL candidate is a II-class Sunday -> the RG111(b) rank floor \
+ still applies, admits nothing (Sixtus, Class3, has no standing)",
+ lord_winner, an_ordinary_sunday,
+ [ (sixtus, P.Ordinary) ],
+ [] );
+ (* The control, same pair as the row above with [observed] = [temporal]
+ (no displacement -- an ordinary WEEKDAY, not a Sunday): "other II
+ class: one", no rank floor, Sixtus IS admitted. Oracle-confirmed
+ (missalemeum, 2026-08-06, a Thursday): Sixtus in "commemorations".
+ Proves the DISCRIMINATING factor is [temporal]'s own Sunday-ness, not
+ merely "was the winner a Feast of the Lord" -- that alone is true of
+ BOTH rows here, and only one of them excludes Sixtus. *)
+ ( "control: the same Feast of the Lord on an ORDINARY weekday (temporal \
+ = observed, not a Sunday) -> \"other II class: one\", Sixtus IS \
+ admitted",
+ lord_winner, lord_winner,
+ [ (sixtus, P.Ordinary) ],
+ [ "pope-sixtus-ii-felicissimus-and-agapitus-martyrs" ] )
]
(* Order independence (brief: "the admitted set must not depend on input
@@ -886,8 +945,10 @@ let test_admit_order_independent () =
let comms =
[ (ordinary_hi, P.Ordinary); (privileged_lo, P.Privileged); (ordinary_lowest, P.Ordinary) ]
in
- let forward = slugs_of (PE.admit ~observed:observed_class3 comms) in
- let reversed = slugs_of (PE.admit ~observed:observed_class3 (List.rev comms)) in
+ let forward = slugs_of (PE.admit ~observed:observed_class3 ~temporal:observed_class3 comms) in
+ let reversed =
+ slugs_of (PE.admit ~observed:observed_class3 ~temporal:observed_class3 (List.rev comms))
+ in
Alcotest.(check (list string)) "reversed input admits the same candidates"
forward reversed
@@ -1023,25 +1084,34 @@ let test_ii_class_sunday_privileged_witness_admitted_end_to_end () =
(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] AND [PE.disposition] together, not [disposition] in
- isolation as [disposition_cases]'s own rows above test it): a real civil
- date this task's own blast-radius measurement names as a live instance
- of the bug this branch fixes -- 6 August 2028 is a Sunday (independently
- checked with `date -d 2028-08-06 +%A`, the same cross-check discipline
- [test_golden.ml]'s own header requires), Time after Pentecost week 9, and
- the Transfiguration (6 Aug, II class, "IN TRANSFIGURATIONE D. N. I. C.")
- falls on it. Before this fix `colitur day` emitted this Sunday as an
- admitted [+ef-time-after-pentecost-sunday-9] commemoration on that date
- (register §6.0's own reproduction); this proves the full pipeline now
- agrees with the isolated [disposition] rows above: [observed] is the
+ ([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
+ separately): a real civil date this task's own blast-radius measurement
+ names as a live instance of the bug this branch fixes -- 6 August 2028
+ is a Sunday (independently checked with `date -d 2028-08-06 +%A`, the
+ same cross-check discipline [test_golden.ml]'s own header requires),
+ Time after Pentecost week 9, and the Transfiguration (6 Aug, II class,
+ "IN TRANSFIGURATIONE D. N. I. C.") falls on it. Before this fix
+ `colitur day` emitted this Sunday as an admitted
+ [+ef-time-after-pentecost-sunday-9] commemoration on that date (register
+ §6.0's own reproduction).
+
+ Fix round 1 (item 2): a THIRD candidate, Pope Sixtus II et al. (real
+ slug/rank/status, 6 August, unrelated to the Sunday), is now also
+ offered, so this test exercises BOTH fixes at once, the same real shape
+ [test_golden.ml]'s own 2028-08-06 pin does: [observed] is the
Transfiguration ({!band} entry 14 already did this correctly before this
- task), [commemorations] is EMPTY (not merely missing the Sunday from
- [admit]'s cut -- RG 16(a) is a [disposition]-level Omit, before [admit]
- ever runs), and the Sunday appears in [omitted] with
- ["omitted: yielded to a higher day"] ({!Precedence.resolve}'s own Omit
- reason), never ["omitted: admission limit reached"] (that reason would
- mean the Sunday was tagged [Commemorate] and then cut by [admit] -- a
- different, wrong mechanism for the same wrong end state). *)
+ task); the Sunday is [disposition]-level [Omit] (RG 16(a)); Sixtus is
+ [disposition]-level [Commemorate], but [admit] then excludes him too --
+ RG 111(b)'s rank floor, reached only because [admit] reads the day's
+ Sunday-ness off [~temporal] (the [sunday] candidate passed to
+ [P.resolve]), not off [observed] (the Transfiguration, whose own slug
+ carries no Sunday marker). [commemorations] is EMPTY, and BOTH losers
+ land in [omitted] with their own distinct reasons -- the Sunday via
+ [disposition]'s own Omit ("omitted: yielded to a higher day"), Sixtus via
+ [admit]'s cut ("omitted: admission limit reached") -- proving the two
+ fixes operate through genuinely different mechanisms, not the same one
+ coincidentally producing the same string. *)
let test_rg16a_lord_feast_suppresses_sunday_end_to_end () =
let date = mk 2028 8 6 in
let day_ctx = ctx date in
@@ -1050,15 +1120,25 @@ let test_rg16a_lord_feast_suppresses_sunday_end_to_end () =
cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer
"transfiguration-of-our-lord"
in
- let resolution = P.resolve real_rules day_ctx ~temporal:sunday ~sanctoral:[ transfiguration ] in
+ let sixtus =
+ cand ~origin:P.Sanctoral ~rank:V.Class3 ~status:Cel.Commemoration_only ~layer:PE.universal_layer
+ "pope-sixtus-ii-felicissimus-and-agapitus-martyrs"
+ in
+ let resolution =
+ P.resolve real_rules day_ctx ~temporal:sunday ~sanctoral:[ transfiguration; sixtus ]
+ in
Alcotest.(check string) "the Transfiguration is observed, not the Sunday"
"transfiguration-of-our-lord" (S.to_string resolution.P.observed.P.cel.Cel.slug);
- Alcotest.(check int) "no commemorations at all -- RG16(a)'s own \"nulla fit commemoratio\""
+ Alcotest.(check int)
+ "no commemorations at all -- RG16(a)'s own \"nulla fit commemoratio\" AND RG111(b)'s rank floor, both live"
0 (List.length resolution.P.commemorations);
Alcotest.(check (list (pair string string)))
- "the Sunday is omitted with RG16(a)'s own disposition-level reason, not admit's cut"
- [ ("ef-time-after-pentecost-sunday-9", "omitted: yielded to a higher day") ]
- (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted)
+ "both losers omitted, via two DIFFERENT mechanisms: the Sunday at disposition-level (RG16a), Sixtus at \
+ admit's own cut (RG111b)"
+ [ ("ef-time-after-pentecost-sunday-9", "omitted: yielded to a higher day");
+ ("pope-sixtus-ii-felicissimus-and-agapitus-martyrs", "omitted: admission limit reached") ]
+ (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted
+ |> List.sort compare)
(* Completes Task 7's carried fix (RG 91 entry 8, §4): on a real Sunday
landing on 2 November, All Souls does not merely lose (that was Task 7's
@@ -1091,7 +1171,7 @@ let test_all_souls_transfers_end_to_end () =
origin = P.Temporal }
in
let all_souls = cand ~origin:P.Sanctoral ~layer:PE.universal_layer "ef-all-souls" in
- let rules = { P.band = PE.band; disposition = PE.disposition; admit = (fun ~observed:_ cs -> cs) } in
+ let rules = { P.band = PE.band; disposition = PE.disposition; admit = (fun ~observed:_ ~temporal:_ cs -> cs) } in
let resolution = P.resolve rules day_ctx ~temporal:sunday ~sanctoral:[ all_souls ] in
Alcotest.(check (list string)) "All Souls is deferred (transferred), not omitted or commemorated"
[ "ef-all-souls" ]
@@ -1281,10 +1361,10 @@ let suite =
Alcotest.test_case "All Souls transfers end-to-end (resolve, real rules)" `Quick
test_all_souls_transfers_end_to_end ]
@ List.map
- (fun (desc, observed, comms, expect) ->
+ (fun (desc, observed, temporal, comms, expect) ->
Alcotest.test_case desc `Quick (fun () ->
Alcotest.(check (list string)) desc expect
- (slugs_of (PE.admit ~observed comms))))
+ (slugs_of (PE.admit ~observed ~temporal comms))))
admit_cases
@ [ Alcotest.test_case "admit is order-independent (III-class, 3 candidates)" `Quick
test_admit_order_independent;