(* Task 5 (2026-08-25-colitur-of-phases-3-5): [Rite_of.context], wired together with the REAL data/of/calendar-2002.sexp + all 13 decree overlays + data/of/lectionary.sexp, resolved through {!Colitur_kernel.Calendar} and checked by {!Colitur_kernel.Validate.run} -- the same pipeline `colitur day --rite of` uses, and the same discipline test_validate.ml/test_rite_ef.ml already apply to the EF side: exactly one observed office per day, the year covered once with no gaps, slug-uniqueness within the liturgical year, and transfers reaching a fixed point are all invariants {!Colitur_kernel.Validate.run} already checks generically -- this file supplies the REAL OF rite and data and asserts the result is clean, rather than re-deriving each invariant by hand. *) module Val = Colitur_kernel.Validate module Layer = Colitur_kernel.Layer module Overlay = Colitur_kernel.Overlay module Cal = Colitur_kernel.Calendar module LD = Colitur_kernel.Liturgical_day module Slug = Colitur_kernel.Slug module Date = Colitur_kernel.Date module Cel = Colitur_kernel.Celebration module P = Colitur_kernel.Precedence module Computus = Colitur_kernel.Computus module V = Rite_of.Vocab_of (* Relative to this test's own build directory (_build/default/test/), same convention test_amendments_of.ml/test_calendar_of_data.ml already use -- test/dune declares each of these as a dep of the (test ...) stanza. *) let base_path = "../data/of/calendar-2002.sexp" let amendments_dir = "../data/of/amendments/" let lectionary_path = "../data/of/lectionary.sexp" (* Decree-chronological order -- the exact list and order test_amendments_of.ml's own [files] table already pins by SHA-256; not re-pinning the hashes here (that is that file's own job), just applying them in the same order so the rite under test here is the one bin/main.ml will assemble. *) let amendment_files = [ "001-padre-pio.sexp"; "002-juan-diego-cuauhtlatoatzin.sexp"; "003-our-lady-of-guadalupe.sexp"; "004-john-xxiii-john-paul-ii.sexp"; "005-mary-magdalene-rank.sexp"; "006-mary-mother-of-the-church.sexp"; "007-paul-vi.sexp"; "008-our-lady-of-loreto.sexp"; "009-faustina-kowalska.sexp"; "010-narek-avila-hildegard.sexp"; "011-martha-mary-lazarus.sexp"; "012-teresa-of-calcutta.sexp"; "013-john-henry-newman.sexp" ] let real_of_layer = let base = match Layer.load V.rank_of_sexp base_path with | Ok l -> l | Error e -> failwith (Printf.sprintf "%s: failed to load: %s" base_path e) in let overlays = List.map (fun name -> let path = amendments_dir ^ name in match Overlay.load V.rank_of_sexp path with | Ok o -> o | Error e -> failwith (Printf.sprintf "%s: failed to load: %s" path e)) amendment_files in let layer, diagnostics = Overlay.merge base overlays in if diagnostics <> [] then failwith (Printf.sprintf "unexpected amendment diagnostics: %s" (String.concat "; " (List.map Overlay.diagnostic_to_string diagnostics))); layer (* [Rite_of.context] takes [~lectionary] as a caller-supplied parameter, not a value closed over an internal load -- see rite_of.ml's own citation for why (the exact `colitur easter ` startup-death lesson {!Rite_ef.Rite_ef.context}'s own comment records). *) let real_of_lectionary = match Colitur_kernel.Lectionary.load lectionary_path with | Ok l -> l | Error e -> failwith (Printf.sprintf "%s: failed to load: %s" lectionary_path e) let real_of_rite = Rite_of.context ~lectionary:real_of_lectionary let run year = Val.run real_of_rite real_of_layer ~year (* CLOSED, fix wave I8 (final-review.md, 2026-08-25-colitur-of-phases-3-5). This paragraph used to describe a LIVE gap: data/of/lectionary.sexp's own provenance header named ONE informational temporal-slug gap, [of-nativity] (25 December -- Christmas Day itself), because niedziela.pl's own source never covered the Christmas DAY Mass at all (only the Vigil), which made {!Colitur_kernel.Validate.run}'s ["citations-unresolved"]/["formulary"] checks fire every year, on 25 December, on real shipped data. tools/bootstrap_lectionary_of.ml's own [hand_authored] table now injects that entry directly (Isaiah 52:7-10 / John 1:1-18, OLM 1981's own "16 Ad Missam in die", docs/research/of/olm-1981-ocr.txt:4513-4520) -- a primary-source citation, not a guess, the same discipline every other hand-authored entry in this project follows. [is_known_nativity_gap] is kept, not deleted, but is no longer in [is_known]'s own filter below: it now exists ONLY as an explicit, named "this must never fire again" check ({!check_year_allowing_known_gaps}'s own dedicated assertion) -- a regression here surfaces as an ordinary unexpected-failure test error, not a silently-absorbed known gap, which is the whole point of moving a predicate out of the filter once its own defect closes. *) let ends_with ~suffix s = let ls = String.length s and lx = String.length suffix in ls >= lx && String.sub s (ls - lx) lx = suffix (* No [Str]/regex (deps frozen) -- a plain substring scan. *) let contains ~substring s = let ls = String.length s and lx = String.length substring in let rec go i = i + lx <= ls && (String.sub s i lx = substring || go (i + 1)) in lx = 0 || go 0 let is_known_nativity_gap (f : Val.failure) = (f.Val.check = "citations-unresolved" || f.Val.check = "formulary") && ends_with ~suffix:"12-25" f.Val.date (* CLOSED (W2, CLAUDE.md; fixed in temporal_of.ml). This paragraph used to describe a SECOND, NEWLY-FOUND gap this task's own wiring surfaced -- [rite_of] was never previously wired into a real {!Colitur_kernel.Rite.t}, so [Validate.run]'s ["anchor"] check had never before run [Temporal_of.anchors] against [Temporal_of.temporal] for real. Normae n. 35(a)'s own text is "Dominica infra octavam Nativitatis, VEL, EA DEFICIENTE, die 30 decembris" -- the Holy Family fallback is a FIXED-DATE fallback (30 December, whatever weekday it falls on that year), confirmed by {!Temporal_of.holy_family}'s own [None -> mk y 12 30] branch and its own .mli citation ("this 6-day window CAN be [empty of a Sunday] -- confirmed by the fallback clause's own existence"). But {!Temporal_of.temporal} used to only ever TEST [same d (holy_family y)] inside its [sunday_slug d] dispatch arm -- i.e. only when [d] genuinely WAS a Sunday -- so in a year whose 26-31 December window had NO Sunday (equivalently: 25 December, Christmas Day, is itself a Sunday), the fallback date was computed correctly by [holy_family]/[anchors] but [temporal] itself silently fell through to an ordinary ferial slug instead (["of-christmas-0-friday"] et al.) -- exactly the "generic day slug masking a real named feast" shape CLAUDE.md already records EF's own Holy Family/Holy Name gaps as, before they were fixed there. Not rare: this fired whenever Christmas Day is a Sunday, roughly one year in seven. [Temporal_of.temporal] now consults [Temporal_of.holy_family] directly in that dispatch arm, independent of weekday, carrying the identical identity (subject Lord, [holy_family_names], rank Festum) the Sunday case already builds -- see temporal_of.ml's own citation on that branch. [is_known_holy_family_fallback_gap] is kept, not deleted, but is no longer in [is_known]'s own filter below -- the same discipline [is_known_nativity_gap] above already established once ITS defect closed: it exists ONLY as an explicit, named "this must never fire again" check ({!check_year_allowing_known_gaps}'s own dedicated assertion), not silently absorbed. *) let is_known_holy_family_fallback_gap (f : Val.failure) = f.Val.check = "anchor" && contains ~substring:"of-holy-family" f.Val.detail let check_year_allowing_known_gaps year = let fs = run year in (* Fix wave I8: [is_known_nativity_gap] is deliberately NOT part of [is_known] any more -- see that predicate's own header. W2 fix: neither is [is_known_holy_family_fallback_gap] now -- see ITS own header. No known gaps remain filtered here (landmark years validate cleanly, full stop); [is_known] is kept as a named hook rather than inlined to [false] so a future gap has an obvious place to land. *) let is_known (_ : Val.failure) = false in let unexpected = List.filter (fun f -> not (is_known f)) fs in (match unexpected with | [] -> () | fs -> Alcotest.failf "%d: %s" year (String.concat "; " (List.map Val.failure_to_string (List.filteri (fun i _ -> i < 5) fs)))); Alcotest.(check int) (Printf.sprintf "%d: no of-nativity citations-unresolved/formulary gap (fix wave I8 -- was 2)" year) 0 (List.length (List.filter is_known_nativity_gap fs)); Alcotest.(check int) (Printf.sprintf "%d: no Holy Family anchor gap (W2 fix -- was 1)" year) 0 (List.length (List.filter is_known_holy_family_fallback_gap fs)) (* Landmark years, the same choice test_validate.ml's own [test_landmark_years] makes for EF: both domain edges plus two ordinary years well inside it. *) let test_landmark_years () = List.iter check_year_allowing_known_gaps [ 1583; 2026; 2035; 9998 ] (* 9999 mirrors test_validate.ml's own [test_year_9999_does_not_raise]: the liturgical year opening in civil year 9999 continues into out-of-domain civil year 10000, so [Val.run]/[Calendar.year] clamp the walk to 31 December 9999 rather than raising, and the truncated season run is *expected* to fail the "seasons" check -- pinning that this surfaces as an ordinary failure, not an uncaught exception, and that resolution itself ("coverage"/"lost"/"duplicated") stays clean through the clamp. *) let test_year_9999_does_not_raise () = let fs = run 9999 in Alcotest.(check bool) "no coverage failures (temporal stayed total through the clamp)" true (not (List.exists (fun f -> f.Val.check = "coverage") fs)); Alcotest.(check bool) "seasons check flags the truncated final year as incomplete" true (List.exists (fun f -> f.Val.check = "seasons") fs) (* A real transfer-bearing sample, the OF counterpart of test_rite_ef.ml's own 2005-2050 sweep: every impeded Sollemnitas [Precedence_of.disposition] defers is either placed by [transfer_target] and reaches a fixed point (no "unconverged" failure -- Validate's own check), or is recorded [omitted] with a reason, never silently dropped ("lost"/"duplicated"), over the project's own 2005-2050 differential-testing window (CLAUDE.md). STRUCTURAL checks only -- ["coverage"; "weekday"; "rank"; "colour"; "determinism"; "slugs"; "seasons"; "week"; "lost"; "duplicated"; "unconverged"; "admission"; "observed"] -- deliberately NOT the citation-chain ones ("anchor"/"citations"/"citations-unresolved"/ "formulary"), and this exclusion is itself a finding, not a shortcut: sweeping the full 46-year window (not just the 4 landmark years above) surfaced that [data/of/lectionary.sexp]'s own coverage was measured against exactly ONE civil year (2026, per that file's own provenance header) -- OTHER years exercise the OTHER weekday-cycle letter for the same temporal slug (OLM n.69.4, {!Lectionary_of.weekday_cycle}: which letter applies flips on the LITURGICAL year label's parity, independent of which civil year is being swept), and at least one such pairing is asymmetric on real shipped data: [of-christmas-0-friday-ii] exists, [of-christmas-0-friday-i] does not (confirmed directly against data/of/lectionary.sexp; first reached in this sweep at 2006-12-29). Separately, 2006-12-24 (a year Christmas Eve itself is a Sunday) also exposed a THIRD newly-found gap: {!Temporal_of.anchors} lists [of-nativity-vigil] on 24 December UNCONDITIONALLY, but {!Temporal_of.named}'s own coded exception (Tabula I.2/Normae n.5: Advent IV outranks the Vigil when they coincide) means {!Temporal_of.temporal} does not always agree. All three are OUT OF THIS TASK'S SCOPE to fix -- lectionary_of.* and data/of/lectionary.sexp are excluded from this task's brief, and temporal_of.ml's own rubric logic is Task 1's deliverable -- reported as concerns in this task's own report rather than fixed here or silently excluded without explanation. CORRECTED (fix-lectionary-anchors task, 2026-08-26): the of-nativity- vigil/[anchors] disagreement described in the paragraph above is now FIXED -- {!Temporal_of.anchors} carries the same Sunday guard [named] already had. A dedicated exhaustive sweep (test_temporal_of.ml's own [test_exhaustive_domain_sweep], every civil year 1584-9997 under COLITUR_EXHAUSTIVE_SWEEP=1) confirmed this was also the ONLY unexplained [anchors]/[temporal] drift anywhere in the domain -- the other two items in this paragraph (the lectionary weekday-cycle-letter asymmetry, and the Holy Family 30-December fallback {!is_known_holy_family_fallback_gap} below already pins) were unrelated and remained open, unchanged by this fix. CORRECTED AGAIN (W2, CLAUDE.md, same day): the Holy Family 30-December fallback named just above is ALSO now fixed -- {!Temporal_of.temporal} consults {!Temporal_of.holy_family} directly, independent of weekday. Only the lectionary weekday-cycle-letter asymmetry remains open; it is untouched by this fix (lectionary_of.*/data/of/lectionary.sexp are out of scope here, per the original paragraph's own citation). *) let sample_years = let rec range a b = if a > b then [] else a :: range (a + 1) b in range 2005 2050 let structural_check = function | "anchor" | "citations" | "citations-unresolved" | "formulary" -> false | _ -> true let check_year_structural_only year = match List.filter (fun f -> structural_check f.Val.check) (run year) with | [] -> () | fs -> Alcotest.failf "%d: %s" year (String.concat "; " (List.map Val.failure_to_string (List.filteri (fun i _ -> i < 5) fs))) let test_transfers_reach_a_fixed_point_2005_2050 () = List.iter check_year_structural_only sample_years let slug_of (c : V.rank Cel.t) = Slug.to_string c.Cel.slug (* RESOLVED ([of-normae-56f]/W1, 2026-08-26; previously the precedence_of.mli-documented KNOWN-UNIMPLEMENTED fourth transfer_target rule, final review Important #5, ledger ruling R9). Normae n. 56(f) -- St Joseph's solemnity, falling on Palm Sunday, is ANTICIPATED BACKWARD to 18 March, not carried forward. {!Colitur_kernel.Rite.t.transfer_target}'s own obligation was relaxed from "strictly later than origin" to "different from origin" (rite.mli's own comment carries the argument, traced against {!Colitur_kernel.Calendar}'s actual placement pass, not merely assumed safe), and [Precedence_of.transfer_target] gained a Rule 0 for exactly this collision -- see that value's own .ml/.mli for the full citation. Previously pinned here as KNOWN WRONG (colitur sent Joseph forward to Easter+9 via the general rule 3 instead); now pinned as CORRECT. All years with Gregorian Easter = 26 March put Palm Sunday on 19 March, coinciding with Joseph; 2062 is the nearest one after today (2026) still inside the differential-adjacent range this project favours for worked examples. 2062 is a doubly-worked example, not chosen only for Joseph: that same year, 25 March (the Annunciation) falls on HOLY SATURDAY (Easter - 1), so the Annunciation is ALSO impeded and targets Easter + 8 via the general rule -- independently of Joseph now, since Rule 0 is a fixed one-day displacement that never enters the general search or competes with the Annunciation's own target at all (Joseph departs 19 March for 18 March; the Annunciation departs 25 March for Easter+8 -- the two no longer collide the way they did when both were pushed toward the same forward date). *) let test_joseph_palm_sunday_2062_anticipated_backward () = let easter_2062 = Computus.gregorian_easter 2062 in Alcotest.(check string) "2062 Easter is really 26 March (the Normae n.56(f) trigger)" "2062-03-26" (Date.to_iso8601 easter_2062); let palm_sunday = Date.add_days easter_2062 (-7) in Alcotest.(check string) "Palm Sunday 2062 is really 19 March, coinciding with St Joseph" "2062-03-19" (Date.to_iso8601 palm_sunday); let holy_saturday = Date.add_days easter_2062 (-1) in Alcotest.(check string) "25 March 2062 is really Holy Saturday, coinciding with the Annunciation too" "2062-03-25" (Date.to_iso8601 holy_saturday); let days = Cal.year real_of_rite real_of_layer 2061 in let day_of d = Array.to_list days |> List.find (fun day -> Date.compare day.LD.date d = 0) in let joseph_day = day_of palm_sunday in Alcotest.(check string) "Palm Sunday itself is observed on 19 March (Joseph impeded, correctly)" "of-palm-sunday" (slug_of joseph_day.LD.observed); let joseph_slug = "joseph-husband-of-the-blessed-virgin-mary" in let departure = List.find_opt (fun (c, _) -> slug_of c = joseph_slug) joseph_day.LD.transferred_out in let eighteen_march = Date.add_days palm_sunday (-1) in (match departure with | None -> Alcotest.fail "expected Joseph to be transferred_out from 19 March 2062 (impeded by Palm Sunday)" | Some (_, target) -> Alcotest.(check string) "Normae n.56(f): Joseph is anticipated BACKWARD to 18 March 2062, not carried forward" "2062-03-18" (Date.to_iso8601 target); Alcotest.(check bool) "which really is the day before Palm Sunday" true (Date.compare target eighteen_march = 0)); let march18_day = day_of eighteen_march in Alcotest.(check string) "and 18 March 2062 itself observes St Joseph (not Cyril of Jerusalem's \ ad-libitum memorial, not the ordinary Lenten Saturday feria)" joseph_slug (slug_of march18_day.LD.observed); let joseph_arrived = match march18_day.LD.transferred_in with | Some c -> slug_of c = joseph_slug | None -> false in Alcotest.(check bool) "and 18 March 2062 records the arrival (transferred_in), not a silent placement" true joseph_arrived; (* {!Colitur_kernel.Rite.t.transfer_target}'s own second obligation (terminate) reduces, for this liturgical year, to the whole-year placement pass reaching a fixed point at all -- {!Val.run}'s own "unconverged" check is exactly {!Colitur_kernel.Calendar}'s round guard surfaced as a named failure (calendar.ml's own [unconverged_reason]). *) let failures = run 2061 in Alcotest.(check bool) "the whole 2061 liturgical year still reaches a fixed point (no unconverged \ transfer placement anywhere in it)" false (List.exists (fun f -> f.Val.check = "unconverged") failures) (* CLOSED, W2 fix (CLAUDE.md). This test used to pin a defect the same way [is_known_holy_family_fallback_gap]'s own citation just above describes: 1583 is the domain floor AND a year Christmas Day falls on a Sunday, so 26-31 December has no Sunday of its own and [Temporal_of.holy_family] falls back to its own fixed 30 December -- correctly, per [Temporal_of.anchors] -- but [Temporal_of.temporal] used to never reach that fallback (its Holy-Family test lived inside the Sunday-only dispatch arm), so 30 December 1583 was observed as an ordinary Friday-of-Christmastide ferial office instead of the Feast of the Holy Family. Now that {!Temporal_of.temporal} consults {!Temporal_of .holy_family} directly, this test asserts the FIXED, correct behaviour instead -- through the full real-data {!Colitur_kernel.Calendar}/ {!Colitur_kernel.Precedence} pipeline, not merely {!Temporal_of.temporal} in isolation (test_temporal_of.ml's own [test_holy_family_fallback_temporal] already covers that layer) -- checking identity (subject, rank), not only the slug, so a fix that landed the right slug on the wrong grade would still be caught. *) let test_holy_family_fallback_1583_now_correct () = let christmas_1583 = Date.of_iso8601 "1583-12-25" |> Result.get_ok in Alcotest.(check bool) "1583 Christmas Day really is a Sunday (the Normae n.35(a) trigger)" true (Date.weekday christmas_1583 = Date.Sun); let days = Cal.year real_of_rite real_of_layer 1583 in let dec30 = Array.to_list days |> List.find (fun d -> Date.compare d.LD.date (Date.add_days christmas_1583 5) = 0) in Alcotest.(check string) "FIXED (W2): 30 December 1583 is observed as of-holy-family, not an ordinary ferial" "of-holy-family" (slug_of dec30.LD.observed); Alcotest.(check string) "subject is Lord (same identity the Sunday case carries)" "lord" (Colitur_kernel.Subject.to_string dec30.LD.observed.Cel.subject); Alcotest.(check string) "rank is Festum, not a lesser grade" "festum" (V.rank_to_string dec30.LD.observed.Cel.rank) (* Fix wave I6 (final-review.md, 2026-08-25-colitur-of-phases-3-5): the obligatory-memorial tie data/of/amendments/006-mary-mother-of-the-church .sexp's own header documents at length (its "*** FINDING ***" comment) was documented but never PINNED -- the ledger's own remedy (F-MEMORIAL-TIE) asked for both halves. Mary, Mother of the Church (Easter+50) and Anthony of Padua (13 June, fixed) both band at Tabula III.10 (100, both universal Memoria_obligatoria) in any year Easter+50 lands on 13 June; 2011 is the worked example that amendment header itself names (Easter 24 April 2011, so Easter+50 = 13 June -- re-derived here, not trusted from the comment). KNOWN ARBITRARY, not KNOWN WRONG: unlike the two tests above, there is no rubric this contradicts. The 2018 decree (AAS 110, 437-438) is silent on a universal-calendar coincidence with an existing obligatory memorial, and Normae n. 14's own third clause resolves only the AD-LIBITUM/AD-LIBITUM case ("Si eodem die plures inscribuntur in calendario memoriae ad libitum") -- it does not reach two OBLIGATORY memorials. So colitur's Slug.compare tie-break ("anthony-of-padua-priest-and-doctor" sorts before "mary-mother-of-the-church") is not this project inventing a rule; it is the kernel's own generic, rite-agnostic fallback, applied here for lack of a rite-specific one. This test pins that CURRENT behaviour so a future Calendar/kernel change, a slug rename, or a future overlay cannot flip which of the two is observed with no test going red -- the same shape of invisible-drift risk the EF side's RG 113/[band] fidelity work (`ef-rg16a`, register ยง6.1) eliminated on that side. *) let test_mater_ecclesiae_anthony_tie_2011_known_arbitrary () = let easter_2011 = Computus.gregorian_easter 2011 in Alcotest.(check string) "2011 Easter is really 24 April (the Easter+50 trigger)" "2011-04-24" (Date.to_iso8601 easter_2011); let tie_date = Date.add_days easter_2011 50 in Alcotest.(check string) "Easter+50 2011 is really 13 June, coinciding with Anthony of Padua's fixed date" "2011-06-13" (Date.to_iso8601 tie_date); (* [Cal.year]'s own [y] labels an Advent-to-Advent LITURGICAL year, not a civil one (year_bounds = [year_start y, year_start (y+1) - 1], and [year_start] is Advent Sunday WITHIN civil year y) -- so 13 June 2011 falls inside liturgical year 2010 (Advent 2010 .. the eve of Advent 2011), the same off-by-one every other test in this file that reaches for a spring date already accounts for (the Joseph test above uses 2061 to reach March 2062). *) let days = Cal.year real_of_rite real_of_layer 2010 in let june13 = Array.to_list days |> List.find (fun d -> Date.compare d.LD.date tie_date = 0) in Alcotest.(check string) "KNOWN ARBITRARY (no rubric decides this; see this test's own header): the kernel's generic \ alphabetical tie-break observes Anthony of Padua, not Mary Mother of the Church" "anthony-of-padua-priest-and-doctor" (slug_of june13.LD.observed); let mater_ecclesiae_omitted = List.exists (fun (c, _) -> slug_of c = "mary-mother-of-the-church") june13.LD.omitted in Alcotest.(check bool) "and Mary, Mother of the Church is recorded in `omitted`, not silently dropped -- {!Colitur_kernel \ .Liturgical_day.t.omitted}'s own contract" true mater_ecclesiae_omitted; Alcotest.(check bool) "she carries no commemoration either (OF's own admit always returns [])" false (List.exists (fun (c, _) -> slug_of c = "mary-mother-of-the-church") june13.LD.commemorations) let suite = ( "Rite_of (real data: assembled Rite.t end-to-end via Calendar/Validate)", [ Alcotest.test_case "landmark years validate cleanly (W2 and the nativity gap both closed)" `Quick test_landmark_years; Alcotest.test_case "year 9999 does not raise; seasons flags the clamp, coverage stays clean" `Quick test_year_9999_does_not_raise; Alcotest.test_case "2005-2050: transfers reach a fixed point, nothing lost or duplicated" `Slow test_transfers_reach_a_fixed_point_2005_2050; Alcotest.test_case "RESOLVED (W1): St Joseph on Palm Sunday 2062 is anticipated backward to 18 March per Normae \ n.56(f), converges, and is recorded as an arrival" `Quick test_joseph_palm_sunday_2062_anticipated_backward; Alcotest.test_case "FIXED (W2): Holy Family's Normae n.35(a) 30-December fallback is now reached when Christmas \ Day is a Sunday (1583)" `Quick test_holy_family_fallback_1583_now_correct; Alcotest.test_case "KNOWN ARBITRARY pinned: Mary Mother of the Church vs Anthony of Padua tie, 2011-06-13 \ (Easter+50)" `Quick test_mater_ecclesiae_anthony_tie_2011_known_arbitrary ] )