aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 12:51:19 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 12:51:19 +0200
commit148729e731370f56a50c3819a7d81808c6e602ca (patch)
treee739546256e34e16d651c69b86d8a898b50b4191 /test
parent2af482c7293d821f10c3bbc96b7913d658c5839c (diff)
parentd0468f53820585e7b4e4bfeb9a4a18f672b821a5 (diff)
downloadcolitur-148729e731370f56a50c3819a7d81808c6e602ca.tar.gz
colitur-148729e731370f56a50c3819a7d81808c6e602ca.zip
Merge branch 'ef-sanctoral-audit': the sanctoral against the Missal
The first full check of all 327 sanctoral entries against the primary calendarium, read from page images of both photographic scans rather than either PDF's OCR text layer -- the second scan's layer interleaves its two print columns row by row and is unusable. Findings that stand: St Barbara (4 December), a Commemoratio both scans carry with her own Mass propers, absent from colitur and from lectio's source alike -- 7196 clean additions, never displacing anything. And 18 colour corrections, all traced to the same bootstrap defect as the earlier eusebius-confessor fix, now shown systemic rather than isolated; several of lectio's own Polish name fields contradict its own colour tag. The Commemoration_only ranks are reframed rather than resolved: the calendarium carries 57 Commemoratio lines and not one gives a class numeral, for anyone. That is a source ceiling, not 105 open questions, and nothing a primary-source read can close. Three corrections did not survive review and are reverted here. RG 120(f) names Cathedrae S. Petri (22 februarii) and Conversionis S. Pauli (25 ianuarii) in its own enumeration of white, fifteen lines above the RG 124(b) they were cited to; RG 124(b)'s own 'in eorum die natalicio' excludes them independently; RG 475(e) confirms it a third time. Both oracles said white because both were right. The cause is worth more than the entries: the page-image method was applied to the calendarium and not to the rubric, and in the text layer the two-column interleave hyphen-splits Cathedrae so it does not grep. A text-layer read of that chapter finds 124 and cannot find 120(f). Two safeguards had been reporting this correctly and were overridden -- a golden pin asserting white, edited to red and rewritten to guard against restoring it, and two allow-lists told to ignore divergences where both oracles were correct. Both restored. Anastasia (25 December) was found and deliberately not added: she is scoped to the second of Christmas's three Masses and the data model has no Mass scope. Now recorded in the tracked tree, beside barbara, where the next auditor will be standing.
Diffstat (limited to 'test')
-rw-r--r--test/test_differential.ml22
-rw-r--r--test/test_golden.ml20
-rw-r--r--test/test_oracle.ml51
-rw-r--r--test/test_rite_ef.ml95
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