diff options
Diffstat (limited to 'test/test_golden.ml')
| -rw-r--r-- | test/test_golden.ml | 174 |
1 files changed, 173 insertions, 1 deletions
diff --git a/test/test_golden.ml b/test/test_golden.ml index 8d33e29..e9b3ec5 100644 --- a/test/test_golden.ml +++ b/test/test_golden.ml @@ -55,6 +55,7 @@ module Slug = Colitur_kernel.Slug module Date = Colitur_kernel.Date module Cel = Colitur_kernel.Celebration module Colour = Colitur_kernel.Colour +module Citation = Colitur_kernel.Citation module Temporal = Colitur_kernel.Temporal module Prec = Colitur_kernel.Precedence module V = Rite_ef.Vocab_ef @@ -170,6 +171,42 @@ let describe (day : (V.season, V.rank) LD.t) = let check ~msg y m d expected = Alcotest.(check string) msg expected (describe (fetch y m d)) +(* ---- Task 10: the reading citations ---- + + A SEPARATE formatter rather than widening [describe] itself, and the + reason is this file's own opening rule, not convenience. Widening + [describe] would invalidate all ~30 expected literals above at once, and + the only practical way to restore them would be to run the suite and paste + back whatever colitur printed -- "copied from a `colitur day` run and then + rationalised", the exact thing the header forbids. Restoring them + HONESTLY would mean hand-verifying 30 further Masses against the scans, + which is a task of its own and not this one. + + So the trade is stated rather than hidden: the pins above stay + citation-blind, and the pins below carry citations for one day per chain + step, every literal hand-verified against the photographic scans BEFORE + being typed here (each pin's own comment carries its scan line numbers). + That division is defensible because layer 2 now covers what breadth would + have bought: {!Colitur_kernel.Validate}'s own citation checks assert the + SHAPE of every day's citations in every year 1583-9999 -- far more days + than 30 pins could -- so what layer 5 still owes is specific VALUES on the + distinct routes, which is exactly what these six are. *) +let describe_readings (day : (V.season, V.rank) LD.t) = + let part_ref p = + match + List.find_opt (fun (c : Citation.t) -> c.Citation.part = p) day.LD.citations + with + | Some c -> c.Citation.reference + | None -> "-" + in + Printf.sprintf "%s slug=%s first=%s gospel=%s" + (Date.to_iso8601 day.LD.date) + (slug_s day.LD.observed) + (part_ref Citation.First) (part_ref Citation.Gospel) + +let check_readings ~msg y m d expected = + Alcotest.(check string) msg expected (describe_readings (fetch y m d)) + let omitted_has (day : (V.season, V.rank) LD.t) slug = List.exists (fun (c, _) -> slug_s c = slug) day.LD.omitted @@ -1122,6 +1159,128 @@ let test_major_litanies_transfer_2011_easter_monday () = "2011-04-26 tuesday season=paschaltide week=1 slug=ef-easter-1-tuesday rank=class-1 colour=white \ subject=temporal name_la=- comms=[major-litanies:privileged] in=- out=[]" +(* ---- Task 10: one pin per step of the reading-resolution chain ---- + + The chain has four steps, and a citation regression is far easier to + diagnose when the failing pin names WHICH step broke. Every literal below + was read out of the photographic scans first (line numbers given per pin), + then compared with colitur -- not the other way round. + + Step 4 deserves special note: it is the ONE step with no external oracle + witness of any kind (register ยง6.7 -- the five Common-routed saints are + the observed office on just five days in all of 2005-2050, and not one + falls inside layer 4's own 2026-2027 fixture window; layer 3 sees those + days but lectio resolves the literal "-"/"-" sentinel there, which is what + C18 is gated on, so it confirms only that colitur emits SOMETHING). These + two pins are therefore the first independent confirmation that route has + ever had, which is also why step 4 gets two of the six rather than one. *) + +(* STEP 1 -- a sanctoral proper: the citation lives on the Celebration + itself, no walk, no Common. 8 March 1938^H2038, "S. Ioannis a Deo Conf., + III classis": "Lectio libri Sapientiae. Eccli. 31, 8-11" / "Sequentia + sancti Evangelii secundum Matthaeum. Mt. 22, 34-46" (scan1.txt:27732-27734 + + 27769-27770; scan2.txt:30698-30699 + 30733-30736; page image p. 485). + The Missal prints him a FULL Mass with its own assigned Gospel -- the + Epistle happens to coincide with the Common of a Confessor not a Bishop's, + but the Gospel does not (that Common has Luke 12:35-40), which is what + makes this a proper and not a Common, and so a step-1 case rather than a + step-4 one. NOTE the plan named 2030-01-13 for this step; that date is a + TEMPORAL day (Holy Family, carried on the generic Sunday slug per + RG 17(b)) and would not have exercised step 1 at all. *) +let test_readings_step1_sanctoral_proper () = + check_readings ~msg:"step 1: sanctoral proper (John of God, 8 March)" 2038 3 8 + "2038-03-08 slug=john-of-god first=Ecclus 31:8-11 gospel=Matt 22:34-46" + +(* STEP 2 -- a temporal day with its own direct lectionary entry. 23 February + 2026 is "Feria II post dominicam I in Quadragesima" (heading, scan1.txt: + 8137): "Lectio Ezechielis Prophetae. Ezech. 34, 11-16" (scan1.txt:8138- + 8139) / "Sequentia sancti Evangelii secundum Matthaeum. Mt. 25,31-46" + (scan1.txt:8199). A Lenten feria is the right shape here because Lent's + ferias each have their OWN Mass -- they never walk back, so a regression + in step 3 cannot mask a regression in step 2 on this date. + The book abbreviation is "Ezech", not "Ezek": this pin was first written + from the scan as "Ezek 34:11-16" and failed, and the difference turned out + to be notation alone -- colitur's own spelling is in fact the Missal's own + ("Ezech. 34, 11-16", above). Recorded rather than quietly amended, since a + failing pin whose only fault is an abbreviation is exactly the kind of + thing a later reader will otherwise re-litigate. Cross-engine abbreviation + differences are normalised away in layer 3 (test_differential.ml's own A/B + normalisation) and so are invisible there; this layer sees them. *) +let test_readings_step2_temporal_proper () = + check_readings ~msg:"step 2: temporal proper (Lent I Monday)" 2026 2 23 + "2026-02-23 slug=ef-lent-1-monday first=Ezech 34:11-16 gospel=Matt 25:31-46" + +(* STEP 3 -- the ferial resumption: a day with NO Mass of its own, which + therefore repeats its preceding Sunday's. 1 December 2025 is the Monday + after Advent I, and Advent's ferias (unlike Lent's) have no proper Mass, + so the citation must be Advent I Sunday's own: "ad Romanos. Rom. 13, + 11-14" (scan1.txt:4878) / "dum Lucam. Luc. 21, 25-33" (scan1.txt:4912). + That the pinned value equals the SUNDAY's, not the Monday's own, is the + whole point of the pin. *) +let test_readings_step3_ferial_resumption () = + check_readings ~msg:"step 3: ferial resumption (Advent I Monday reads Advent I Sunday)" 2025 12 1 + "2025-12-01 slug=ef-advent-1-monday first=Rom 13:11-14 gospel=Luke 21:25-33" + +(* STEP 4 (a) -- the Common route. 6 March 2038, "Ss. Perpetuae et + Felicitatis Martyrum, III classis", whose own entry directs: "Missa Me + exspectaverunt, de Communi non Virginum I loco [35]" (scan1.txt:27634- + 27635). That Common -- COMMUNE NON VIRGINUM, "Pro Martyre non Virgine" + (scan1.txt:42560 ff) -- reads "Lectio libri Sapientiae. Eccli. 51, 1-8 et + 12" (scan1.txt:42589-42590) and "Sequentia sancti Evangelii secundum + Matthaeum. Mt. 13, 44-52" (scan1.txt:42606). 2038 is the only year in + 2005-2050 in which she is the OBSERVED office at all. *) +let test_readings_step4_common_felicitas () = + check_readings ~msg:"step 4: Common of Non-Virgins I (Perpetua & Felicitas)" 2038 3 6 + "2038-03-06 slug=sts-felicitas-perpetua first=Ecclus 51:1-8, 12 gospel=Matt 13:44-52" + +(* STEP 4 (b) -- the SECOND Common, deliberately a different one, so the pin + pair distinguishes "the Common route works" from "one Common's data is + right". 9 March 2038, "S. Franciscae Romanae Vid., III classis", directed + to "Missa Cognovi, de Communi non Virginum" -- the second Mass of that + same Common, which reads "Lectio libri Sapientiae. Prov. 31, 10-31" + (scan1.txt:42679) and shares the Gospel "Mt. 13, 44-52" (scan1.txt:42720). + The shared Gospel with (a) is the Missal's own doing, not a colitur + collapse -- which is exactly why both Epistles are pinned too. *) +let test_readings_step4_common_frances () = + check_readings ~msg:"step 4: Common of Non-Virgins II (Frances of Rome)" 2038 3 9 + "2038-03-09 slug=frances-rome first=Prov 31:10-31 gospel=Matt 13:44-52" + +(* THE DISPLACED-SUNDAY FERIA -- the case that separates the temporal slug + from the observed one, and the one the plan singles out. It is pinned + here as KNOWN-DIVERGENT OUTPUT, deliberately and with the divergence + named, NOT blessed as correct: this is test_oracle.ml's own M26 shape 2(b) + (verdict open). 26 October 2026 is a feria of the week whose Sunday was + displaced by Christ the King (I class, movable, "Dominica ultima + octobris"). The general mechanism -- a week's ferias follow their OWN + Sunday's temporal identity even when that Sunday is impeded -- is the + shape RG 69 establishes for the Nativity Octave, so the displaced ordinary + Sunday's Mass is what the ferias should read; colitur's step 3 instead + walks back to the DISPLACING feast and emits Christ the King's own Gospel + (John 18:33-37, "Art thou a king?"), which is the literal in this pin. + No Missal-propers rubric specific to Christ the King's own week was found + (checked: scan1.txt:39140-39163, no rubric precedes that Mass heading, + unlike Holy Name's and Holy Family's own), so M26 stays verdict open + rather than being asserted against a citation that does not exist. + WHEN M26 IS FIXED THIS PIN MUST FAIL -- that is its purpose. Update it + deliberately then; do not regenerate it. + + Two things this pin established that M26's own note did not record. First, + BOTH parts come from the displacing feast, not only the Gospel M26 cites: + the Epistle here is Col 1:12-20, which is Christ the King's own, so step 3 + is transplanting the whole Mass rather than half of it. Second, the + reference carries a TRAILING PERIOD ("Col 1:12-20."), a blemish inherited + through the bootstrap from the source data. It is pinned verbatim rather + than tidied, because this pin's job is to state what colitur actually + emits today; the period is noted here as a separate, cosmetic data defect + and is deliberately not fixed under a task about test coverage. Layer 3 + cannot see it (its A/B normalisation strips punctuation before comparing), + which is why it surfaced here first. *) +let test_readings_displaced_sunday_feria_known_divergent () = + check_readings + ~msg:"displaced-Sunday feria: pins M26 shape 2(b)'s KNOWN-WRONG walkback, not correct output" + 2026 10 26 + "2026-10-26 slug=ef-time-after-pentecost-22-monday first=Col 1:12-20. gospel=John 18:33-37" + let suite = ( "golden pins (known-tricky years)", [ Alcotest.test_case "Easter extreme: 1598 earliest (22 Mar, Gauss-verified)" `Quick @@ -1199,5 +1358,18 @@ let suite = `Quick test_major_litanies_displaces_mark_on_ii_class_sunday; Alcotest.test_case "RG80's second trigger: Easter Monday = 25 April, the Litanies transfer to Easter+2 (2011)" `Quick - test_major_litanies_transfer_2011_easter_monday + test_major_litanies_transfer_2011_easter_monday; + Alcotest.test_case "readings step 1: sanctoral proper (John of God, 2038-03-08)" `Quick + test_readings_step1_sanctoral_proper; + Alcotest.test_case "readings step 2: temporal proper (Lent I Monday, 2026-02-23)" `Quick + test_readings_step2_temporal_proper; + Alcotest.test_case "readings step 3: ferial resumption (Advent I Monday, 2025-12-01)" `Quick + test_readings_step3_ferial_resumption; + Alcotest.test_case "readings step 4: Common of Non-Virgins I (2038-03-06)" `Quick + test_readings_step4_common_felicitas; + Alcotest.test_case "readings step 4: Common of Non-Virgins II (2038-03-09)" `Quick + test_readings_step4_common_frances; + Alcotest.test_case + "readings: displaced-Sunday feria pins M26 shape 2(b)'s KNOWN-WRONG walkback (2026-10-26)" `Quick + test_readings_displaced_sunday_feria_known_divergent ] ) |
