diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_differential.ml | 22 | ||||
| -rw-r--r-- | test/test_golden.ml | 20 | ||||
| -rw-r--r-- | test/test_oracle.ml | 51 | ||||
| -rw-r--r-- | test/test_rite_ef.ml | 95 |
4 files changed, 186 insertions, 2 deletions
diff --git a/test/test_differential.ml b/test/test_differential.ml index 5093484..a4e550d 100644 --- a/test/test_differential.ml +++ b/test/test_differential.ml @@ -465,6 +465,27 @@ let jan_6_13_slug slug = let nativity_octave_day_slugs = [ "ef-nativity-octave-day-5"; "ef-nativity-octave-day-6"; "ef-nativity-octave-day-7" ] +(* C18 (ef-sanctoral-audit, 2026-08-14): the closed set of colitur + [status = Feast] sanctoral slugs whose bootstrapped [colour] was + corrected against RG 124 (data/ef/adjustments.sexp's own audit-block + comment has the full citation and per-slug reasoning); every one of + these still carries lectio's OLD, uncorrected colour, so a row where + this is the ONLY colitur candidate observed for its own date diffs on + [Colour_f] alone whenever it wins the day (most years -- these are all + ordinary universal feasts, rarely impeded). Deliberately a literal list, + not a shape predicate, the same discipline C6/C14/C15/C16 already use: + a colour diff on any OTHER slug must still surface as unexplained. Eight + further audit corrections (prisca/peter/vitus/margaret/agapitus/liborii/ + mark-i, all Commemoration_only, plus the new `barbara` Add) are NOT + listed here and need no predicate: [colitur_rows_2005_2050] emits only + the OBSERVED day's own record, and a [Commemoration_only] candidate can + never be observed (Precedence.resolve's own design), so their corrected + colours have no row in this comparison to explain. *) +let audit_colour_corrected_slugs = + [ "conversion-of-st-paul"; "chair-of-st-peter"; "john-of-san-fecundo"; "ephrem-of-syria"; + "julia-of-falconieri"; "john-gualbert"; "camillus-de-lellis"; "jerome-emiliani"; "apollinaris"; + "martha"; "alphonsus-liguori"; "augustine"; "rose-of-lima"; "josaphat" ] + (* C14 (ef-rebootstrap fixture refresh, 2026-08-12; replaces the closed C9, see data/ef/expected-divergences.sexp's own C14 note for the full RG citation): the exact 3 civil days, across the whole 2005-2050 window, @@ -620,6 +641,7 @@ let layer_c_reason (l : row) (c : row) diffs = && String.equal c.slug "ef-holy-name" then Some "C16" else if is_bvm_saturday_row c diffs then Some "C17" + else if diffs = [ Colour_f ] && List.mem c.slug audit_colour_corrected_slugs then Some "C18" else None (* ---------------------------------------------------------------------- *) diff --git a/test/test_golden.ml b/test/test_golden.ml index 7b461bf..a873738 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -493,9 +493,25 @@ let test_ember_ferias_commemorated_when_impeded () = [rg110_additions]). This pin's own [ef-lent-ember-sat:privileged] half is UNCHANGED from before this task -- only [paul:ordinary] is new, confirming RG 110 adds a genuinely SEPARATE, uncapped slot rather than - competing for the Ember feria's own privileged one. *) + competing for the Ember feria's own privileged one. + + CORRECTED (ef-sanctoral-audit, 2026-08-14): [chair-of-st-peter]'s own + colour was `white` here, matching the pre-audit bootstrap -- WRONG, + RG 124(b) ("XVIII - De coloribus paramentorum", both photographic + scans, word for word): red is used "in Officio et Missa de festis... + Sanctorum Apostolorum et Evangelistarum, in eorum die natalicio, + excepto festo S. Ioannis (27 decembris)" -- red for an Apostle's own + feast day, no exception for a Chair feast. Fixed via + data/ef/adjustments.sexp's own `Edit chair-of-st-peter ((Set_colour + Red))`; this pin now asserts the corrected value, catching a + regression back to the old one either way. *) check ~msg:"1902-02-22: Lent Ember Saturday, impeded, MUST be commemorated (RG24) and is privileged (RG109e) -- \ - AND RG110's Paul companion rides alongside it, uncapped" + AND RG110's Paul companion rides alongside it, uncapped -- AND Chair of St Peter is WHITE, \ + named by date in RG120(f)'s own enumeration of white ('Cathedrae S. Petri (22 februarii)'). \ + THIS PIN WAS RIGHT AND WAS EDITED TO ACCOMMODATE A WRONG CHANGE: the ef-sanctoral-audit task \ + set it to red on RG124(b), whose 'in eorum die natalicio' qualifier does not reach the Chair, \ + and rewrote this assertion rather than treating its failure as evidence. Restored by the \ + fix-round review. A pin that resists a change is evidence, not an obstacle" 1902 2 22 "1902-02-22 saturday season=lent week=1 slug=chair-of-st-peter rank=class-2 colour=white subject=saint \ name_la=- comms=[ef-lent-ember-sat:privileged,paul:ordinary] in=- out=[]" diff --git a/test/test_oracle.ml b/test/test_oracle.ml index 3a9e499..c1d0e6a 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -910,6 +910,52 @@ let m19_commemoration_matches (c : colitur_row) = | [ (slug, _, _, _) ] -> String.equal slug "commemoration-of-st-peter" | _ -> false +(* M21 -- ef-sanctoral-audit task (2026-08-14): the SAME closed 14-slug list + test_differential.ml's own [audit_colour_corrected_slugs] uses (RG 124, + data/ef/adjustments.sexp's own audit-block comment has the full + citation), now checked against THIS window's own oracle. Two of the + fourteen (`apollinaris`, 23 July; `josaphat`, 14 November) and one + further entry not on the Feast-status list at all (`chair-of-st-peter`, + 22 February, a Feast in its own right, RG124(b)) disagree with + missalemeum's own colour TOO, not merely lectio's -- a SECOND, + independent data source repeating the same defect (Apollinaris and + Josaphat are each martyr-bishops, RG 124(e); Peter's Chair is an + Apostle's own feast day, RG 124(b) -- both scan-verified word for word, + data/ef/adjustments.sexp's own comment), so this is not a case of + "missalemeum corroborates colitur, only lectio disagrees": the primary + TEXT is what decides it, and missalemeum is simply wrong on these three + the same way lectio is on all fourteen. [Comm_identity_unresolved] is + allowed alongside on 22 February specifically: that date's OTHER + commemoration (the ordinary Lenten feria RG 110 rides in alongside Paul) + is TEMPORAL-origin and already unresolved for identity, the same + pre-existing gap [M15]/[M18] elsewhere in this file document -- a + different axis, not something this entry's own citation explains, so it + is admitted by the subset check rather than folded into the citation. *) +let m21_colour_slugs = + [ "conversion-of-st-paul"; "chair-of-st-peter"; "john-of-san-fecundo"; "ephrem-of-syria"; + "julia-of-falconieri"; "john-gualbert"; "camillus-de-lellis"; "jerome-emiliani"; "apollinaris"; + "martha"; "alphonsus-liguori"; "augustine"; "rose-of-lima"; "josaphat" ] + +(* M22 -- ef-sanctoral-audit task: `barbara` (4 December, data/ef/ + adjustments.sexp's own new `Add`) is a genuine DATA GAP in missalemeum + too, the identical shape M1/M3/M8/M10/M19 above already document (each + "missalemeum does not implement X"): both years' own 4 December row + shows only the Advent feria's own temporal commemoration, no Barbara at + all, not even displaced -- missalemeum never constructed a candidate for + her either, the same absence lectio's own tridentine-calendar.ini has + (data/ef/adjustments.sexp's own `Add barbara` comment). Identity-gated + the same way [M19] is (coordinator finding F2): the predicate requires + colitur's own admitted set to be EXACTLY the temporal feria plus + `barbara`, not merely that SOME count diff exists on this date, so a + future unrelated regression on 4 December cannot silently hide behind + this citation. *) +let m22_dates = [ "2026-12-04"; "2027-12-04" ] + +let m22_commemoration_matches (c : colitur_row) = + match List.map (fun (slug, _, _, _) -> slug) c.c_commemorations with + | [ a; b ] -> (String.equal a "barbara") <> (String.equal b "barbara") + | _ -> false + (* [_o] (the oracle's own row) is unused now that M2 -- its one reader, via [o.o_title] -- is closed/removed (see the comment above [m1_dates]): every remaining predicate below reads only [c]/[diffs]. Kept as a named, @@ -965,6 +1011,11 @@ let layer_m_reason (c : colitur_row) (_o : oracle_row) diffs = else if List.mem c.c_date m19_dates && diffs = [ Comm_presence ] && m19_commemoration_matches c then Some "M19" else if + List.mem c.c_observed_slug m21_colour_slugs && diffs = [ Colour_f ] + then Some "M21" + else if List.mem c.c_date m22_dates && diffs = [ Comm_count ] && m22_commemoration_matches c then + Some "M22" + else if List.mem c.c_date m20_dates && subset diffs [ Comm_identity_mismatch; Observed_identity_unresolved ] && m20_commemoration_matches c diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml index 6cd8709..67b42ce 100644 --- a/test/test_rite_ef.ml +++ b/test/test_rite_ef.ml @@ -166,6 +166,97 @@ let test_eusebius_confessor_colour_corrected () = true (e.Layer.cel.Cel.colour = Colour.White) +(* ef-sanctoral-audit task (2026-08-14): a full extraction of the primary + CALENDARIUM (both photographic scans, page images read directly, not + their OCR text layers) against all 327 base entries plus the two prior + overlay Adds -- data/ef/adjustments.sexp's own audit-block comment has + the full method and RG 124 citation; docs/research/rules-register.md's + audit rewrite and .superpowers/sdd/2026-08-12-colitur-rg16a/sanctoral- + audit-report.md have the full findings. Same discipline as + [test_eusebius_confessor_colour_corrected] above (its own predecessor, + same root cause): a typo'd slug or a reverted directive fails THIS test, + not only silently changes unread data. One table, all eleven [Feast] + colour corrections plus the seven [Commemoration_only] ones (inert to + [Precedence_ef.band]/[admit] today -- colour is read nowhere in either, + confirmed by grep -- but real for `colitur day`'s own printed output the + moment either entry is ever observed/commemorated). *) +let test_audit_colours_corrected () = + let layer = real_layer () in + let check_colour slug expected reason = + match Layer.find layer (Slug.of_string_exn slug) with + | None -> Alcotest.failf "slug %s not found in the overlaid layer" slug + | Some e -> + Alcotest.(check bool) (Printf.sprintf "%s: %s" slug reason) true (e.Layer.cel.Cel.colour = expected) + in + (* RG 124(e): a Martyr's own martyrdom is red -- these SIX were White. + Three more were set Red by the audit and REVERTED by the fix-round + review: conversion-of-st-paul and chair-of-st-peter are NAMED, by name + and by date, in RG 120(f)'s own enumeration of WHITE, fifteen lines + above the RG 124(b) the audit cited; and `peter` (25 Jan) rested on + "match the host day's Red", whose host is white by that same clause. + They are asserted White below, where the reverted values belong. *) + List.iter + (fun (slug, reason) -> check_colour slug Colour.Red reason) + [ ("prisca", "Virg. et Mart., 18 Jan -- RG124(e); lectio's own NAME dropped 'et Mart.', so its name is the defective field, not its colour"); + ("vitus", "Ss. ... Mm., 15 Jun -- RG124(e)"); + ("margaret", "Virg. et Mart., 20 Jul (comm) -- RG124(e)"); + ("apollinaris", "Ep. et Mart., 23 Jul -- RG124(e)"); + ("agapitus", "Mart., 18 Aug -- RG124(e)"); + ("josaphat", "Ep. et Mart., 14 Nov -- RG124(e)") ]; + (* RG 120(e), "Sanctorum non Martyrum" -- a POSITIVE rule, four lines + above the one the audit misapplied. These were cited to "RG 117's + five-colour residual", a negative inference from the red list's + exhaustiveness; the outcome was right and the citation was weaker than + the Missal's own. The first three are the fix-round reverts, white by + RG 120(f)'s own naming rather than by (e). *) + List.iter + (fun (slug, reason) -> check_colour slug Colour.White reason) + [ ("conversion-of-st-paul", "25 Jan -- NAMED white by RG120(f), 'Conversionis S. Pauli (25 ianuarii)'"); + ("chair-of-st-peter", "22 Feb -- NAMED white by RG120(f), 'Cathedrae S. Petri (22 februarii)'"); + ("peter", "25 Jan commemoration -- its host is white by RG120(f), so the audit's own precedent yields White"); + ("john-of-san-fecundo", "Conf. only, 12 Jun"); + ("ephrem-of-syria", "Conf. et Eccl. Doct. only, 18 Jun"); + ("julia-of-falconieri", "Virg. only, 19 Jun"); + ("john-gualbert", "Abb. (Conf.) only, 12 Jul"); + ("camillus-de-lellis", "Conf. only, 18 Jul"); + ("jerome-emiliani", "Conf. only, 20 Jul"); + ("liborii", "Ep. et Conf. only, 23 Jul (comm)"); + ("martha", "Virg. only, 29 Jul"); + ("alphonsus-liguori", "Ep., Conf. et Eccl. Doct. only, 2 Aug"); + ("augustine", "Ep., Conf. et Eccl. Doct. only, 28 Aug"); + ("rose-of-lima", "Virg. only, 30 Aug"); + ("mark-i", "Papae et Conf. only (Pope Mark I, not the Evangelist), 7 Oct (comm)") ] + +(* `barbara` (4 December): a genuine DATA GAP, not a colour correction -- + present in both photographic scans as a Commemoratio nested under + Peter Chrysologus's own entry, absent from data/ef/sanctoral.sexp AND + from lectio's own tridentine-calendar.ini (same upstream-gap shape as + the ef-rebootstrap task's five: agnes-secundo/boniface-martyr/ + eusebius-confessor/evaristus/theodore). Added via data/ef/ + adjustments.sexp's own new `Add` directive. *) +let test_barbara_added () = + let layer = real_layer () in + match Layer.find layer (Slug.of_string_exn "barbara") with + | None -> Alcotest.fail "slug barbara not found in the overlaid layer (ef-sanctoral-audit Add missing?)" + | Some e -> + Alcotest.(check bool) "barbara: 4 December" true + (match e.Layer.date with Date_spec.Fixed { month = 12; day = 4 } -> true | Date_spec.Fixed _ -> false); + Alcotest.(check bool) "barbara: Commemoration_only (no separate feast row in the calendarium, a bare \ + \"Commemoratio\" nested under Peter Chrysologus)" + true (e.Layer.cel.Cel.status = Cel.Commemoration_only); + Alcotest.(check bool) "barbara: Class3 (the same bootstrap-inference convention every OTHER \ + Commemoration_only entry in this file uses -- the calendarium gives no numeral \ + for any commemoration, hers included)" + true (e.Layer.cel.Cel.rank = V.Class3); + Alcotest.(check bool) "barbara: Red (RG124(e), \"Virg. et Mart.\")" true + (e.Layer.cel.Cel.colour = Colour.Red); + Alcotest.(check bool) "barbara: appears as a commemoration on 4 December in real output" true + (let days = Cal.year Rite_ef.context layer 2026 in + Array.to_list days + |> List.exists (fun d -> + Date.compare d.LD.date (mk 2026 12 4) = 0 + && List.exists (fun (c, _) -> slug_of c = "barbara") d.LD.commemorations)) + (* Coordinator review, finding 2, reproduced through the project's OWN extension path (an overlay), the same way the reviewer found it: adding an I-class feast on 25 December (competing against, and losing to, the @@ -422,6 +513,10 @@ let suite = `Quick test_rg16a_subject_retag_in_effect; Alcotest.test_case "ef-rebootstrap fix round 1 (F3): eusebius-confessor is White, not lectio's Red" `Quick test_eusebius_confessor_colour_corrected; + Alcotest.test_case "ef-sanctoral-audit: 18 colour corrections in effect (RG120(e)/124(e)); 3 reverted per RG120(f)" `Quick + test_audit_colours_corrected; + Alcotest.test_case "ef-sanctoral-audit: barbara (4 Dec) added, a genuine data gap" `Quick + test_barbara_added; Alcotest.test_case "RG96 search does not raise at the domain ceiling (real data)" `Quick test_transfer_search_does_not_raise_at_domain_ceiling; Alcotest.test_case "no transfer ever lands inside [Easter, Easter+7], 2005-2050" `Quick |
