diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_calendar.ml | 2 | ||||
| -rw-r--r-- | test/test_differential.ml | 23 | ||||
| -rw-r--r-- | test/test_golden.ml | 95 | ||||
| -rw-r--r-- | test/test_precedence.ml | 2 | ||||
| -rw-r--r-- | test/test_precedence_ef.ml | 158 | ||||
| -rw-r--r-- | test/test_rite_ef.ml | 45 | ||||
| -rw-r--r-- | test/test_validate.ml | 12 |
7 files changed, 228 insertions, 109 deletions
diff --git a/test/test_calendar.ml b/test/test_calendar.ml index 505994e..8770017 100644 --- a/test/test_calendar.ml +++ b/test/test_calendar.ml @@ -82,7 +82,7 @@ module Fixture = struct test below a genuine Precedence-native omission (distinct from a deferred one) to exercise. *) let rules : (season, rank) P.rules = - { P.band; disposition; admit = (fun ~observed:_ cs -> List.filteri (fun i _ -> i < 1) cs) } + { P.band; disposition; admit = (fun ~observed:_ ~temporal:_ cs -> List.filteri (fun i _ -> i < 1) cs) } (* RG 96, generic form: search forward from the day after [origin] for the first day whose occupant is not "blocking" -- in this synthetic diff --git a/test/test_differential.ml b/test/test_differential.ml index aa75737..e12cd9a 100644 --- a/test/test_differential.ml +++ b/test/test_differential.ml @@ -450,19 +450,16 @@ let layer_c_reason (l : row) (c : row) diffs = && subset diffs [ Slug_f; Rank; Colour_f ] then Some "C10" else if String.equal c.slug "ef-passiontide-2-thursday" && diffs = [ Colour_f ] then Some "C11" - (* RG16(a) task (register §6.0 + the sanctoral subject audit, this task's - own report): 2 February on a Sunday. colitur now observes the Sunday - (data/ef/adjustments.sexp retags the Purification `Bvm`, so it no - longer bands at RG 91 entry 14 -- only a Feast of the LORD does); the - Purification survives as its own commemoration, matching the register's - ruling, just not as [c]'s OBSERVED slug here. lectio still tags it - `class = lord` (unretagged upstream) and so still observes it outright. - Matched on [l.slug] (lectio's side), the only side that can show this - literal now -- colitur's own [c.slug] is whichever Sunday family the - date falls in (time-after-epiphany or Septuagesima), not one fixed - literal, unlike [c7]/[c11]'s single-slug tests above. *) - else if String.equal l.slug "purification-of-the-blessed-virgin-mary" && subset diffs [ Slug_f; Colour_f ] - then Some "C12" + (* RG16(a) task, fix round 1 (CRITICAL finding): a C12 entry briefly lived + here, allow-listing 2 February on a Sunday against lectio, when + `data/ef/adjustments.sexp` retagged the Purification `Bvm`. REVERTED -- + the user has ruled: follow the oracle (register §6.0 has the full + account). The Purification is `Lord` again, colitur observes it + outright on those six 2-February Sundays, matching lectio's own + `class = lord` exactly -- no divergence to allow-list. Left + unimplemented here deliberately, not merely absent by oversight: this + comment is the record that C12 existed and was removed, should a + future reader wonder why the numbering skips it. *) else None (* ---------------------------------------------------------------------- *) diff --git a/test/test_golden.ml b/test/test_golden.ml index 85a129b..fb3cff4 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -501,16 +501,38 @@ let test_ii_class_sunday_admits_only_ii_class_commemoration () = of the bug this pin closes -- before this fix `colitur day` admitted "+ef-time-after-pentecost-sunday-9" here. + CORRECTED, fix round 1 (IMPORTANT finding, item 2): this pin used to + expect Pope Sixtus II et al. (6 August's own unrelated Class3 saint, + Commemoration_only) admitted as an ordinary commemoration in the freed + slot -- promoted from `colitur day`'s own actual output without + consulting either the primary text or the oracle first (the exact + vacuous-pin flavour the review caught, and this file's own header warns + against). Re-derived properly this time: + - PRIMARY TEXT: RG 16(a) itself says the winning Feast of the Lord holds + the Sunday's place cum omnibus iuribus et privilegiis -- WITH ALL the + Sunday's own rights and privileges. RG 111(b) is one of those: in + dominicis II classis, una tantum admittitur commemoratio, SCILICET DE + FESTO II CLASSIS -- a Sunday's own slot is reserved for a Class2 + candidate specifically. The day is still a dominica II classis for + this purpose even though the Transfiguration, not the Sunday, is + [observed] -- so Sixtus (Class3) has no standing for the slot at all, + the same as on any other II-class Sunday (contrast + [test_ii_class_sunday_admits_only_ii_class_commemoration] above, + romanus, Class3, excluded the identical way on an ORDINARY II-class + Sunday). + - ORACLE, independently fetched (missalemeum's own /api/v5/calendar + JSON, not the small-model webpage summary, which proved unreliable for + this exact question): 2023-08-06 (a Sunday) -- title Transfiguration of + Our Lord, commemorations empty, displaced Pope Sixtus II, Felicissimus + and Agapitus, Martyrs -- Sixtus displaced, not commemorated. Control, + 2026-08-06 (a Thursday, no Sunday collision) -- Sixtus present in + commemorations. Being a Sunday is exactly what excludes him. + Deliberately NOT a bare "comms=[]" pin (this project's own catalogued vacuity flavour: a count/emptiness assertion that would pass even if nothing had ever been offered): [omitted_has] first proves the Sunday really WAS a candidate that reached [disposition] and was actively - excluded, not merely never constructed. And the Sunday is not the day's - ONLY loser -- Pope Sixtus II, Felicissimus and Agapitus (Martyrs, - Commemoration_only, III class, also fixed 6 August, unrelated to the - Sunday) still receive their own ORDINARY commemoration exactly as RG - 111(c)/(d) require: proof that RG 16(a) suppresses the SUNDAY - specifically, not "every commemoration due that day". *) + excluded, not merely never constructed. *) let test_rg16a_lord_feast_no_sunday_commemoration_2028 () = let d = fetch 2028 8 6 in Alcotest.(check bool) @@ -518,35 +540,45 @@ let test_rg16a_lord_feast_no_sunday_commemoration_2028 () = true (omitted_has d "ef-time-after-pentecost-sunday-9"); Alcotest.(check string) - "2028-08-06: the Transfiguration observed; the Sunday has NO commemoration (RG16a); an UNRELATED III-class \ - saint the same day still gets its own ordinary one" + "2028-08-06: the Transfiguration observed; NO commemoration at all -- RG16(a)'s own \"cum omnibus iuribus \ + et privilegiis\" keeps the day a dominica II classis for RG111(b), so Sixtus (Class3) has no standing \ + either, oracle-confirmed" "2028-08-06 sunday season=time-after-pentecost week=9 slug=transfiguration-of-our-lord rank=class-2 \ - colour=white comms=[pope-sixtus-ii-felicissimus-and-agapitus-martyrs:ordinary] in=- out=[]" + colour=white comms=[] in=- out=[]" (describe d) -(* 2025-02-02: the other direction, and the change that made this task's - two halves inseparable (this task's own report). The Purification (2 - Feb, calendarium "IN PURIFICATIONE B. MARIAE VIRG.") is a feast of the - BLESSED VIRGIN, not of the Lord -- data/ef/adjustments.sexp retags it - [Bvm] (the sanctoral audit, this task's report), so it no longer bands - at RG 91 entry 14 and no longer outranks an occurring II-class Sunday - (entry 16 > entry 15). `date -d 2025-02-02 +%A` = Sunday, independently - confirmed. Register §6.0's own text: "Applying RG 16(a) to today's - [pre-fix] data would then also suppress the Sunday's commemoration - there" -- exactly the wrong outcome the data fix (not RG 16(a) itself) - prevents: with the Purification correctly Bvm, RG 16(a)'s own winner-side - [subject = Lord] conjunct never matches here, so the Sunday is simply the - observed day and the Purification survives as its ordinary commemoration - (RG 109/RG 111(b): a plain II-class candidate on a II-class Sunday, no - privileged rival due). *) +(* 2025-02-02, the other real instance of the SAME pattern -- not a + contrasting second direction, per this task's fix round 1 (CRITICAL + finding, item 1, reverted; see register §6.0 for the full account). + + The Purification (2 Feb, calendarium "IN PURIFICATIONE B. MARIAE VIRG.") + stays [subject = Lord] -- the user has ruled: follow the oracle. + missalemeum treats it exactly as RG 16(a)'s own "festum Domini" case + (independently fetched, `/api/v5/calendar` JSON): 2020-02-02 (a Sunday) + -- `{"title":"Purification of the Blessed Virgin Mary","tags":["IV + Sunday after Epiphany"],...,"commemorations":[],"displaced":[]}` -- the + Sunday named only as a TAG (the underlying temporal placement), not + commemorated at all; matches 2014-02-02 exactly. Contrast, the SAME + oracle on an ordinary Marian feast (2019-09-08, the Nativity of the + BVM): `{"title":"XIII Sunday after Pentecost",...,"commemorations": + [{"title":"Nativity of the Blessed Virgin Mary",...}],...}` -- the + Sunday observed, the feast merely commemorated, the OPPOSITE pattern -- + proving missalemeum does not treat every Marian feast this way, only the + Purification specifically. `date -d 2025-02-02 +%A` = Sunday, + independently confirmed. + + Unlike 2028-08-06, no second sanctoral candidate exists on 2 February + (data/ef/sanctoral.sexp has exactly one 2 February entry) -- a genuinely + clean "comms=[]" case, complementing the pair above rather than + duplicating it. *) let test_purification_on_a_sunday_2025 () = check ~msg: - "2025-02-02: the Sunday observed (Purification retagged Bvm, no longer a Feast of the Lord); the \ - Purification survives as an ordinary commemoration, not suppressed" + "2025-02-02: the Purification observed (subject Lord, unretagged -- the oracle's own treatment); NO \ + commemoration of the Sunday, oracle-confirmed" 2025 2 2 - "2025-02-02 sunday season=time-after-epiphany week=4 slug=ef-time-after-epiphany-sunday-4 rank=class-2 \ - colour=green comms=[purification-of-the-blessed-virgin-mary:ordinary] in=- out=[]" + "2025-02-02 sunday season=time-after-epiphany week=4 slug=purification-of-the-blessed-virgin-mary \ + rank=class-2 colour=white comms=[] in=- out=[]" let suite = ( "golden pins (known-tricky years)", @@ -574,10 +606,11 @@ let suite = Alcotest.test_case "IV-class ferias never commemorated (2026)" `Quick test_iv_class_ferias_never_commemorated; Alcotest.test_case "RG111(b): a II-class Sunday admits only a de-festo-II-classis commemoration (2009, 2026)" `Quick test_ii_class_sunday_admits_only_ii_class_commemoration; - Alcotest.test_case "RG16(a): a Feast of the Lord leaves the impeded Sunday with no commemoration (2028-08-06)" + Alcotest.test_case + "RG16(a): a Feast of the Lord leaves the impeded Sunday with NO commemoration at all, not even an \ + unrelated saint's own (2028-08-06, rubric + oracle)" `Quick test_rg16a_lord_feast_no_sunday_commemoration_2028; Alcotest.test_case - "RG16(a) does not fire for the (corrected) Purification: the Sunday observed, the Purification \ - commemorated (2025-02-02)" + "RG16(a), the Purification (oracle-ruled): observed outright, the Sunday not commemorated (2025-02-02)" `Quick test_purification_on_a_sunday_2025 ] ) diff --git a/test/test_precedence.ml b/test/test_precedence.ml index 369c490..ff75baa 100644 --- a/test/test_precedence.ml +++ b/test/test_precedence.ml @@ -26,7 +26,7 @@ let rules = | Cel.Feast -> (match loser.P.cel.Cel.rank with | Hi -> P.Transfer | Lo -> P.Commemorate P.Ordinary)); - admit = (fun ~observed:_ cs -> List.filteri (fun i _ -> i < 2) cs) } + admit = (fun ~observed:_ ~temporal:_ cs -> List.filteri (fun i _ -> i < 2) cs) } let slug_of c = S.to_string c.P.cel.Cel.slug 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; diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml index ad9057b..6fcb25d 100644 --- a/test/test_rite_ef.ml +++ b/test/test_rite_ef.ml @@ -88,22 +88,30 @@ let test_vigil_of_christmas_suppressed () = appears_anywhere (* RG16(a) task (register §6.0 + the sanctoral subject audit, this task's - own report): data/ef/sanctoral.sexp is left untouched (still a faithful - mirror of lectio, subject `Lord` for both entries below -- see - test_sanctoral_ef.ml's own "explicit class = lord" spot-check, which - loads that file WITHOUT applying this overlay and still passes); the - correction lives entirely in data/ef/adjustments.sexp's two [Edit] - directives, the same mechanism [test_vigil_of_christmas_suppressed] - above already proves for a sibling bootstrap defect. This is the ONE - test in the suite that observes the two retags actually take effect - through the real pipeline -- without it, a typo in either directive's - slug (silently a no-op diagnostic, not a hard failure -- Overlay.apply's - own contract) or a reverted adjustments.sexp would leave every other - test green (2 February isn't a Sunday in any golden-pinned year, and - [test_sanctoral_ef.ml] deliberately never applies the overlay). Also - re-verifies the four entries the audit confirmed correct and left - untouched, so a future accidental retag of one of THEM would be caught - here too, not just the two that changed. *) + own report). data/ef/sanctoral.sexp is left untouched (still a faithful + mirror of lectio, subject `Lord` for every entry below except + `most-holy-name-of-mary` -- see test_sanctoral_ef.ml's own "explicit + class = lord" spot-check, which loads that file WITHOUT applying this + overlay and still passes); the one real correction lives entirely in + data/ef/adjustments.sexp's single remaining [Edit] directive, the same + mechanism [test_vigil_of_christmas_suppressed] above already proves for + a sibling bootstrap defect. + + CORRECTED, fix round 1 (CRITICAL finding, item 1): this test used to + also assert `purification-of-the-blessed-virgin-mary` was retagged + `Bvm`. REVERTED -- the user has ruled: follow the oracle (register §6.0 + has the full account, both the calendarium argument for `Bvm` and the + oracle evidence against it). The Purification is `Lord` again, one of + FIVE untouched entries this test now re-verifies, not four. + + This is the ONE test in the suite that observes the one live retag + actually takes effect through the real pipeline -- without it, a typo in + the directive's slug (silently a no-op diagnostic, not a hard failure -- + Overlay.apply's own contract) or a reverted adjustments.sexp would leave + every other test green ([test_sanctoral_ef.ml] deliberately never + applies the overlay). Also re-verifies the five entries the audit + confirmed correct and left untouched, so a future accidental retag of + one of THEM would be caught here too, not just the one that changed. *) let test_rg16a_subject_retag_in_effect () = let layer = real_layer () in let subject_of slug = @@ -111,10 +119,11 @@ let test_rg16a_subject_retag_in_effect () = | Some e -> e.Layer.cel.Cel.subject | None -> Alcotest.failf "slug %s not found in the overlaid layer" slug in - Alcotest.(check bool) "Purification retagged Bvm (calendarium: \"B. MARIAE VIRG.\")" true - (subject_of "purification-of-the-blessed-virgin-mary" = Subject.Bvm); Alcotest.(check bool) "Most Holy Name of Mary retagged Bvm (calendarium: \"Nominis Mariae\")" true (subject_of "most-holy-name-of-mary" = Subject.Bvm); + Alcotest.(check bool) + "Purification stays Lord (reverted, fix round 1 -- the user's ruling: follow the oracle)" true + (subject_of "purification-of-the-blessed-virgin-mary" = Subject.Lord); Alcotest.(check bool) "Precious Blood stays Lord (calendarium: \"D. N. I. C.\") -- audit, not touched" true (subject_of "precious-blood-of-our-lord-jesus-christ" = Subject.Lord); Alcotest.(check bool) "Transfiguration stays Lord (calendarium: \"D. N. I. C.\") -- audit, not touched" true diff --git a/test/test_validate.ml b/test/test_validate.ml index 89053c1..42c58f5 100644 --- a/test/test_validate.ml +++ b/test/test_validate.ml @@ -225,7 +225,7 @@ module Synthetic = struct let rules : (season, rank) P.rules = { P.band = (fun _ _ -> 0); disposition = (fun ~winner:_ ~loser:_ -> P.Omit); - admit = (fun ~observed:_ _ -> []) } + admit = (fun ~observed:_ ~temporal:_ _ -> []) } let year_start y = match D.make ~year:y ~month:1 ~day:1 with Ok d -> d | Error e -> failwith e @@ -377,7 +377,7 @@ module Synthetic = struct let dup_rules : (season, rank) P.rules = { P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10); disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary); - admit = (fun ~observed:_ cs -> List.map (fun (c, p) -> ({ c with P.origin = c.P.origin }, p)) cs) } + admit = (fun ~observed:_ ~temporal:_ cs -> List.map (fun (c, p) -> ({ c with P.origin = c.P.origin }, p)) cs) } (* "unconverged": two entries collide on one date (6 June), both beating the temporal office and tied with each other, so slug decides: @@ -416,7 +416,7 @@ module Synthetic = struct disposition = (fun ~winner:_ ~loser -> match loser.P.cel.Cel.rank with R1 -> P.Transfer | R2 -> P.Commemorate P.Ordinary); - admit = (fun ~observed:_ cs -> cs) } + admit = (fun ~observed:_ ~temporal:_ cs -> cs) } let guard_transfer_target (_ : rank P.candidate) (origin : D.t) (_ : D.t -> rank Cel.t) = origin @@ -444,7 +444,7 @@ module Synthetic = struct { P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10); disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary); admit = - (fun ~observed:_ cs -> + (fun ~observed:_ ~temporal:_ cs -> let sorted = List.stable_sort adm_compare_slug cs in if List.length sorted mod 2 = 1 then adm_take 2 sorted else adm_take 1 sorted) } @@ -475,7 +475,7 @@ module Synthetic = struct disposition = (fun ~winner:_ ~loser -> match loser.P.cel.Cel.rank with R1 -> P.Transfer | R2 -> P.Commemorate P.Ordinary); - admit = (fun ~observed:_ cs -> cs) } + admit = (fun ~observed:_ ~temporal:_ cs -> cs) } let collide_d2 = match D.make ~year:2026 ~month:2 ~day:10 with Ok d -> d | Error e -> failwith e let collide_transfer_target (_ : rank P.candidate) (_ : D.t) (_ : D.t -> rank Cel.t) = collide_d2 @@ -492,7 +492,7 @@ module Synthetic = struct let clean_sanctoral_rules : (season, rank) P.rules = { P.band = (fun _ c -> match c.P.origin with P.Temporal -> 0 | P.Sanctoral -> 10); disposition = (fun ~winner:_ ~loser:_ -> P.Commemorate P.Ordinary); - admit = (fun ~observed:_ cs -> cs) } + admit = (fun ~observed:_ ~temporal:_ cs -> cs) } end open Synthetic |
